protocol: introduce wireproto.py
authorMatt Mackall <mpm@selenic.com>
Wed, 14 Jul 2010 15:25:15 -0500
changeset 11581 4530b3307fb9
parent 11580 69248b5add46
child 11582 26c7d4fc31bf
protocol: introduce wireproto.py - add a protocol-independent dispatcher - move most of the basic commands from sshserver to wireproto - dispatch through wireproto first
mercurial/sshserver.py
mercurial/wireproto.py
--- a/mercurial/sshserver.py	Wed Jul 14 15:25:15 2010 -0500
+++ b/mercurial/sshserver.py	Wed Jul 14 15:25:15 2010 -0500
@@ -8,7 +8,7 @@
 
 from i18n import _
 from node import bin, hex
-import streamclone, util, hook, pushkey
+import streamclone, util, hook, pushkey, wireproto
 import os, sys, tempfile, urllib, copy
 
 class sshserver(object):
@@ -69,7 +69,7 @@
 
     def serve_one(self):
         cmd = self.fin.readline()[:-1]
-        if cmd:
+        if cmd and not wireproto.dispatch(self.repo, self, cmd):
             impl = getattr(self, 'do_' + cmd, None)
             if impl:
                 r = impl()
@@ -78,29 +78,6 @@
             else: self.respond("")
         return cmd != ''
 
-    def do_lookup(self):
-        key = self.getarg('key')
-        try:
-            r = hex(self.repo.lookup(key))
-            success = 1
-        except Exception, inst:
-            r = str(inst)
-            success = 0
-        return "%s %s\n" % (success, r)
-
-    def do_branchmap(self):
-        branchmap = self.repo.branchmap()
-        heads = []
-        for branch, nodes in branchmap.iteritems():
-            branchname = urllib.quote(branch)
-            branchnodes = [hex(node) for node in nodes]
-            heads.append('%s %s' % (branchname, ' '.join(branchnodes)))
-        return '\n'.join(heads)
-
-    def do_heads(self):
-        h = self.repo.heads()
-        return " ".join(map(hex, h)) + "\n"
-
     def do_hello(self):
         '''the hello command returns a set of lines describing various
         interesting things about the server, in an RFC822-like format.
@@ -128,22 +105,6 @@
         self.lock = None
         return ""
 
-    def do_branches(self):
-        nodes = self.getarg('nodes')
-        nodes = map(bin, nodes.split(" "))
-        r = []
-        for b in self.repo.branches(nodes):
-            r.append(" ".join(map(hex, b)) + "\n")
-        return "".join(r)
-
-    def do_between(self):
-        pairs = self.getarg('pairs')
-        pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
-        r = []
-        for b in self.repo.between(pairs):
-            r.append(" ".join(map(hex, b)) + "\n")
-        return "".join(r)
-
     def do_changegroup(self):
         nodes = []
         roots = self.getarg('roots')
@@ -244,15 +205,3 @@
         except streamclone.StreamException, inst:
             self.fout.write(str(inst))
             self.fout.flush()
-
-    def do_pushkey(self):
-        namespace, key, old, new = self.getargs('namespace key old new')
-        r = pushkey.push(self.repo, namespace, key, old, new)
-        return '%s\n' % int(r)
-
-    def do_listkeys(self):
-        namespace = self.getarg('namespace')
-        d = pushkey.list(self.repo, namespace).items()
-        t = '\n'.join(['%s\t%s' % (k.encode('string-escape'),
-                                   v.encode('string-escape')) for k, v in d])
-        return t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/wireproto.py	Wed Jul 14 15:25:15 2010 -0500
@@ -0,0 +1,75 @@
+# wireproto.py - generic wire protocol support functions
+#
+# Copyright 2005-2010 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 _
+from node import bin, hex
+import urllib
+import pushkey as pushkey_
+
+def dispatch(repo, proto, command):
+    if command not in commands:
+        return False
+    func, spec = commands[command]
+    args = proto.getargs(spec)
+    proto.respond(func(repo, *args))
+    return True
+
+def between(repo, pairs):
+    pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
+    r = []
+    for b in repo.between(pairs):
+        r.append(" ".join(map(hex, b)) + "\n")
+    return "".join(r)
+
+def branchmap(repo):
+    branchmap = repo.branchmap()
+    heads = []
+    for branch, nodes in branchmap.iteritems():
+        branchname = urllib.quote(branch)
+        branchnodes = [hex(node) for node in nodes]
+        heads.append('%s %s' % (branchname, ' '.join(branchnodes)))
+    return '\n'.join(heads)
+
+def branches(repo, nodes):
+    nodes = map(bin, nodes.split(" "))
+    r = []
+    for b in repo.branches(nodes):
+        r.append(" ".join(map(hex, b)) + "\n")
+    return "".join(r)
+
+def heads(repo):
+    h = repo.heads()
+    return " ".join(map(hex, h)) + "\n"
+
+def listkeys(repo, namespace):
+    d = pushkey_.list(repo, namespace).items()
+    t = '\n'.join(['%s\t%s' % (k.encode('string-escape'),
+                               v.encode('string-escape')) for k, v in d])
+    return t
+
+def lookup(repo, key):
+    try:
+        r = hex(repo.lookup(key))
+        success = 1
+    except Exception, inst:
+        r = str(inst)
+        success = 0
+    return "%s %s\n" % (success, r)
+
+def pushkey(repo, namespace, key, old, new):
+    r = pushkey_.push(repo, namespace, key, old, new)
+    return '%s\n' % int(r)
+
+commands = {
+    'between': (between, 'pairs'),
+    'branchmap': (branchmap, ''),
+    'branches': (branches, 'nodes'),
+    'heads': (heads, ''),
+    'listkeys': (listkeys, 'namespace'),
+    'lookup': (lookup, 'key'),
+    'pushkey': (pushkey, 'namespace key old new'),
+}