diff mercurial/hgweb/protocol.py @ 11595:368cd5325348

protocol: move hgweb protocol support back into protocol.py - introduce iscmd - simplify error handling - remove unneeded imports
author Matt Mackall <mpm@selenic.com>
date Thu, 15 Jul 2010 15:05:04 -0500
parents 67863f9d805f
children 83070a9cd526
line wrap: on
line diff
--- 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