##// END OF EJS Templates
localrepository: use 'changectx.dirs()' in 'status()' for directory patterns...
localrepository: use 'changectx.dirs()' in 'status()' for directory patterns when pattern which does not match against any files in working context is specified, current implementation of 'localrepository.status()' decides whether warning message about it should be shown or not by 'f not in context' this works correctly for 'file pattern', but not for 'directory pattern', because 'f not in context' always returns True for directories, even if they are related to the context. this patch uses 'changectx.dirs()' to examine whether specified pattern is related to the context as a directory or not.

File last commit:

r16114:acfca07a stable
r16144:4546a851 stable
Show More
commandserver.py
238 lines | 6.6 KiB | text/x-python | PythonLexer
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 # commandserver.py - communicate with Mercurial's API over a pipe
#
# Copyright Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from i18n import _
import struct
Idan Kamara
cmdserver: restore old working dir after dispatch when we have --cwd
r14864 import sys, os
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 import dispatch, encoding, util
logfile = None
def log(*args):
if not logfile:
return
for a in args:
logfile.write(str(a))
logfile.flush()
class channeledoutput(object):
"""
Write data from in_ to out in the following format:
data length (unsigned int),
data
"""
def __init__(self, in_, out, channel):
self.in_ = in_
self.out = out
self.channel = channel
def write(self, data):
if not data:
return
self.out.write(struct.pack('>cI', self.channel, len(data)))
self.out.write(data)
self.out.flush()
def __getattr__(self, attr):
if attr in ('isatty', 'fileno'):
raise AttributeError, attr
return getattr(self.in_, attr)
class channeledinput(object):
"""
Read data from in_.
Requests for input are written to out in the following format:
channel identifier - 'I' for plain input, 'L' line based (1 byte)
how many bytes to send at most (unsigned int),
The client replies with:
data length (unsigned int), 0 meaning EOF
data
"""
maxchunksize = 4 * 1024
def __init__(self, in_, out, channel):
self.in_ = in_
self.out = out
self.channel = channel
def read(self, size=-1):
if size < 0:
# if we need to consume all the clients input, ask for 4k chunks
# so the pipe doesn't fill up risking a deadlock
size = self.maxchunksize
s = self._read(size, self.channel)
buf = s
while s:
Idan Kamara
cmdserver: fix read-loop string concatenation
r14728 s = self._read(size, self.channel)
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 buf += s
return buf
else:
return self._read(size, self.channel)
def _read(self, size, channel):
if not size:
return ''
assert size > 0
# tell the client we need at most size bytes
self.out.write(struct.pack('>cI', channel, size))
self.out.flush()
length = self.in_.read(4)
length = struct.unpack('>I', length)[0]
if not length:
return ''
else:
return self.in_.read(length)
def readline(self, size=-1):
if size < 0:
size = self.maxchunksize
s = self._read(size, 'L')
buf = s
# keep asking for more until there's either no more or
# we got a full line
while s and s[-1] != '\n':
Idan Kamara
cmdserver: fix read-loop string concatenation
r14728 s = self._read(size, 'L')
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 buf += s
return buf
else:
return self._read(size, 'L')
def __iter__(self):
return self
def next(self):
l = self.readline()
if not l:
raise StopIteration
return l
def __getattr__(self, attr):
if attr in ('isatty', 'fileno'):
raise AttributeError, attr
return getattr(self.in_, attr)
class server(object):
"""
Listens for commands on stdin, runs them and writes the output on a channel
based stream to stdout.
"""
def __init__(self, ui, repo, mode):
Idan Kamara
cmdserver: restore old working dir after dispatch when we have --cwd
r14864 self.cwd = os.getcwd()
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647
logpath = ui.config("cmdserver", "log", None)
if logpath:
global logfile
if logpath == '-':
# write log on a special 'd'ebug channel
logfile = channeledoutput(sys.stdout, sys.stdout, 'd')
else:
logfile = open(logpath, 'a')
Idan Kamara
cmdserver: take repo.baseui as our ui...
r14882 # the ui here is really the repo ui so take its baseui so we don't end up
# with its local configuration
self.ui = repo.baseui
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 self.repo = repo
Idan Kamara
cmdserver: copy repo.ui before running commands
r14750 self.repoui = repo.ui
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647
if mode == 'pipe':
self.cerr = channeledoutput(sys.stderr, sys.stdout, 'e')
self.cout = channeledoutput(sys.stdout, sys.stdout, 'o')
self.cin = channeledinput(sys.stdin, sys.stdout, 'I')
self.cresult = channeledoutput(sys.stdout, sys.stdout, 'r')
self.client = sys.stdin
else:
raise util.Abort(_('unknown mode %s') % mode)
def _read(self, size):
Idan Kamara
cmdserver: don't raise EOFError when trying to read 0 bytes from the client
r14706 if not size:
return ''
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 data = self.client.read(size)
# is the other end closed?
if not data:
raise EOFError()
return data
def runcommand(self):
""" reads a list of \0 terminated arguments, executes
and writes the return code to the result channel """
length = struct.unpack('>I', self._read(4))[0]
Idan Kamara
cmdserver, runcommand: properly handle the client sending no arguments...
r14707 if not length:
args = []
else:
args = self._read(length).split('\0')
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647
Idan Kamara
cmdserver: copy repo.ui before running commands
r14750 # copy the uis so changes (e.g. --config or --verbose) don't
# persist between requests
Idan Kamara
cmdserver: assign repo.baseui before running commands...
r14751 copiedui = self.ui.copy()
self.repo.baseui = copiedui
Idan Kamara
cmdserver: copy repo.ui before running commands
r14750 self.repo.ui = self.repo.dirstate._ui = self.repoui.copy()
Idan Kamara
cmdserver: repo.invalidate() on every runcommand...
r14939 self.repo.invalidate()
Idan Kamara
cmdserver: invalidate the dirstate when running commands (issue3271)...
r16114 self.repo.invalidatedirstate()
Idan Kamara
cmdserver: assign repo.baseui before running commands...
r14751
Idan Kamara
cmdserver: restore old working dir after dispatch when we have --cwd
r14864 req = dispatch.request(args[:], copiedui, self.repo, self.cin,
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 self.cout, self.cerr)
ret = dispatch.dispatch(req) or 0 # might return None
Idan Kamara
cmdserver: restore old working dir after dispatch when we have --cwd
r14864 # restore old cwd
if '--cwd' in args:
os.chdir(self.cwd)
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647 self.cresult.write(struct.pack('>i', int(ret)))
def getencoding(self):
""" writes the current encoding to the result channel """
self.cresult.write(encoding.encoding)
def serveone(self):
cmd = self.client.readline()[:-1]
if cmd:
handler = self.capabilities.get(cmd)
if handler:
handler(self)
else:
# clients are expected to check what commands are supported by
# looking at the servers capabilities
raise util.Abort(_('unknown command %s') % cmd)
return cmd != ''
capabilities = {'runcommand' : runcommand,
'getencoding' : getencoding}
def serve(self):
Idan Kamara
cmdserver: write the hello message as one chunk on the 'o' channel...
r14719 hellomsg = 'capabilities: ' + ' '.join(self.capabilities.keys())
hellomsg += '\n'
hellomsg += 'encoding: ' + encoding.encoding
# write the hello msg in -one- chunk
self.cout.write(hellomsg)
Idan Kamara
serve: add --cmdserver option to communicate with hg over a pipe
r14647
try:
while self.serveone():
pass
except EOFError:
# we'll get here if the client disconnected while we were reading
# its request
return 1
return 0