# HG changeset patch # User Nicolas Dumazet # Date 2009-12-11 06:58:09 # Node ID a3ad96ead8f027568f35f348f7f5ead10b3c8bac # Parent 8fab31727037c7a9d5e240fd81a6442b7ee09abf inotify: do not rely on stat(.hg/dirstate) to invalidate our dirstate stat() is not reliable when several events happen quickly. Which means that if two hg actions occur in the same second, stat() result will not reflect the second change. And only _one_ invalidate() call was done. Also ignore the events that occur when wlock is held, since wlock release will trigger a full rescan anyway. Fixes 17 run-tests.py --inotify tests. diff --git a/hgext/inotify/linuxserver.py b/hgext/inotify/linuxserver.py --- a/hgext/inotify/linuxserver.py +++ b/hgext/inotify/linuxserver.py @@ -170,6 +170,7 @@ class repowatcher(server.repowatcher, po server.repowatcher.__init__(self, ui, dirstate, root) self.lastevent = {} + self.dirty = False try: self.watcher = watcher.watcher() except OSError, err: @@ -214,7 +215,6 @@ class repowatcher(server.repowatcher, po def setup(self): self.ui.note(_('watching directories under %r\n') % self.wprefix) self.add_watch(self.wprefix + '.hg', inotify.IN_DELETE) - self.check_dirstate() def scan(self, topdir=''): ds = self.dirstate._map.copy() @@ -272,8 +272,6 @@ class repowatcher(server.repowatcher, po if wpath == '.hgignore': self.update_hgignore() elif wpath.startswith('.hg/'): - if wpath == '.hg/wlock': - self.check_dirstate() return self.deletefile(wpath, self.dirstate[wpath]) @@ -343,16 +341,26 @@ class repowatcher(server.repowatcher, po if wpath.startswith('.hg/') and evt.mask & inotify.IN_ISDIR: # ignore subdirectories of .hg/ (merge, patches...) continue + if wpath == ".hg/wlock": + if evt.mask & inotify.IN_DELETE: + self.dirstate.invalidate() + self.dirty = False + self.scan() + elif evt.mask & inotify.IN_CREATE: + self.dirty = True + else: + if self.dirty: + continue - if evt.mask & inotify.IN_UNMOUNT: - self.process_unmount(wpath, evt) - elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB): - self.process_modify(wpath, evt) - elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF | - inotify.IN_MOVED_FROM): - self.process_delete(wpath, evt) - elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO): - self.process_create(wpath, evt) + if evt.mask & inotify.IN_UNMOUNT: + self.process_unmount(wpath, evt) + elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB): + self.process_modify(wpath, evt) + elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF | + inotify.IN_MOVED_FROM): + self.process_delete(wpath, evt) + elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO): + self.process_create(wpath, evt) self.lastevent.clear() diff --git a/hgext/inotify/server.py b/hgext/inotify/server.py --- a/hgext/inotify/server.py +++ b/hgext/inotify/server.py @@ -281,17 +281,6 @@ class repowatcher(object): del self.statustrees[key].dir(root).files[fn] del self.tree.dir(root).files[fn] - def check_dirstate(self): - ds_info = self.dirstate_info() - if ds_info == self.ds_info: - return - self.ds_info = ds_info - if not self.ui.debugflag: - self.last_event = None - self.dirstate.invalidate() - self.handle_timeout() - self.scan() - def update_hgignore(self): # An update of the ignore file can potentially change the # states of all unknown and ignored files.