6239
|
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
|
|
7 # of the GNU General Public License, incorporated herein by reference.
|
|
8
|
|
9 '''inotify-based status acceleration for Linux systems
|
|
10 '''
|
|
11
|
|
12 # todo: socket permissions
|
|
13
|
|
14 from mercurial.i18n import gettext as _
|
|
15 from mercurial import cmdutil, util
|
|
16 import client, errno, os, server, socket
|
|
17 from weakref import proxy
|
|
18
|
|
19 def serve(ui, repo, **opts):
|
|
20 '''start an inotify server for this repository'''
|
|
21 timeout = opts.get('timeout')
|
|
22 if timeout:
|
|
23 timeout = float(timeout) * 1e3
|
|
24
|
|
25 class service:
|
|
26 def init(self):
|
|
27 self.master = server.Master(ui, repo, timeout)
|
|
28
|
|
29 def run(self):
|
|
30 try:
|
|
31 self.master.run()
|
|
32 finally:
|
|
33 self.master.shutdown()
|
|
34
|
|
35 service = service()
|
|
36 cmdutil.service(opts, initfn=service.init, runfn=service.run)
|
|
37
|
|
38 def reposetup(ui, repo):
|
|
39 if not repo.local():
|
|
40 return
|
|
41
|
|
42 # XXX: weakref until hg stops relying on __del__
|
|
43 repo = proxy(repo)
|
|
44
|
|
45 class inotifydirstate(repo.dirstate.__class__):
|
|
46 # Set to True if we're the inotify server, so we don't attempt
|
|
47 # to recurse.
|
|
48 inotifyserver = False
|
|
49
|
|
50 def status(self, files, match, list_ignored, list_clean,
|
|
51 list_unknown=True):
|
|
52 try:
|
|
53 if not list_ignored and not self.inotifyserver:
|
|
54 result = client.query(ui, repo, files, match, False,
|
|
55 list_clean, list_unknown)
|
|
56 if result is not None:
|
|
57 return result
|
|
58 except socket.error, err:
|
|
59 if err[0] == errno.ECONNREFUSED:
|
|
60 ui.warn(_('(found dead inotify server socket; '
|
|
61 'removing it)\n'))
|
|
62 os.unlink(repo.join('inotify.sock'))
|
|
63 elif err[0] != errno.ENOENT:
|
|
64 raise
|
|
65 if ui.configbool('inotify', 'autostart'):
|
|
66 query = None
|
|
67 ui.debug(_('(starting inotify server)\n'))
|
|
68 try:
|
|
69 server.start(ui, repo)
|
|
70 query = client.query
|
|
71 except server.AlreadyStartedException, inst:
|
|
72 # another process may have started its own
|
|
73 # inotify server while this one was starting.
|
|
74 ui.debug(str(inst))
|
|
75 query = client.query
|
|
76 except Exception, inst:
|
|
77 ui.warn(_('could not start inotify server: '
|
|
78 '%s\n') % inst)
|
|
79 ui.print_exc()
|
|
80
|
|
81 if query:
|
|
82 try:
|
|
83 return query(ui, repo, files or [], match,
|
|
84 list_ignored, list_clean, list_unknown)
|
|
85 except socket.error, err:
|
|
86 ui.warn(_('could not talk to new inotify '
|
|
87 'server: %s\n') % err[1])
|
|
88 ui.print_exc()
|
|
89
|
|
90 return super(inotifydirstate, self).status(
|
|
91 files, match or util.always, list_ignored, list_clean,
|
|
92 list_unknown)
|
|
93
|
|
94 repo.dirstate.__class__ = inotifydirstate
|
|
95
|
|
96 cmdtable = {
|
|
97 '^inserve':
|
|
98 (serve,
|
|
99 [('d', 'daemon', None, _('run server in background')),
|
|
100 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
|
|
101 ('t', 'idle-timeout', '', _('minutes to sit idle before exiting')),
|
|
102 ('', 'pid-file', '', _('name of file to write process ID to'))],
|
|
103 _('hg inserve [OPT]...')),
|
|
104 }
|