[PATCH 1 of 1] add basic support for ssh wire protocol version 2
Sune Foldager
cryo at cyanite.org
Sat Mar 13 09:06:27 CST 2010
# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1268491347 -3600
# Node ID 3a19af28ee6e0152a33fb3209721521bcb42f692
# Parent 85e81d9bfb7ae7792be4030a5a1033f8ae4c99e9
add basic support for ssh wire protocol version 2
diff --git a/mercurial/sshrepo.py b/mercurial/sshrepo.py
--- a/mercurial/sshrepo.py
+++ b/mercurial/sshrepo.py
@@ -23,6 +23,7 @@
class sshrepository(repo.repository):
def __init__(self, ui, path, create=0):
self._url = path
+ self._protocol = 1
self.ui = ui
m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
@@ -86,6 +87,9 @@
if l.startswith("capabilities:"):
self.capabilities.update(l[:-1].split(":")[1].split())
break
+ p = self.capable('protocol')
+ if p:
+ self._protocol = int(p)
def readerr(self):
while 1:
@@ -116,12 +120,13 @@
def do_cmd(self, cmd, **args):
self.ui.debug("sending %s command\n" % cmd)
+ if self._protocol >= 2:
+ cmd = "%s %d" % (cmd, len(args))
self.pipeo.write("%s\n" % cmd)
for k, v in args.iteritems():
self.pipeo.write("%s %d\n" % (k, len(v)))
self.pipeo.write(v)
self.pipeo.flush()
-
return self.pipei
def call(self, cmd, **args):
diff --git a/mercurial/sshserver.py b/mercurial/sshserver.py
--- a/mercurial/sshserver.py
+++ b/mercurial/sshserver.py
@@ -13,7 +13,7 @@
class sshserver(object):
- caps = 'unbundle lookup changegroupsubset branchmap'.split()
+ caps = 'unbundle lookup changegroupsubset branchmap protocol=2'.split()
def __init__(self, ui, repo):
self.ui = ui
@@ -21,6 +21,7 @@
self.lock = None
self.fin = sys.stdin
self.fout = sys.stdout
+ self.args = None
hook.redirect(True)
sys.stdout = sys.stderr
@@ -29,12 +30,20 @@
util.set_binary(self.fin)
util.set_binary(self.fout)
- def getarg(self):
+ def _getarg(self):
argline = self.fin.readline()[:-1]
arg, l = argline.split()
val = self.fin.read(int(l))
return arg, val
+ def _getargs(self, argc):
+ self.args = dict(self._getarg() for i in xrange(argc))
+
+ def getargs(self, argc):
+ if not self.args:
+ self._getargs(argc)
+ return self.args
+
def respond(self, v):
self.fout.write("%d\n" % len(v))
self.fout.write(v)
@@ -51,18 +60,25 @@
def serve_one(self):
cmd = self.fin.readline()[:-1]
- if cmd:
- impl = getattr(self, 'do_' + cmd, None)
- if impl:
- impl()
- else: self.respond("")
- return cmd != ''
+ if not cmd:
+ return False
+ c = cmd.split(' ')
+ if len(c) > 1: # protocol v2
+ cmd, argc, self.options = c[0], c[1], c[2:]
+ self._getargs(int(argc))
+ else:
+ self.args, self.options = None, []
+ impl = getattr(self, 'do_' + cmd, None)
+ if impl:
+ impl()
+ else:
+ self.respond("")
+ return True
def do_lookup(self):
- arg, key = self.getarg()
- assert arg == 'key'
+ args = self.getargs(1)
try:
- r = hex(self.repo.lookup(key))
+ r = hex(self.repo.lookup(args['key']))
success = 1
except Exception, inst:
r = str(inst)
@@ -110,25 +126,24 @@
self.respond("")
def do_branches(self):
- arg, nodes = self.getarg()
- nodes = map(bin, nodes.split(" "))
+ args = self.getargs(1)
+ nodes = map(bin, args['nodes'].split(" "))
r = []
for b in self.repo.branches(nodes):
r.append(" ".join(map(hex, b)) + "\n")
self.respond("".join(r))
def do_between(self):
- arg, pairs = self.getarg()
- pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
+ args = self.getargs(1)
+ pairs = [map(bin, p.split("-")) for p in args['pairs'].split(" ")]
r = []
for b in self.repo.between(pairs):
r.append(" ".join(map(hex, b)) + "\n")
self.respond("".join(r))
def do_changegroup(self):
- nodes = []
- arg, roots = self.getarg()
- nodes = map(bin, roots.split(" "))
+ args = self.getargs(1)
+ nodes = map(bin, args['roots'].split(" "))
cg = self.repo.changegroup(nodes, 'serve')
while True:
@@ -140,9 +155,9 @@
self.fout.flush()
def do_changegroupsubset(self):
- argmap = dict([self.getarg(), self.getarg()])
- bases = [bin(n) for n in argmap['bases'].split(' ')]
- heads = [bin(n) for n in argmap['heads'].split(' ')]
+ args = self.getargs(2)
+ bases = [bin(n) for n in args['bases'].split(' ')]
+ heads = [bin(n) for n in args['heads'].split(' ')]
cg = self.repo.changegroupsubset(bases, heads, 'serve')
while True:
@@ -169,7 +184,7 @@
return 'remote:ssh:' + client
def do_unbundle(self):
- their_heads = self.getarg()[1].split()
+ their_heads = self.getargs(1)['heads'].split()
def check_heads():
heads = map(hex, self.repo.heads())
diff --git a/tests/test-ssh b/tests/test-ssh
--- a/tests/test-ssh
+++ b/tests/test-ssh
@@ -109,3 +109,6 @@
cd ..
cat dummylog
+
+echo "# test protocol 2 format"
+printf 'hello 2\nfoo 2\n.\nbar 4\n...\n\n' | hg -R local serve --stdio
diff --git a/tests/test-ssh.out b/tests/test-ssh.out
--- a/tests/test-ssh.out
+++ b/tests/test-ssh.out
@@ -105,3 +105,6 @@
changegroup-in-remote hook: HG_NODE=572896fe480d7581849806ee402175c49cb20037 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
Got arguments 1:user at dummy 2:hg -R remote serve --stdio
changegroup-in-remote hook: HG_NODE=ac7448082955a0b2ff5cb4512c1e061c779bbc79 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
+# test protocol 2 format
+82
+capabilities: unbundle lookup changegroupsubset branchmap protocol=2 stream=65537
More information about the Mercurial-devel
mailing list