protocol.py
88 lines
| 2.8 KiB
| text/x-python
|
PythonLexer
|
r5598 | # | ||
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> | ||||
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
|
r8225 | # This software may be used and distributed according to the terms of the | ||
|
r10263 | # GNU General Public License version 2 or any later version. | ||
|
r5598 | |||
|
r14094 | import cgi, cStringIO, zlib, sys, urllib | ||
|
r11595 | from mercurial import util, wireproto | ||
from common import HTTP_OK | ||||
|
r5963 | |||
|
r5993 | HGTYPE = 'application/mercurial-0.1' | ||
|
r11595 | |||
class webproto(object): | ||||
def __init__(self, req): | ||||
self.req = req | ||||
self.response = '' | ||||
def getargs(self, args): | ||||
|
r14093 | knownargs = self._args() | ||
|
r11595 | data = {} | ||
keys = args.split() | ||||
for k in keys: | ||||
if k == '*': | ||||
star = {} | ||||
|
r14093 | for key in knownargs.keys(): | ||
|
r13721 | if key != 'cmd' and key not in keys: | ||
|
r14093 | star[key] = knownargs[key][0] | ||
|
r11595 | data['*'] = star | ||
else: | ||||
|
r14093 | data[k] = knownargs[k][0] | ||
|
r11595 | return [data[k] for k in keys] | ||
|
r14093 | def _args(self): | ||
args = self.req.form.copy() | ||||
chunks = [] | ||||
|
r14094 | i = 1 | ||
while 1: | ||||
h = self.req.env.get('HTTP_X_HGARG_' + str(i)) | ||||
|
r14093 | if h is None: | ||
break | ||||
chunks += [h] | ||||
|
r14094 | i += 1 | ||
|
r14093 | args.update(cgi.parse_qs(''.join(chunks), keep_blank_values=True)) | ||
return args | ||||
|
r11621 | 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() | ||||
|
r11623 | def groupchunks(self, cg): | ||
|
r11595 | z = zlib.compressobj() | ||
while 1: | ||||
chunk = cg.read(4096) | ||||
if not chunk: | ||||
break | ||||
|
r11623 | yield z.compress(chunk) | ||
yield z.flush() | ||||
|
r11595 | 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) | ||||
|
r11625 | rsp = wireproto.dispatch(repo, p, cmd) | ||
|
r11626 | if isinstance(rsp, str): | ||
req.respond(HTTP_OK, HGTYPE, length=len(rsp)) | ||||
return [rsp] | ||||
elif isinstance(rsp, wireproto.streamres): | ||||
req.respond(HTTP_OK, HGTYPE) | ||||
return rsp.gen | ||||
elif isinstance(rsp, wireproto.pushres): | ||||
val = sys.stdout.getvalue() | ||||
sys.stdout, sys.stderr = p.oldio | ||||
req.respond(HTTP_OK, HGTYPE) | ||||
return ['%d\n%s' % (rsp.res, val)] | ||||
|
r12703 | elif isinstance(rsp, wireproto.pusherr): | ||
|
r12704 | # drain the incoming bundle | ||
req.drain() | ||||
|
r12703 | sys.stdout, sys.stderr = p.oldio | ||
rsp = '0\n%s\n' % rsp.res | ||||
req.respond(HTTP_OK, HGTYPE, length=len(rsp)) | ||||
return [rsp] | ||||