##// END OF EJS Templates
config: abort on indented non-continuation lines (issue1829)...
config: abort on indented non-continuation lines (issue1829) Previously, as soon as a continuation would be met, "cont" would stay forever set to True, but "item" was set back to "None". This caused the continuation code bits to run every time, until the next "self.get(section, item) + '\n'" which would crash.

File last commit:

r9467:4c041f1e default
r9469:7f0f882a default
Show More
client.py
159 lines | 5.3 KiB | text/x-python | PythonLexer
Bryan O'Sullivan
Add inotify extension
r6239 # client.py - inotify status client
#
# Copyright 2006, 2007, 2008 Bryan O'Sullivan <bos@serpentine.com>
# Copyright 2007, 2008 Brendan Cully <brendan@kublai.com>
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 # Copyright 2009 Nicolas Dumazet <nicdumz@gmail.com>
Bryan O'Sullivan
Add inotify extension
r6239 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Bryan O'Sullivan
Add inotify extension
r6239
Martin Geisler
i18n: import _ instead of gettext
r7225 from mercurial.i18n import _
Nicolas Dumazet
inotify: Separate query sending logic from Server starting....
r8552 import common, server
import errno, os, socket, struct
class QueryFailed(Exception): pass
def start_server(function):
"""
Decorator.
Tries to call function, if it fails, try to (re)start inotify server.
Raise QueryFailed if something went wrong
"""
def decorated_function(self, *args):
result = None
try:
return function(self, *args)
except (OSError, socket.error), err:
autostart = self.ui.configbool('inotify', 'autostart', True)
if err[0] == errno.ECONNREFUSED:
self.ui.warn(_('(found dead inotify server socket; '
'removing it)\n'))
os.unlink(self.repo.join('inotify.sock'))
if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and autostart:
self.ui.debug(_('(starting inotify server)\n'))
try:
try:
server.start(self.ui, self.repo)
except server.AlreadyStartedException, inst:
# another process may have started its own
# inotify server while this one was starting.
self.ui.debug(str(inst))
except Exception, inst:
self.ui.warn(_('could not start inotify server: '
'%s\n') % inst)
else:
try:
return function(self, *args)
except socket.error, err:
self.ui.warn(_('could not talk to new inotify '
'server: %s\n') % err[-1])
elif err[0] in (errno.ECONNREFUSED, errno.ENOENT):
# silently ignore normal errors if autostart is False
self.ui.debug(_('(inotify server not running)\n'))
else:
self.ui.warn(_('failed to contact inotify server: %s\n')
% err[-1])
self.ui.traceback()
raise QueryFailed('inotify query failed')
return decorated_function
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 class client(object):
def __init__(self, ui, repo):
self.ui = ui
self.repo = repo
self.sock = socket.socket(socket.AF_UNIX)
def _connect(self):
sockpath = self.repo.join('inotify.sock')
try:
self.sock.connect(sockpath)
except socket.error, err:
if err[0] == "AF_UNIX path too long":
sockpath = os.readlink(sockpath)
self.sock.connect(sockpath)
else:
raise
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 def _send(self, type, data):
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 """Sends protocol version number, and the data"""
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 self.sock.sendall(chr(common.version) + type + data)
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551
self.sock.shutdown(socket.SHUT_WR)
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 def _receive(self, type):
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 """
Read data, check version number, extract headers,
and returns a tuple (data descriptor, header)
Nicolas Dumazet
inotify: Separate query sending logic from Server starting....
r8552 Raises QueryFailed on error
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 """
cs = common.recvcs(self.sock)
Nicolas Dumazet
inotify: raise QueryFailed when the server crash...
r8788 try:
version = ord(cs.read(1))
except TypeError:
# empty answer, assume the server crashed
self.ui.warn(_('received empty answer from inotify server'))
raise QueryFailed('server crashed')
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 if version != common.version:
self.ui.warn(_('(inotify: received response from incompatible '
'server version %d)\n') % version)
Nicolas Dumazet
inotify: Separate query sending logic from Server starting....
r8552 raise QueryFailed('incompatible server version')
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 readtype = cs.read(4)
if readtype != type:
self.ui.warn(_('(inotify: received \'%s\' response when expecting'
' \'%s\')\n') % (readtype, type))
raise QueryFailed('wrong response type')
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 hdrfmt = common.resphdrfmts[type]
hdrsize = common.resphdrsizes[type]
try:
resphdr = struct.unpack(hdrfmt, cs.read(hdrsize))
except struct.error:
Nicolas Dumazet
inotify: Separate query sending logic from Server starting....
r8552 raise QueryFailed('unable to retrieve query response headers')
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 return cs, resphdr
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 def query(self, type, req):
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 self._connect()
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 self._send(type, req)
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 return self._receive(type)
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551
Nicolas Dumazet
inotify: Separate query sending logic from Server starting....
r8552 @start_server
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 def statusquery(self, names, match, ignored, clean, unknown=True):
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551 def genquery():
for n in names:
yield n
states = 'almrx!'
if ignored:
raise ValueError('this is insanity')
if clean: states += 'c'
if unknown: states += '?'
yield states
req = '\0'.join(genquery())
Bryan O'Sullivan
Add inotify extension
r6239
Nicolas Dumazet
inotify: change protocol so that different query types can be supported.
r8553 cs, resphdr = self.query('STAT', req)
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551
def readnames(nbytes):
if nbytes:
names = cs.read(nbytes)
if names:
return filter(match, names.split('\0'))
return []
Nicolas Dumazet
inotify: introduce debuginotify, which lists which paths are under watch
r8555 return map(readnames, resphdr)
Nicolas Dumazet
inotify: modular architecture for inotify clients...
r8551
Nicolas Dumazet
inotify: introduce debuginotify, which lists which paths are under watch
r8555 @start_server
def debugquery(self):
cs, resphdr = self.query('DBUG', '')
nbytes = resphdr[0]
names = cs.read(nbytes)
return names.split('\0')