mercurial/hgweb/hgweb_mod.py
changeset 11595 368cd5325348
parent 11593 d054cc5c7737
child 12062 c327bfa5e831
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]: