comparison mercurial/hgweb/hgweb_mod.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 d054cc5c7737
children c327bfa5e831
comparison
equal deleted inserted replaced
11594:67863f9d805f 11595:368cd5325348
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> 4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 # 5 #
6 # This software may be used and distributed according to the terms of the 6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version. 7 # GNU General Public License version 2 or any later version.
8 8
9 import os, zlib, sys, cStringIO, urllib 9 import os, sys, urllib
10 from mercurial import ui, hg, hook, error, encoding, templater, wireproto, util 10 from mercurial import ui, hg, hook, error, encoding, templater, util
11 from common import get_mtime, ErrorResponse, permhooks 11 from common import get_mtime, ErrorResponse, permhooks
12 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR 12 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
13 from request import wsgirequest 13 from request import wsgirequest
14 import webcommands, protocol, webutil 14 import webcommands, protocol, webutil
15 15
19 'stream_out': 'pull', 19 'stream_out': 'pull',
20 'listkeys': 'pull', 20 'listkeys': 'pull',
21 'unbundle': 'push', 21 'unbundle': 'push',
22 'pushkey': 'push', 22 'pushkey': 'push',
23 } 23 }
24
25 HGTYPE = 'application/mercurial-0.1'
26 class webproto(object):
27 def __init__(self, req):
28 self.req = req
29 self.response = ''
30 def getargs(self, args):
31 data = {}
32 keys = args.split()
33 for k in keys:
34 if k == '*':
35 star = {}
36 for key in self.req.form.keys():
37 if key not in keys:
38 star[key] = self.req.form[key][0]
39 data['*'] = star
40 else:
41 data[k] = self.req.form[k][0]
42 return [data[k] for k in keys]
43 def sendchangegroup(self, cg):
44 self.req.respond(HTTP_OK, HGTYPE)
45 z = zlib.compressobj()
46 while 1:
47 chunk = cg.read(4096)
48 if not chunk:
49 break
50 self.req.write(z.compress(chunk))
51 self.req.write(z.flush())
52 def sendstream(self, source):
53 self.req.respond(HTTP_OK, HGTYPE)
54 for chunk in source:
55 self.req.write(chunk)
56 def respond(self, s):
57 self.req.respond(HTTP_OK, HGTYPE, length=len(s))
58 self.response = s
59 def getfile(self, fp):
60 length = int(self.req.env['CONTENT_LENGTH'])
61 for s in util.filechunkiter(self.req, limit=length):
62 fp.write(s)
63 def redirect(self):
64 self.oldio = sys.stdout, sys.stderr
65 sys.stderr = sys.stdout = cStringIO.StringIO()
66 def respondpush(self, ret):
67 val = sys.stdout.getvalue()
68 sys.stdout, sys.stderr = self.oldio
69 self.req.respond(HTTP_OK, HGTYPE)
70 self.response = '%d\n%s' % (ret, val)
71 def _client(self):
72 return 'remote:%s:%s:%s' % (
73 self.req.env.get('wsgi.url_scheme') or 'http',
74 urllib.quote(self.req.env.get('REMOTE_HOST', '')),
75 urllib.quote(self.req.env.get('REMOTE_USER', '')))
76
77 def callproto(repo, req, cmd):
78 p = webproto(req)
79 r = wireproto.dispatch(repo, p, cmd)
80 yield p.response
81 24
82 class hgweb(object): 25 class hgweb(object):
83 def __init__(self, repo, name=None, baseui=None): 26 def __init__(self, repo, name=None, baseui=None):
84 if isinstance(repo, str): 27 if isinstance(repo, str):
85 if baseui: 28 if baseui:
167 # process this if it's a protocol request 110 # process this if it's a protocol request
168 # protocol bits don't need to create any URLs 111 # protocol bits don't need to create any URLs
169 # and the clients always use the old URL structure 112 # and the clients always use the old URL structure
170 113
171 cmd = req.form.get('cmd', [''])[0] 114 cmd = req.form.get('cmd', [''])[0]
172 if cmd and cmd in protocol.__all__: 115 if protocol.iscmd(cmd):
173 if query: 116 if query:
174 raise ErrorResponse(HTTP_NOT_FOUND) 117 raise ErrorResponse(HTTP_NOT_FOUND)
175 try: 118 if cmd in perms:
176 if cmd in perms: 119 try:
177 try: 120 self.check_perm(req, perms[cmd])
178 self.check_perm(req, perms[cmd]) 121 except ErrorResponse, inst:
179 except ErrorResponse, inst: 122 if cmd == 'unbundle':
180 if cmd == 'unbundle': 123 req.drain()
181 req.drain() 124 req.respond(inst, protocol.HGTYPE)
182 raise 125 return '0\n%s\n' % inst.message
183 if cmd in wireproto.commands: 126 return protocol.call(self.repo, req, cmd)
184 return callproto(self.repo, req, cmd)
185 method = getattr(protocol, cmd)
186 return method(self.repo, req)
187 except ErrorResponse, inst:
188 req.respond(inst, protocol.HGTYPE)
189 if not inst.message:
190 return []
191 return '0\n%s\n' % inst.message,
192 127
193 # translate user-visible url structure to internal structure 128 # translate user-visible url structure to internal structure
194 129
195 args = query.split('/', 2) 130 args = query.split('/', 2)
196 if 'cmd' not in req.form and args and args[0]: 131 if 'cmd' not in req.form and args and args[0]: