Mercurial > hg
comparison hgext/inotify/linuxserver.py @ 10090:a3ad96ead8f0
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.
author | Nicolas Dumazet <nicdumz.commits@gmail.com> |
---|---|
date | Fri, 11 Dec 2009 15:58:09 +0900 |
parents | 8fab31727037 |
children | 0ce645cc3f20 |
comparison
equal
deleted
inserted
replaced
10089:8fab31727037 | 10090:a3ad96ead8f0 |
---|---|
168 | 168 |
169 def __init__(self, ui, dirstate, root): | 169 def __init__(self, ui, dirstate, root): |
170 server.repowatcher.__init__(self, ui, dirstate, root) | 170 server.repowatcher.__init__(self, ui, dirstate, root) |
171 | 171 |
172 self.lastevent = {} | 172 self.lastevent = {} |
173 self.dirty = False | |
173 try: | 174 try: |
174 self.watcher = watcher.watcher() | 175 self.watcher = watcher.watcher() |
175 except OSError, err: | 176 except OSError, err: |
176 raise util.Abort(_('inotify service not available: %s') % | 177 raise util.Abort(_('inotify service not available: %s') % |
177 err.strerror) | 178 err.strerror) |
212 _explain_watch_limit(self.ui, self.dirstate, self.wprefix) | 213 _explain_watch_limit(self.ui, self.dirstate, self.wprefix) |
213 | 214 |
214 def setup(self): | 215 def setup(self): |
215 self.ui.note(_('watching directories under %r\n') % self.wprefix) | 216 self.ui.note(_('watching directories under %r\n') % self.wprefix) |
216 self.add_watch(self.wprefix + '.hg', inotify.IN_DELETE) | 217 self.add_watch(self.wprefix + '.hg', inotify.IN_DELETE) |
217 self.check_dirstate() | |
218 | 218 |
219 def scan(self, topdir=''): | 219 def scan(self, topdir=''): |
220 ds = self.dirstate._map.copy() | 220 ds = self.dirstate._map.copy() |
221 self.add_watch(server.join(self.wprefix, topdir), self.mask) | 221 self.add_watch(server.join(self.wprefix, topdir), self.mask) |
222 for root, dirs, files in server.walk(self.dirstate, self.wprefix, | 222 for root, dirs, files in server.walk(self.dirstate, self.wprefix, |
270 @eventaction('d') | 270 @eventaction('d') |
271 def deleted(self, wpath): | 271 def deleted(self, wpath): |
272 if wpath == '.hgignore': | 272 if wpath == '.hgignore': |
273 self.update_hgignore() | 273 self.update_hgignore() |
274 elif wpath.startswith('.hg/'): | 274 elif wpath.startswith('.hg/'): |
275 if wpath == '.hg/wlock': | |
276 self.check_dirstate() | |
277 return | 275 return |
278 | 276 |
279 self.deletefile(wpath, self.dirstate[wpath]) | 277 self.deletefile(wpath, self.dirstate[wpath]) |
280 | 278 |
281 def process_create(self, wpath, evt): | 279 def process_create(self, wpath, evt): |
341 # paths have been normalized, wpath never ends with a '/' | 339 # paths have been normalized, wpath never ends with a '/' |
342 | 340 |
343 if wpath.startswith('.hg/') and evt.mask & inotify.IN_ISDIR: | 341 if wpath.startswith('.hg/') and evt.mask & inotify.IN_ISDIR: |
344 # ignore subdirectories of .hg/ (merge, patches...) | 342 # ignore subdirectories of .hg/ (merge, patches...) |
345 continue | 343 continue |
346 | 344 if wpath == ".hg/wlock": |
347 if evt.mask & inotify.IN_UNMOUNT: | 345 if evt.mask & inotify.IN_DELETE: |
348 self.process_unmount(wpath, evt) | 346 self.dirstate.invalidate() |
349 elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB): | 347 self.dirty = False |
350 self.process_modify(wpath, evt) | 348 self.scan() |
351 elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF | | 349 elif evt.mask & inotify.IN_CREATE: |
352 inotify.IN_MOVED_FROM): | 350 self.dirty = True |
353 self.process_delete(wpath, evt) | 351 else: |
354 elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO): | 352 if self.dirty: |
355 self.process_create(wpath, evt) | 353 continue |
354 | |
355 if evt.mask & inotify.IN_UNMOUNT: | |
356 self.process_unmount(wpath, evt) | |
357 elif evt.mask & (inotify.IN_MODIFY | inotify.IN_ATTRIB): | |
358 self.process_modify(wpath, evt) | |
359 elif evt.mask & (inotify.IN_DELETE | inotify.IN_DELETE_SELF | | |
360 inotify.IN_MOVED_FROM): | |
361 self.process_delete(wpath, evt) | |
362 elif evt.mask & (inotify.IN_CREATE | inotify.IN_MOVED_TO): | |
363 self.process_create(wpath, evt) | |
356 | 364 |
357 self.lastevent.clear() | 365 self.lastevent.clear() |
358 | 366 |
359 def handle_timeout(self): | 367 def handle_timeout(self): |
360 if not self.registered: | 368 if not self.registered: |