1 # __init__.py - inotify-based status acceleration for Linux |
|
2 # |
|
3 # Copyright 2006, 2007, 2008 Bryan O'Sullivan <bos@serpentine.com> |
|
4 # Copyright 2007, 2008 Brendan Cully <brendan@kublai.com> |
|
5 # |
|
6 # This software may be used and distributed according to the terms of the |
|
7 # GNU General Public License version 2 or any later version. |
|
8 |
|
9 '''accelerate status report using Linux's inotify service''' |
|
10 |
|
11 # todo: socket permissions |
|
12 |
|
13 from mercurial.i18n import _ |
|
14 from mercurial import util |
|
15 import server |
|
16 from client import client, QueryFailed |
|
17 |
|
18 testedwith = 'internal' |
|
19 |
|
20 def serve(ui, repo, **opts): |
|
21 '''start an inotify server for this repository''' |
|
22 server.start(ui, repo.dirstate, repo.root, opts) |
|
23 |
|
24 def debuginotify(ui, repo, **opts): |
|
25 '''debugging information for inotify extension |
|
26 |
|
27 Prints the list of directories being watched by the inotify server. |
|
28 ''' |
|
29 cli = client(ui, repo) |
|
30 response = cli.debugquery() |
|
31 |
|
32 ui.write(_('directories being watched:\n')) |
|
33 for path in response: |
|
34 ui.write((' %s/\n') % path) |
|
35 |
|
36 def reposetup(ui, repo): |
|
37 if not util.safehasattr(repo, 'dirstate'): |
|
38 return |
|
39 |
|
40 class inotifydirstate(repo.dirstate.__class__): |
|
41 |
|
42 # We'll set this to false after an unsuccessful attempt so that |
|
43 # next calls of status() within the same instance don't try again |
|
44 # to start an inotify server if it won't start. |
|
45 _inotifyon = True |
|
46 |
|
47 def status(self, match, subrepos, ignored, clean, unknown): |
|
48 files = match.files() |
|
49 if '.' in files: |
|
50 files = [] |
|
51 if (self._inotifyon and not ignored and not subrepos and |
|
52 not self._dirty): |
|
53 cli = client(ui, repo) |
|
54 try: |
|
55 result = cli.statusquery(files, match, False, |
|
56 clean, unknown) |
|
57 except QueryFailed, instr: |
|
58 ui.debug(str(instr)) |
|
59 # don't retry within the same hg instance |
|
60 inotifydirstate._inotifyon = False |
|
61 pass |
|
62 else: |
|
63 if ui.config('inotify', 'debug'): |
|
64 r2 = super(inotifydirstate, self).status( |
|
65 match, [], False, clean, unknown) |
|
66 for c, a, b in zip('LMARDUIC', result, r2): |
|
67 for f in a: |
|
68 if f not in b: |
|
69 ui.warn('*** inotify: %s +%s\n' % (c, f)) |
|
70 for f in b: |
|
71 if f not in a: |
|
72 ui.warn('*** inotify: %s -%s\n' % (c, f)) |
|
73 result = r2 |
|
74 return result |
|
75 return super(inotifydirstate, self).status( |
|
76 match, subrepos, ignored, clean, unknown) |
|
77 |
|
78 repo.dirstate.__class__ = inotifydirstate |
|
79 |
|
80 cmdtable = { |
|
81 'debuginotify': |
|
82 (debuginotify, [], ('hg debuginotify')), |
|
83 '^inserve': |
|
84 (serve, |
|
85 [('d', 'daemon', None, _('run server in background')), |
|
86 ('', 'daemon-pipefds', '', |
|
87 _('used internally by daemon mode'), _('NUM')), |
|
88 ('t', 'idle-timeout', '', |
|
89 _('minutes to sit idle before exiting'), _('NUM')), |
|
90 ('', 'pid-file', '', |
|
91 _('name of file to write process ID to'), _('FILE'))], |
|
92 _('hg inserve [OPTION]...')), |
|
93 } |
|