protocol: move hgweb protocol support back into protocol.py
authorMatt Mackall <mpm@selenic.com>
Thu, 15 Jul 2010 15:05:04 -0500
changeset 11595 368cd5325348
parent 11594 67863f9d805f
child 11596 47ca289a3a08
protocol: move hgweb protocol support back into protocol.py - introduce iscmd - simplify error handling - remove unneeded imports
mercurial/hgweb/hgweb_mod.py
mercurial/hgweb/protocol.py
--- a/mercurial/hgweb/hgweb_mod.py	Thu Jul 15 13:56:52 2010 -0500
+++ b/mercurial/hgweb/hgweb_mod.py	Thu Jul 15 15:05:04 2010 -0500
@@ -6,8 +6,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import os, zlib, sys, cStringIO, urllib
-from mercurial import ui, hg, hook, error, encoding, templater, wireproto, util
+import os, sys, urllib
+from mercurial import ui, hg, hook, error, encoding, templater, util
 from common import get_mtime, ErrorResponse, permhooks
 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
 from request import wsgirequest
@@ -22,63 +22,6 @@
     'pushkey': 'push',
 }
 
-HGTYPE = 'application/mercurial-0.1'
-class webproto(object):
-    def __init__(self, req):
-        self.req = req
-        self.response = ''
-    def getargs(self, args):
-        data = {}
-        keys = args.split()
-        for k in keys:
-            if k == '*':
-                star = {}
-                for key in self.req.form.keys():
-                    if key not in keys:
-                        star[key] = self.req.form[key][0]
-                data['*'] = star
-            else:
-                data[k] = self.req.form[k][0]
-        return [data[k] for k in keys]
-    def sendchangegroup(self, cg):
-        self.req.respond(HTTP_OK, HGTYPE)
-        z = zlib.compressobj()
-        while 1:
-            chunk = cg.read(4096)
-            if not chunk:
-                break
-            self.req.write(z.compress(chunk))
-        self.req.write(z.flush())
-    def sendstream(self, source):
-        self.req.respond(HTTP_OK, HGTYPE)
-        for chunk in source:
-            self.req.write(chunk)
-    def respond(self, s):
-        self.req.respond(HTTP_OK, HGTYPE, length=len(s))
-        self.response = s
-    def getfile(self, fp):
-        length = int(self.req.env['CONTENT_LENGTH'])
-        for s in util.filechunkiter(self.req, limit=length):
-            fp.write(s)
-    def redirect(self):
-        self.oldio = sys.stdout, sys.stderr
-        sys.stderr = sys.stdout = cStringIO.StringIO()
-    def respondpush(self, ret):
-        val = sys.stdout.getvalue()
-        sys.stdout, sys.stderr = self.oldio
-        self.req.respond(HTTP_OK, HGTYPE)
-        self.response = '%d\n%s' % (ret, val)
-    def _client(self):
-        return 'remote:%s:%s:%s' % (
-            self.req.env.get('wsgi.url_scheme') or 'http',
-            urllib.quote(self.req.env.get('REMOTE_HOST', '')),
-            urllib.quote(self.req.env.get('REMOTE_USER', '')))
-
-def callproto(repo, req, cmd):
-    p = webproto(req)
-    r = wireproto.dispatch(repo, p, cmd)
-    yield p.response
-
 class hgweb(object):
     def __init__(self, repo, name=None, baseui=None):
         if isinstance(repo, str):
@@ -169,26 +112,18 @@
         # and the clients always use the old URL structure
 
         cmd = req.form.get('cmd', [''])[0]
-        if cmd and cmd in protocol.__all__:
+        if protocol.iscmd(cmd):
             if query:
                 raise ErrorResponse(HTTP_NOT_FOUND)
