Mercurial > public > mercurial-scm > hg-stable
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]: |