__init__.py
125 lines
| 4.9 KiB
| text/x-python
|
PythonLexer
Bryan O'Sullivan
|
r6239 | # __init__.py - inotify-based status acceleration for Linux | ||
# | ||||
# Copyright 2006, 2007, 2008 Bryan O'Sullivan <bos@serpentine.com> | ||||
# Copyright 2007, 2008 Brendan Cully <brendan@kublai.com> | ||||
# | ||||
# This software may be used and distributed according to the terms | ||||
# of the GNU General Public License, incorporated herein by reference. | ||||
'''inotify-based status acceleration for Linux systems | ||||
''' | ||||
# todo: socket permissions | ||||
Martin Geisler
|
r7225 | from mercurial.i18n import _ | ||
Bryan O'Sullivan
|
r6239 | from mercurial import cmdutil, util | ||
import client, errno, os, server, socket | ||||
from weakref import proxy | ||||
def serve(ui, repo, **opts): | ||||
'''start an inotify server for this repository''' | ||||
timeout = opts.get('timeout') | ||||
if timeout: | ||||
timeout = float(timeout) * 1e3 | ||||
class service: | ||||
def init(self): | ||||
Benoit Boissinot
|
r6995 | try: | ||
self.master = server.Master(ui, repo, timeout) | ||||
except server.AlreadyStartedException, inst: | ||||
raise util.Abort(str(inst)) | ||||
Bryan O'Sullivan
|
r6239 | |||
def run(self): | ||||
try: | ||||
self.master.run() | ||||
finally: | ||||
self.master.shutdown() | ||||
service = service() | ||||
cmdutil.service(opts, initfn=service.init, runfn=service.run) | ||||
def reposetup(ui, repo): | ||||
Brendan Cully
|
r7522 | if not hasattr(repo, 'dirstate'): | ||
Bryan O'Sullivan
|
r6239 | return | ||
# XXX: weakref until hg stops relying on __del__ | ||||
repo = proxy(repo) | ||||
class inotifydirstate(repo.dirstate.__class__): | ||||
# Set to True if we're the inotify server, so we don't attempt | ||||
# to recurse. | ||||
inotifyserver = False | ||||
Matt Mackall
|
r6753 | def status(self, match, ignored, clean, unknown=True): | ||
Matt Mackall
|
r6603 | files = match.files() | ||
Brendan Cully
|
r7393 | if '.' in files: | ||
Dirkjan Ochtman
|
r7434 | files = [] | ||
Bryan O'Sullivan
|
r6239 | try: | ||
Matt Mackall
|
r6753 | if not ignored and not self.inotifyserver: | ||
Bryan O'Sullivan
|
r6239 | result = client.query(ui, repo, files, match, False, | ||
Matt Mackall
|
r6753 | clean, unknown) | ||
Nicolas Dumazet
|
r8069 | if result and ui.config('inotify', 'debug'): | ||
Matt Mackall
|
r7219 | r2 = super(inotifydirstate, self).status( | ||
match, False, clean, unknown) | ||||
for c,a,b in zip('LMARDUIC', result, r2): | ||||
for f in a: | ||||
if f not in b: | ||||
ui.warn('*** inotify: %s +%s\n' % (c, f)) | ||||
for f in b: | ||||
if f not in a: | ||||
Benoit Boissinot
|
r7304 | ui.warn('*** inotify: %s -%s\n' % (c, f)) | ||
Matt Mackall
|
r7219 | result = r2 | ||
Bryan O'Sullivan
|
r6239 | if result is not None: | ||
return result | ||||
Benoit Boissinot
|
r6997 | except (OSError, socket.error), err: | ||
Brendan Cully
|
r7452 | autostart = ui.configbool('inotify', 'autostart', True) | ||
Bryan O'Sullivan
|
r6239 | if err[0] == errno.ECONNREFUSED: | ||
ui.warn(_('(found dead inotify server socket; ' | ||||
'removing it)\n')) | ||||
os.unlink(repo.join('inotify.sock')) | ||||
Brendan Cully
|
r7452 | if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and autostart: | ||
Bryan O'Sullivan
|
r6239 | ui.debug(_('(starting inotify server)\n')) | ||
try: | ||||
Thomas Arendsen Hein
|
r7329 | try: | ||
server.start(ui, repo) | ||||
except server.AlreadyStartedException, inst: | ||||
# another process may have started its own | ||||
# inotify server while this one was starting. | ||||
ui.debug(str(inst)) | ||||
Bryan O'Sullivan
|
r6239 | except Exception, inst: | ||
ui.warn(_('could not start inotify server: ' | ||||
'%s\n') % inst) | ||||
Nicolas Dumazet
|
r8068 | else: | ||
# server is started, send query again | ||||
Bryan O'Sullivan
|
r6239 | try: | ||
Nicolas Dumazet
|
r8068 | return client.query(ui, repo, files, match, | ||
Matt Mackall
|
r6753 | ignored, clean, unknown) | ||
Bryan O'Sullivan
|
r6239 | except socket.error, err: | ||
ui.warn(_('could not talk to new inotify ' | ||||
Benoit Boissinot
|
r6996 | 'server: %s\n') % err[-1]) | ||
Brendan Cully
|
r7452 | elif err[0] in (errno.ECONNREFUSED, errno.ENOENT): | ||
# silently ignore normal errors if autostart is False | ||||
ui.debug(_('(inotify server not running)\n')) | ||||
Benoit Boissinot
|
r6996 | else: | ||
ui.warn(_('failed to contact inotify server: %s\n') | ||||
% err[-1]) | ||||
Matt Mackall
|
r8206 | ui.traceback() | ||
Benoit Boissinot
|
r6996 | # replace by old status function | ||
self.status = super(inotifydirstate, self).status | ||||
Bryan O'Sullivan
|
r6239 | |||
return super(inotifydirstate, self).status( | ||||
Matt Mackall
|
r6753 | match, ignored, clean, unknown) | ||
Bryan O'Sullivan
|
r6239 | |||
repo.dirstate.__class__ = inotifydirstate | ||||
cmdtable = { | ||||
'^inserve': | ||||
(serve, | ||||
[('d', 'daemon', None, _('run server in background')), | ||||
('', 'daemon-pipefds', '', _('used internally by daemon mode')), | ||||
('t', 'idle-timeout', '', _('minutes to sit idle before exiting')), | ||||
('', 'pid-file', '', _('name of file to write process ID to'))], | ||||
_('hg inserve [OPT]...')), | ||||
} | ||||