[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