-            try:
-                if cmd in perms:
-                    try:
-                        self.check_perm(req, perms[cmd])
-                    except ErrorResponse, inst:
-                        if cmd == 'unbundle':
-                            req.drain()
-                        raise
-                if cmd in wireproto.commands:
-                    return callproto(self.repo, req, cmd)
-                method = getattr(protocol, cmd)
-                return method(self.repo, req)
-            except ErrorResponse, inst:
-                req.respond(inst, protocol.HGTYPE)
-                if not inst.message:
-                    return []
-                return '0\n%s\n' % inst.message,
+            if cmd in perms:
+                try:
+                    self.check_perm(req, perms[cmd])
+                except ErrorResponse, inst:
+                    if cmd == 'unbundle':
+                        req.drain()
+                    req.respond(inst, protocol.HGTYPE)
+                    return '0\n%s\n' % inst.message
+            return protocol.call(self.repo, req, cmd)
 
         # translate user-visible url structure to internal structure
 
--- a/mercurial/hgweb/protocol.py	Thu Jul 15 13:56:52 2010 -0500
+++ b/mercurial/hgweb/protocol.py	Thu Jul 15 15:05:04 2010 -0500
@@ -5,19 +5,67 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import cStringIO, zlib, tempfile, errno, os, sys, urllib, copy
-from mercurial import util, streamclone, pushkey
-from mercurial.node import bin, hex
-from mercurial import changegroup as changegroupmod
-from common import ErrorResponse, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
-
-# __all__ is populated with the allowed commands. Be sure to add to it if
-# you're adding a new command, or the new command won't work.
-
-__all__ = [
-   'lookup', 'heads', 'branches', 'between', 'changegroup',
-   'changegroupsubset', 'capabilities', 'unbundle', 'stream_out',
-   'branchmap', 'pushkey', 'listkeys'
-]
+import cStringIO, zlib, sys, urllib
+from mercurial import util, wireproto
+from common import HTTP_OK
 
 HGTYPE = 'application/mercurial-0.1'
+
+class webproto(object):
+    def __init__(self, req):
+        self.req = req
+        self.response = ''
+    def getargs(self, args):
+        data = {}
+        keys = args.split()
+        for k in keys:
+            if k == '*':
+                star = {}
+                for key in self.req.form.keys():
+                    if key not in keys:
+                        star[key] = self.req.form[key][0]
+                data['*'] = star
+            else:
+                data[k] = self.req.form[k][0]
+        return [data[k] for k in keys]
+    def sendchangegroup(self, cg):
+        self.req.respond(HTTP_OK, HGTYPE)
+        z = zlib.compressobj()
+        while 1:
+            chunk = cg.read(4096)
+            if not chunk:
+                break
+            self.req.write(z.compress(chunk))
+        self.req.write(z.flush())
+    def sendstream(self, source):
+        self.req.respond(HTTP_OK, HGTYPE)
+        for chunk in source:
+            self.req.write(chunk)
+    def respond(self, s):
+        self.req.respond(HTTP_OK, HGTYPE, length=len(s))
+        self.response = s
+    def getfile(self, fp):
+        length = int(self.req.env['CONTENT_LENGTH'])
+        for s in util.filechunkiter(self.req, limit=length):
+            fp.write(s)
+    def redirect(self):
+        self.oldio = sys.stdout, sys.stderr
+        sys.stderr = sys.stdout = cStringIO.StringIO()
+    def respondpush(self, ret):
+        val = sys.stdout.getvalue()
+        sys.stdout, sys.stderr = self.oldio
+        self.req.respond(HTTP_OK, HGTYPE)
+        self.response = '%d\n%s' % (ret, val)
+    def _client(self):
+        return 'remote:%s:%s:%s' % (
+            self.req.env.get('wsgi.url_scheme') or 'http',
+            urllib.quote(self.req.env.get('REMOTE_HOST', '')),
+            urllib.quote(self.req.env.get('REMOTE_USER', '')))
+
+def iscmd(cmd):
+    return cmd in wireproto.commands
+
+def call(repo, req, cmd):
+    p = webproto(req)
+    r = wireproto.dispatch(repo, p, cmd)
+    yield p.response