[PATCH 1 of 1] sshserver: add varargs capability

Sune Foldager cryo at cyanite.org
Tue Feb 9 05:37:24 CST 2010


# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1265715038 -3600
# Node ID 858b863d83543293e210468ec3e967985dd8c4c6
# Parent  d216fa04e48a2aeeae138b8d4995ff25fbd771c2
sshserver: add varargs capability

The SSH wire protocol is fairly rigid, and allows only a fixed number of
arguments for its commands. This capability signals that commands in the form
command#argc are accepted, where argc is a non-negative integer (represented as
a decimal number) denoting the number of arguments the command has.

Future extensions to wire commands can use this to determine if certain
optional arguments were sent. Existing commands will work as before regardless
of the new command format being used or not.

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._varargs = False
         self.ui = ui
 
         m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
@@ -86,6 +87,7 @@
             if l.startswith("capabilities:"):
                 self.capabilities.update(l[:-1].split(":")[1].split())
                 break
+        self._varargs = 'varargs' in self.capabilities
 
     def readerr(self):
         while 1:
@@ -116,6 +118,8 @@
 
     def do_cmd(self, cmd, **args):
         self.ui.debug("sending %s command\n" % cmd)
+        if self._varargs:
+            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)))
diff --git a/mercurial/sshserver.py b/mercurial/sshserver.py
--- a/mercurial/sshserver.py
+++ b/mercurial/sshserver.py
@@ -13,12 +13,13 @@
 
 class sshserver(object):
 
-    caps = 'unbundle lookup changegroupsubset branchmap'.split()
+    caps = 'unbundle lookup changegroupsubset branchmap varargs'.split()
 
     def __init__(self, ui, repo):
         self.ui = ui
         self.repo = repo
         self.lock = None
+        self.argv = None
         self.fin = sys.stdin
         self.fout = sys.stdout
 
@@ -30,6 +31,8 @@
         util.set_binary(self.fout)
 
     def getarg(self):
+        if self.argv:
+            return self.argv.popitem()
         argline = self.fin.readline()[:-1]
         arg, l = argline.split()
         val = self.fin.read(int(l))
@@ -52,6 +55,11 @@
     def serve_one(self):
         cmd = self.fin.readline()[:-1]
         if cmd:
+            self.argv = None
+            cmdargc = cmd.split('#', 1)
+            if len(cmdargc) == 2:
+                cmd, argc = cmdargc
+                self.argv = dict(self.getarg() for i in xrange(int(argc)))
             impl = getattr(self, 'do_' + cmd, None)
             if impl:
                 impl()


More information about the Mercurial-devel mailing list