wireproto: fix handling of '*' args for HTTP and SSH
authorPeter Arrenbrecht <peter.arrenbrecht@gmail.com>
Tue, 22 Mar 2011 07:38:32 +0100
changeset 13721 3458c15ab2f0
parent 13720 9c4e04fe267e
child 13722 f4a85acef50c
wireproto: fix handling of '*' args for HTTP and SSH
mercurial/hgweb/protocol.py
mercurial/sshrepo.py
mercurial/sshserver.py
mercurial/wireproto.py
tests/test-wireproto.t
--- a/mercurial/hgweb/protocol.py	Tue Mar 22 07:38:32 2011 +0100
+++ b/mercurial/hgweb/protocol.py	Tue Mar 22 07:38:32 2011 +0100
@@ -22,7 +22,7 @@
             if k == '*':
                 star = {}
                 for key in self.req.form.keys():
-                    if key not in keys:
+                    if key != 'cmd' and key not in keys:
                         star[key] = self.req.form[key][0]
                 data['*'] = star
             else:
--- a/mercurial/sshrepo.py	Tue Mar 22 07:38:32 2011 +0100
+++ b/mercurial/sshrepo.py	Tue Mar 22 07:38:32 2011 +0100
@@ -119,9 +119,24 @@
     def _callstream(self, cmd, **args):
         self.ui.debug("sending %s command\n" % cmd)
         self.pipeo.write("%s\n" % cmd)
-        for k, v in sorted(args.iteritems()):
+        _func, names = wireproto.commands[cmd]
+        keys = names.split()
+        wireargs = {}
+        for k in keys:
+            if k == '*':
+                wireargs['*'] = args
+                break
+            else:
+                wireargs[k] = args[k]
+                del args[k]
+        for k, v in sorted(wireargs.iteritems()):
             self.pipeo.write("%s %d\n" % (k, len(v)))
-            self.pipeo.write(v)
+            if isinstance(v, dict):
+                for dk, dv in v.iteritems():
+                    self.pipeo.write("%s %d\n" % (dk, len(dv)))
+                    self.pipeo.write(dv)
+            else:
+                self.pipeo.write(v)
         self.pipeo.flush()
 
         return self.pipei
--- a/mercurial/sshserver.py	Tue Mar 22 07:38:32 2011 +0100
+++ b/mercurial/sshserver.py	Tue Mar 22 07:38:32 2011 +0100
@@ -30,17 +30,18 @@
         for n in xrange(len(keys)):
             argline = self.fin.readline()[:-1]
             arg, l = argline.split()
-            val = self.fin.read(int(l))
             if arg not in keys:
                 raise util.Abort("unexpected parameter %r" % arg)
             if arg == '*':
                 star = {}
-                for n in xrange(int(l)):
+                for k in xrange(int(l)):
+                    argline = self.fin.readline()[:-1]
                     arg, l = argline.split()
                     val = self.fin.read(int(l))
                     star[arg] = val
                 data['*'] = star
             else:
+                val = self.fin.read(int(l))
                 data[arg] = val
         return [data[k] for k in keys]
 
--- a/mercurial/wireproto.py	Tue Mar 22 07:38:32 2011 +0100
+++ b/mercurial/wireproto.py	Tue Mar 22 07:38:32 2011 +0100
@@ -161,6 +161,17 @@
     args = proto.getargs(spec)
     return func(repo, proto, *args)
 
+def options(cmd, keys, others):
+    opts = {}
+    for k in keys:
+        if k in others:
+            opts[k] = others[k]
+            del others[k]
+    if others:
+        sys.stderr.write("abort: %s got unexpected arguments %s\n"
+                         % (cmd, ",".join(others)))
+    return opts
+
 def between(repo, proto, pairs):
     pairs = [decodelist(p, '-') for p in pairs.split(" ")]
     r = []
@@ -208,8 +219,10 @@
     cg = repo.changegroupsubset(bases, heads, 'serve')
     return streamres(proto.groupchunks(cg))
 
-def debugwireargs(repo, proto, one, two):
-    return repo.debugwireargs(one, two)
+def debugwireargs(repo, proto, one, two, others):
+    # only accept optional args from the known set
+    opts = options('debugwireargs', ['three', 'four'], others)
+    return repo.debugwireargs(one, two, **opts)
 
 def heads(repo, proto):
     h = repo.heads()
@@ -355,7 +368,7 @@
     'capabilities': (capabilities, ''),
     'changegroup': (changegroup, 'roots'),
     'changegroupsubset': (changegroupsubset, 'bases heads'),
-    'debugwireargs': (debugwireargs, 'one two'),
+    'debugwireargs': (debugwireargs, 'one two *'),
     'heads': (heads, ''),
     'hello': (hello, ''),
     'listkeys': (listkeys, 'namespace'),
--- a/tests/test-wireproto.t	Tue Mar 22 07:38:32 2011 +0100
+++ b/tests/test-wireproto.t	Tue Mar 22 07:38:32 2011 +0100
@@ -7,6 +7,10 @@
 
 Local:
 
+  $ hg debugwireargs repo eins zwei --three drei --four vier
+  eins zwei drei vier
+  $ hg debugwireargs repo eins zwei --four vier
+  eins zwei None vier
   $ hg debugwireargs repo eins zwei
   eins zwei None None
 
@@ -15,10 +19,20 @@
   $ hg serve -R repo -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
   $ cat hg1.pid >> $DAEMON_PIDS
 
+  $ hg debugwireargs http://localhost:$HGPORT/ un deux trois quatre
+  un deux trois quatre
+  $ hg debugwireargs http://localhost:$HGPORT/ eins zwei --four vier
+  eins zwei None vier
   $ hg debugwireargs http://localhost:$HGPORT/ eins zwei
   eins zwei None None
   $ cat access.log
   * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * - - [*] "GET /?cmd=debugwireargs&four=quatre&one=un&three=trois&two=deux HTTP/1.1" 200 - (glob)
+  * - - [*] "GET /?cmd=debugwireargs&four=quatre&one=un&three=trois&two=deux HTTP/1.1" 200 - (glob)
+  * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * - - [*] "GET /?cmd=debugwireargs&four=vier&one=eins&two=zwei HTTP/1.1" 200 - (glob)
+  * - - [*] "GET /?cmd=debugwireargs&four=vier&one=eins&two=zwei HTTP/1.1" 200 - (glob)
+  * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
   * - - [*] "GET /?cmd=debugwireargs&one=eins&two=zwei HTTP/1.1" 200 - (glob)
   * - - [*] "GET /?cmd=debugwireargs&one=eins&two=zwei HTTP/1.1" 200 - (glob)
 
@@ -37,6 +51,10 @@
   > sys.exit(bool(r))
   > EOF
 
+  $ hg debugwireargs --ssh "python ./dummyssh" ssh://user@dummy/repo uno due tre quattro
+  uno due tre quattro
+  $ hg debugwireargs --ssh "python ./dummyssh" ssh://user@dummy/repo eins zwei --four vier
+  eins zwei None vier
   $ hg debugwireargs --ssh "python ./dummyssh" ssh://user@dummy/repo eins zwei
   eins zwei None None