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: