view mercurial/hgweb/request.py @ 6858:8f256bf98219

Add support for multiple possible bisect results (issue1228, issue1182) The real reason for both issue is that bisect can not handle cases where there are multiple possibilities for the result. Example (from issue1228): rev 0 -> good rev 1 -> skipped rev 2 -> skipped rev 3 -> skipped rev 4 -> bad Note that this patch does not only fix the reported Assertion Error but also the problem of a non converging bisect: hg init for i in `seq 3`; do echo $i > $i; hg add $i; hg ci -m$i; done hg bisect -b 2 hg bisect -g 0 hg bisect -s From this state on, you can: a) mark as bad forever (non converging!) b) mark as good to get an inconsistent state c) skip for the Assertion Error Minor description and code edits by pmezard.
author Bernhard Leiner <bleiner@gmail.com>
date Sat, 02 Aug 2008 22:10:10 +0200
parents e75aab656f46
children 0dbb56e90a71
line wrap: on
line source

# hgweb/request.py - An http request from either CGI or the standalone server.
#
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

import socket, cgi, errno
from common import ErrorResponse, statusmessage

class wsgirequest(object):
    def __init__(self, wsgienv, start_response):
        version = wsgienv['wsgi.version']
        if (version < (1, 0)) or (version >= (2, 0)):
            raise RuntimeError("Unknown and unsupported WSGI version %d.%d"
                               % version)
        self.inp = wsgienv['wsgi.input']
        self.err = wsgienv['wsgi.errors']
        self.threaded = wsgienv['wsgi.multithread']
        self.multiprocess = wsgienv['wsgi.multiprocess']
        self.run_once = wsgienv['wsgi.run_once']
        self.env = wsgienv
        self.form = cgi.parse(self.inp, self.env, keep_blank_values=1)
        self._start_response = start_response
        self.server_write = None
        self.headers = []

    def __iter__(self):
        return iter([])

    def read(self, count=-1):
        return self.inp.read(count)

    def respond(self, status, type=None, filename=None, length=0):
        if self._start_response is not None:

            self.httphdr(type, filename, length)
            if not self.headers:
                raise RuntimeError("request.write called before headers sent")

            for k, v in self.headers:
                if not isinstance(v, str):
                    raise TypeError('header value must be string: %r' % v)

            if isinstance(status, ErrorResponse):
                status = statusmessage(status.code)
            elif status == 200:
                status = '200 Script output follows'
            elif isinstance(status, int):
                status = statusmessage(status)

            self.server_write = self._start_response(status, self.headers)
            self._start_response = None
            self.headers = []

    def write(self, thing):
        if hasattr(thing, "__iter__"):
            for part in thing:
                self.write(part)
        else:
            thing = str(thing)
            try:
                self.server_write(thing)
            except socket.error, inst:
                if inst[0] != errno.ECONNRESET:
                    raise

    def writelines(self, lines):
        for line in lines:
            self.write(line)

    def flush(self):
        return None

    def close(self):
        return None

    def header(self, headers=[('Content-Type','text/html')]):
        self.headers.extend(headers)

    def httphdr(self, type=None, filename=None, length=0, headers={}):
        headers = headers.items()
        if type is not None:
            headers.append(('Content-Type', type))
        if filename:
            filename = (filename.split('/')[-1]
                        .replace('\\', '\\\\').replace('"', '\\"'))
            headers.append(('Content-Disposition',
                            'inline; filename="%s"' % filename))
        if length:
            headers.append(('Content-Length', str(length)))
        self.header(headers)

def wsgiapplication(app_maker):
    '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir()
    can and should now be used as a WSGI application.'''
    application = app_maker()
    def run_wsgi(env, respond):
        return application(env, respond)
    return run_wsgi