コード例 #1
0
ファイル: hgwebinit.py プロジェクト: j3hyde/hgwebinit
def hgwebinit_run_wsgi_wrapper(orig, obj, req):
    """Handles hgwebdir_mod requests, looking for pushes to non-existent repos.
    If one is detected, the user is first authorized and then prompted to init.
    Following that we simply hand the request off ot the next handler in the
    chain - typically hgwebdir_mod itself."""
    try:
        tmpl = obj.templater(req)
        ctype = tmpl("mimetype", encoding=encoding.encoding)
        ctype = templater.stringify(ctype)

        obj.refresh()

        # Do our stuff...
        if should_create_repo(obj, req):
            # Ah, but is this user allowed to create repos?
            if create_allowed(obj.ui, req):
                virtual = req.env.get("PATH_INFO", "").strip("/")

                paths = {}
                for name, value in obj.ui.configitems("paths"):
                    paths[name] = value

                local = local_path_for_repo(virtual, paths)

                if obj.ui.configbool("web", "implicit_init", False):
                    # Go ahead and init if implicit creation is enabled
                    hg.repository(obj.ui, path=local, create=True)
                else:
                    # Find out what the client wants.
                    # Only the capabilities and init commands are supported.
                    cmd = req.form.get("cmd", [""])[0]
                    if protocol.iscmd(cmd) and cmd in ("capabilities", "init"):
                        repo = emptyrepo(baseui=obj.ui)
                        return protocol.call(repo, req, cmd)

                # force refresh
                obj.lastrefresh = 0

    except ErrorResponse, err:
        req.respond(err, ctype)
        return tmpl("error", error=err.message or "")
コード例 #2
0
ファイル: backend.py プロジェクト: PMR2/pmr2.mercurial
    def process_request(self, request):
        """
        Process the request object and returns output.
        """

        protocol = mercurial.hgweb.protocol
        request.stdin.seek(0)
        env = dict(request.environ)

        # the request object *should* be WSGI compliant as Mercurial
        # supports it, but we have kind of completely wrap around it so
        # might as well emulate it if it's missing.

        if 'wsgi.version' not in env:
            # 'REQUEST_URI' is missing but seems to be unused
            env['REMOTE_HOST'] = env['REMOTE_ADDR']
            # emulate wsgi environment
            env['wsgi.version'] = (1, 0)
            # environment variable has https
            env['wsgi.url_scheme'] = \
                request.base.split(':')[0]  # self.url_scheme
            env['wsgi.input'] = request.stdin # self.rfile
            env['wsgi.errors'] = StringIO() #_error_logger(self)
            env['wsgi.multithread'] = True  # XXX guess
            env['wsgi.multiprocess'] = True  # same as above
            env['wsgi.run_once'] = True

        headers_set = []
        headers_sent = []

        def write(data):
            if not headers_set:
                raise AssertionError("write() before start_response()")

            elif not headers_sent:
                # Before the first output, send the stored headers
                status, response_headers = headers_sent[:] = headers_set
                status, code = status.split(' ', 1)
                request.response.setStatus(status, code)
                for header in response_headers:
                    # let zope deal with the header.
                    request.response.setHeader(*header)

            out.write(data)
            out.flush()

        def start_response(status, response_headers, exc_info=None):
            if exc_info:
                try:
                    if headers_sent:
                        # Re-raise original exception if headers sent
                        raise exc_info[0], exc_info[1], exc_info[2]
                finally:
                    exc_info = None     # avoid dangling circular ref
            elif headers_set:
                raise AssertionError("Headers already set!")

            headers_set[:] = [status, response_headers]
            return write

        # XXX this is a hgweb object already.  While run_wsgi has what
        # we need, Zope/repoze/Plone handles some of the request stuff
        # already, so we just skip some of the parsing steps.

        out = StringIO()
        req = wsgirequest(env, start_response)

        self.refresh()

        req.url = req.env['SCRIPT_NAME']
        if not req.url.endswith('/'):
            req.url += '/'
        if 'REPO_NAME' in req.env:
            req.url += req.env['REPO_NAME'] + '/'

        if 'PATH_INFO' in req.env:
            parts = req.env['PATH_INFO'].strip('/').split('/')
            repo_parts = req.env.get('REPO_NAME', '').split('/')
            if parts[:len(repo_parts)] == repo_parts:
                parts = parts[len(repo_parts):]
            query = '/'.join(parts)
        else:
            query = req.env['QUERY_STRING'].split('&', 1)[0]
            query = query.split(';', 1)[0]

        # process this if it's a protocol request
        # protocol bits don't need to create any URLs
        # and the clients always use the old URL structure

        cmd = req.form.get('cmd', [''])[0]
        if cmd:
            if not protocol.iscmd(cmd):
                raise UnsupportedCommandError('%s is unsupported' % cmd)
            # XXX not sure why?
            #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
                content = protocol.call(self.repo, req, cmd)
            except ErrorResponse, inst:
                req.respond(inst, protocol.HGTYPE)
                # XXX doing write here because the other methods expect
                # output.
                write('0\n')
                if not inst.message:
                    return []
                write('%s\n' % inst.message,)
                return out.getvalue()