##// END OF EJS Templates
inotify: server: use dirstate instead of repo
Nicolas Dumazet -
r9350:b789ea38 default
parent child Browse files
Show More
@@ -34,13 +34,11 b' def split(path):'
34 34
35 35 walk_ignored_errors = (errno.ENOENT, errno.ENAMETOOLONG)
36 36
37 def walkrepodirs(repo):
37 def walkrepodirs(dirstate, absroot):
38 38 '''Iterate over all subdirectories of this repo.
39 39 Exclude the .hg directory, any nested repos, and ignored dirs.'''
40 rootslash = repo.root + os.sep
41
42 40 def walkit(dirname, top):
43 fullpath = rootslash + dirname
41 fullpath = join(absroot, dirname)
44 42 try:
45 43 for name, kind in osutil.listdir(fullpath):
46 44 if kind == stat.S_IFDIR:
@@ -49,7 +47,7 b' def walkrepodirs(repo):'
49 47 return
50 48 else:
51 49 d = join(dirname, name)
52 if repo.dirstate._ignore(d):
50 if dirstate._ignore(d):
53 51 continue
54 52 for subdir in walkit(d, False):
55 53 yield subdir
@@ -60,18 +58,16 b' def walkrepodirs(repo):'
60 58
61 59 return walkit('', True)
62 60
63 def walk(repo, root):
61 def walk(dirstate, absroot, root):
64 62 '''Like os.walk, but only yields regular files.'''
65 63
66 64 # This function is critical to performance during startup.
67 65
68 rootslash = repo.root + os.sep
69
70 66 def walkit(root, reporoot):
71 67 files, dirs = [], []
72 68
73 69 try:
74 fullpath = rootslash + root
70 fullpath = join(absroot, root)
75 71 for name, kind in osutil.listdir(fullpath):
76 72 if kind == stat.S_IFDIR:
77 73 if name == '.hg':
@@ -80,7 +76,7 b' def walk(repo, root):'
80 76 else:
81 77 dirs.append(name)
82 78 path = join(root, name)
83 if repo.dirstate._ignore(path):
79 if dirstate._ignore(path):
84 80 continue
85 81 for result in walkit(path, False):
86 82 yield result
@@ -98,7 +94,7 b' def walk(repo, root):'
98 94
99 95 return walkit(root, root == '')
100 96
101 def _explain_watch_limit(ui, repo):
97 def _explain_watch_limit(ui, dirstate, rootabs):
102 98 path = '/proc/sys/fs/inotify/max_user_watches'
103 99 try:
104 100 limit = int(file(path).read())
@@ -112,7 +108,7 b' def _explain_watch_limit(ui, repo):'
112 108 ui.warn(_('*** this limit is too low to watch every '
113 109 'directory in this repository\n'))
114 110 ui.warn(_('*** counting directories: '))
115 ndirs = len(list(walkrepodirs(repo)))
111 ndirs = len(list(walkrepodirs(dirstate, rootabs)))
116 112 ui.warn(_('found %d\n') % ndirs)
117 113 newlimit = min(limit, 1024)
118 114 while newlimit < ((limit + ndirs) * 1.1):
@@ -121,7 +117,7 b' def _explain_watch_limit(ui, repo):'
121 117 (limit, newlimit))
122 118 ui.warn(_('*** echo %d > %s\n') % (newlimit, path))
123 119 raise util.Abort(_('cannot watch %s until inotify watch limit is raised')
124 % repo.root)
120 % rootabs)
125 121
126 122 class pollable(object):
127 123 """
@@ -309,10 +305,11 b' class repowatcher(pollable):'
309 305 inotify.IN_UNMOUNT |
310 306 0)
311 307
312 def __init__(self, ui, repo):
308 def __init__(self, ui, dirstate, root):
313 309 self.ui = ui
314 self.repo = repo
315 self.wprefix = join(repo.root, '')
310 self.dirstate = dirstate
311
312 self.wprefix = join(root, '')
316 313 self.prefixlen = len(self.wprefix)
317 314 try:
318 315 self.watcher = watcher.watcher()
@@ -352,7 +349,7 b' class repowatcher(pollable):'
352 349
353 350 def dirstate_info(self):
354 351 try:
355 st = os.lstat(self.repo.join('dirstate'))
352 st = os.lstat(self.wprefix + '.hg/dirstate')
356 353 return st.st_mtime, st.st_ino
357 354 except OSError, err:
358 355 if err.errno != errno.ENOENT:
@@ -372,16 +369,16 b' class repowatcher(pollable):'
372 369 return
373 370 if err.errno != errno.ENOSPC:
374 371 raise
375 _explain_watch_limit(self.ui, self.repo)
372 _explain_watch_limit(self.ui, self.dirstate, self.wprefix)
376 373
377 374 def setup(self):
378 375 self.ui.note(_('watching directories under %r\n') % self.wprefix)
379 self.add_watch(self.repo.path, inotify.IN_DELETE)
376 self.add_watch(self.wprefix + '.hg', inotify.IN_DELETE)
380 377 self.check_dirstate()
381 378
382 379 def filestatus(self, fn, st):
383 380 try:
384 type_, mode, size, time = self.repo.dirstate._map[fn][:4]
381 type_, mode, size, time = self.dirstate._map[fn][:4]
385 382 except KeyError:
386 383 type_ = '?'
387 384 if type_ == 'n':
@@ -393,7 +390,7 b' class repowatcher(pollable):'
393 390 if time != int(st_mtime):
394 391 return 'l'
395 392 return 'n'
396 if type_ == '?' and self.repo.dirstate._ignore(fn):
393 if type_ == '?' and self.dirstate._ignore(fn):
397 394 return 'i'
398 395 return type_
399 396
@@ -458,7 +455,7 b' class repowatcher(pollable):'
458 455 # may have vanished from the dirstate; we must clean them up.
459 456 nuke = []
460 457 for wfn, ignore in self.statustrees[key].walk(key):
461 if wfn not in self.repo.dirstate:
458 if wfn not in self.dirstate:
462 459 nuke.append(wfn)
463 460 for wfn in nuke:
464 461 root, fn = split(wfn)
@@ -466,9 +463,9 b' class repowatcher(pollable):'
466 463 del self.tree.dir(root).files[fn]
467 464
468 465 def scan(self, topdir=''):
469 ds = self.repo.dirstate._map.copy()
466 ds = self.dirstate._map.copy()
470 467 self.add_watch(join(self.wprefix, topdir), self.mask)
471 for root, dirs, files in walk(self.repo, topdir):
468 for root, dirs, files in walk(self.dirstate, self.wprefix, topdir):
472 469 for d in dirs:
473 470 self.add_watch(join(root, d), self.mask)
474 471 wroot = root[self.prefixlen:]
@@ -500,7 +497,7 b' class repowatcher(pollable):'
500 497 if not self.ui.debugflag:
501 498 self.last_event = None
502 499 self.ui.note(_('%s dirstate reload\n') % self.event_time())
503 self.repo.dirstate.invalidate()
500 self.dirstate.invalidate()
504 501 self.handle_timeout()
505 502 self.scan()
506 503 self.ui.note(_('%s end dirstate reload\n') % self.event_time())
@@ -516,8 +513,8 b' class repowatcher(pollable):'
516 513 # But it's easier to do nothing than to open that can of
517 514 # worms.
518 515
519 if '_ignore' in self.repo.dirstate.__dict__:
520 delattr(self.repo.dirstate, '_ignore')
516 if '_ignore' in self.dirstate.__dict__:
517 delattr(self.dirstate, '_ignore')
521 518 self.ui.note(_('rescanning due to .hgignore change\n'))
522 519 self.handle_timeout()
523 520 self.scan()
@@ -560,7 +557,7 b' class repowatcher(pollable):'
560 557 try:
561 558 st = self.stat(wpath)
562 559 if stat.S_ISREG(st[0]):
563 if self.repo.dirstate[wpath] in 'lmn':
560 if self.dirstate[wpath] in 'lmn':
564 561 self.updatefile(wpath, st)
565 562 except OSError:
566 563 pass
@@ -574,7 +571,7 b' class repowatcher(pollable):'
574 571 self.check_dirstate()
575 572 return
576 573
577 self.deletefile(wpath, self.repo.dirstate[wpath])
574 self.deletefile(wpath, self.dirstate[wpath])
578 575
579 576 def process_create(self, wpath, evt):
580 577 if self.ui.debugflag:
@@ -678,12 +675,11 b' class server(pollable):'
678 675 """
679 676 Listens for client queries on unix socket inotify.sock
680 677 """
681 def __init__(self, ui, repo, repowatcher, timeout):
678 def __init__(self, ui, root, repowatcher, timeout):
682 679 self.ui = ui
683 self.repo = repo
684 680 self.repowatcher = repowatcher
685 681 self.sock = socket.socket(socket.AF_UNIX)
686 self.sockpath = self.repo.join('inotify.sock')
682 self.sockpath = join(root, '.hg/inotify.sock')
687 683 self.realsockpath = None
688 684 try:
689 685 self.sock.bind(self.sockpath)
@@ -813,9 +809,8 b' class server(pollable):'
813 809 class master(object):
814 810 def __init__(self, ui, repo, timeout=None):
815 811 self.ui = ui
816 self.repo = repo
817 self.repowatcher = repowatcher(ui, repo)
818 self.server = server(ui, repo, self.repowatcher, timeout)
812 self.repowatcher = repowatcher(ui, repo.dirstate, repo.root)
813 self.server = server(ui, repo.root, self.repowatcher, timeout)
819 814
820 815 def shutdown(self):
821 816 for obj in pollable.instances.itervalues():
General Comments 0
You need to be logged in to leave comments. Login now