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