protocol: move hgweb protocol support back into protocol.py
- introduce iscmd
- simplify error handling
- remove unneeded imports
--- 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