|
|
# __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 version 2 or any later version.
|
|
|
|
|
|
'''accelerate status report using Linux's inotify service'''
|
|
|
|
|
|
# todo: socket permissions
|
|
|
|
|
|
from mercurial.i18n import _
|
|
|
from mercurial import util
|
|
|
import server
|
|
|
from client import client, QueryFailed
|
|
|
|
|
|
testedwith = 'internal'
|
|
|
|
|
|
def serve(ui, repo, **opts):
|
|
|
'''start an inotify server for this repository'''
|
|
|
server.start(ui, repo.dirstate, repo.root, opts)
|
|
|
|
|
|
def debuginotify(ui, repo, **opts):
|
|
|
'''debugging information for inotify extension
|
|
|
|
|
|
Prints the list of directories being watched by the inotify server.
|
|
|
'''
|
|
|
cli = client(ui, repo)
|
|
|
response = cli.debugquery()
|
|
|
|
|
|
ui.write(_('directories being watched:\n'))
|
|
|
for path in response:
|
|
|
ui.write((' %s/\n') % path)
|
|
|
|
|
|
def reposetup(ui, repo):
|
|
|
if not util.safehasattr(repo, 'dirstate'):
|
|
|
return
|
|
|
|
|
|
class inotifydirstate(repo.dirstate.__class__):
|
|
|
|
|
|
# We'll set this to false after an unsuccessful attempt so that
|
|
|
# next calls of status() within the same instance don't try again
|
|
|
# to start an inotify server if it won't start.
|
|
|
_inotifyon = True
|
|
|
|
|
|
def status(self, match, subrepos, ignored, clean, unknown):
|
|
|
files = match.files()
|
|
|
if '.' in files:
|
|
|
files = []
|
|
|
if (self._inotifyon and not ignored and not subrepos and
|
|
|
not self._dirty):
|
|
|
cli = client(ui, repo)
|
|
|
try:
|
|
|
result = cli.statusquery(files, match, False,
|
|
|
clean, unknown)
|
|
|
except QueryFailed, instr:
|
|
|
ui.debug(str(instr))
|
|
|
# don't retry within the same hg instance
|
|
|
inotifydirstate._inotifyon = False
|
|
|
pass
|
|
|
else:
|
|
|
if ui.config('inotify', 'debug'):
|
|
|
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:
|
|
|
ui.warn('*** inotify: %s -%s\n' % (c, f))
|
|
|
result = r2
|
|
|
return result
|
|
|
return super(inotifydirstate, self).status(
|
|
|
match, subrepos, ignored, clean, unknown)
|
|
|
|
|
|
repo.dirstate.__class__ = inotifydirstate
|
|
|
|
|
|
cmdtable = {
|
|
|
'debuginotify':
|
|
|
(debuginotify, [], ('hg debuginotify')),
|
|
|
'^inserve':
|
|
|
(serve,
|
|
|
[('d', 'daemon', None, _('run server in background')),
|
|
|
('', 'daemon-pipefds', '',
|
|
|
_('used internally by daemon mode'), _('NUM')),
|
|
|
('t', 'idle-timeout', '',
|
|
|
_('minutes to sit idle before exiting'), _('NUM')),
|
|
|
('', 'pid-file', '',
|
|
|
_('name of file to write process ID to'), _('FILE'))],
|
|
|
_('hg inserve [OPTION]...')),
|
|
|
}
|
|
|
|