Mercurial > hg
changeset 2355:eb08fb4d41e1
Splitting up hgweb so it's easier to change.
author | Eric Hopper <hopper@omnifarious.org> |
---|---|
date | Wed, 31 May 2006 08:03:29 -0700 |
parents | 61909dfb316d |
children | 2db831b33e8f |
files | mercurial/commands.py mercurial/hgweb/__init__.py mercurial/hgweb/request.py mercurial/hgweb/server.py |
diffstat | 4 files changed, 197 insertions(+), 158 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/commands.py Mon May 29 16:46:31 2006 +0800 +++ b/mercurial/commands.py Wed May 31 08:03:29 2006 -0700 @@ -2542,7 +2542,7 @@ os._exit(0) try: - httpd = hgweb.create_server(ui, repo) + httpd = hgweb.create_server(ui, repo, hgweb.hgwebdir, hgweb.hgweb) except socket.error, inst: raise util.Abort(_('cannot start server: ') + inst.args[1])
--- a/mercurial/hgweb/__init__.py Mon May 29 16:46:31 2006 +0800 +++ b/mercurial/hgweb/__init__.py Wed May 31 08:03:29 2006 -0700 @@ -10,23 +10,12 @@ import mimetypes from mercurial.demandload import demandload demandload(globals(), "time re socket zlib errno ConfigParser tempfile") -demandload(globals(), "StringIO BaseHTTPServer SocketServer urllib") demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,templater") +demandload(globals(), "mercurial.hgweb.request:hgrequest") +demandload(globals(), "mercurial.hgweb.server:create_server") from mercurial.node import * from mercurial.i18n import gettext as _ -def splitURI(uri): - """ Return path and query splited from uri - - Just like CGI environment, the path is unquoted, the query is - not. - """ - if '?' in uri: - path, query = uri.split('?', 1) - else: - path, query = uri, '' - return urllib.unquote(path), query - def up(p): if p[0] != "/": p = "/" + p @@ -69,39 +58,6 @@ # illegal fname or unreadable file return "" -class hgrequest(object): - def __init__(self, inp=None, out=None, env=None): - self.inp = inp or sys.stdin - self.out = out or sys.stdout - self.env = env or os.environ - self.form = cgi.parse(self.inp, self.env, keep_blank_values=1) - - def write(self, *things): - for thing in things: - if hasattr(thing, "__iter__"): - for part in thing: - self.write(part) - else: - try: - self.out.write(str(thing)) - except socket.error, inst: - if inst[0] != errno.ECONNRESET: - raise - - def header(self, headers=[('Content-type','text/html')]): - for header in headers: - self.out.write("%s: %s\r\n" % header) - self.out.write("\r\n") - - def httphdr(self, type, file="", size=0): - - headers = [('Content-type', type)] - if file: - headers.append(('Content-disposition', 'attachment; filename=%s' % file)) - if size > 0: - headers.append(('Content-length', str(size))) - self.header(headers) - class hgweb(object): def __init__(self, repo, name=None): if type(repo) == type(""): @@ -893,117 +849,6 @@ else: req.write(self.t("error")) -def create_server(ui, repo): - use_threads = True - - def openlog(opt, default): - if opt and opt != '-': - return open(opt, 'w') - return default - - address = ui.config("web", "address", "") - port = int(ui.config("web", "port", 8000)) - use_ipv6 = ui.configbool("web", "ipv6") - webdir_conf = ui.config("web", "webdir_conf") - accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout) - errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr) - - if use_threads: - try: - from threading import activeCount - except ImportError: - use_threads = False - - if use_threads: - _mixin = SocketServer.ThreadingMixIn - else: - if hasattr(os, "fork"): - _mixin = SocketServer.ForkingMixIn - else: - class _mixin: pass - - class MercurialHTTPServer(_mixin, BaseHTTPServer.HTTPServer): - pass - - class IPv6HTTPServer(MercurialHTTPServer): - address_family = getattr(socket, 'AF_INET6', None) - - def __init__(self, *args, **kwargs): - if self.address_family is None: - raise hg.RepoError(_('IPv6 not available on this system')) - BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs) - - class hgwebhandler(BaseHTTPServer.BaseHTTPRequestHandler): - - def log_error(self, format, *args): - errorlog.write("%s - - [%s] %s\n" % (self.address_string(), - self.log_date_time_string(), - format % args)) - - def log_message(self, format, *args): - accesslog.write("%s - - [%s] %s\n" % (self.address_string(), - self.log_date_time_string(), - format % args)) - - def do_POST(self): - try: - self.do_hgweb() - except socket.error, inst: - if inst[0] != errno.EPIPE: - raise - - def do_GET(self): - self.do_POST() - - def do_hgweb(self): - path_info, query = splitURI(self.path) - - env = {} - env['GATEWAY_INTERFACE'] = 'CGI/1.1' - env['REQUEST_METHOD'] = self.command - env['SERVER_NAME'] = self.server.server_name - env['SERVER_PORT'] = str(self.server.server_port) - env['REQUEST_URI'] = "/" - env['PATH_INFO'] = path_info - if query: - env['QUERY_STRING'] = query - host = self.address_string() - if host != self.client_address[0]: - env['REMOTE_HOST'] = host - env['REMOTE_ADDR'] = self.client_address[0] - - if self.headers.typeheader is None: - env['CONTENT_TYPE'] = self.headers.type - else: - env['CONTENT_TYPE'] = self.headers.typeheader - length = self.headers.getheader('content-length') - if length: - env['CONTENT_LENGTH'] = length - accept = [] - for line in self.headers.getallmatchingheaders('accept'): - if line[:1] in "\t\n\r ": - accept.append(line.strip()) - else: - accept = accept + line[7:].split(',') - env['HTTP_ACCEPT'] = ','.join(accept) - - req = hgrequest(self.rfile, self.wfile, env) - self.send_response(200, "Script output follows") - - if webdir_conf: - hgwebobj = hgwebdir(webdir_conf) - elif repo is not None: - hgwebobj = hgweb(repo.__class__(repo.ui, repo.origroot)) - else: - raise hg.RepoError(_('no repo found')) - hgwebobj.run(req) - - - if use_ipv6: - return IPv6HTTPServer((address, port), hgwebhandler) - else: - return MercurialHTTPServer((address, port), hgwebhandler) - # This is a stopgap class hgwebdir(object): def __init__(self, config):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/hgweb/request.py Wed May 31 08:03:29 2006 -0700 @@ -0,0 +1,44 @@ +# hgweb.py - web interface to a mercurial repository +# +# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> +# Copyright 2005 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. + +from mercurial.demandload import demandload +demandload(globals(), "socket sys cgi os") +from mercurial.i18n import gettext as _ + +class hgrequest(object): + def __init__(self, inp=None, out=None, env=None): + self.inp = inp or sys.stdin + self.out = out or sys.stdout + self.env = env or os.environ + self.form = cgi.parse(self.inp, self.env, keep_blank_values=1) + + def write(self, *things): + for thing in things: + if hasattr(thing, "__iter__"): + for part in thing: + self.write(part) + else: + try: + self.out.write(str(thing)) + except socket.error, inst: + if inst[0] != errno.ECONNRESET: + raise + + def header(self, headers=[('Content-type','text/html')]): + for header in headers: + self.out.write("%s: %s\r\n" % header) + self.out.write("\r\n") + + def httphdr(self, type, file="", size=0): + + headers = [('Content-type', type)] + if file: + headers.append(('Content-disposition', 'attachment; filename=%s' % file)) + if size > 0: + headers.append(('Content-length', str(size))) + self.header(headers)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/hgweb/server.py Wed May 31 08:03:29 2006 -0700 @@ -0,0 +1,150 @@ +# hgweb.py - web interface to a mercurial repository +# +# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> +# Copyright 2005 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. + +from mercurial.demandload import demandload +import os, sys, errno +demandload(globals(), "urllib BaseHTTPServer socket SocketServer") +demandload(globals(), "mercurial:ui,hg,util,templater") +demandload(globals(), "mercurial.hgweb.request:hgrequest") +from mercurial.i18n import gettext as _ + +def _splitURI(uri): + """ Return path and query splited from uri + + Just like CGI environment, the path is unquoted, the query is + not. + """ + if '?' in uri: + path, query = uri.split('?', 1) + else: + path, query = uri, '' + return urllib.unquote(path), query + +class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler): + def __init__(self, *args, **kargs): + BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs) + + def log_error(self, format, *args): + errorlog = self.server.errorlog + errorlog.write("%s - - [%s] %s\n" % (self.address_string(), + self.log_date_time_string(), + format % args)) + + def log_message(self, format, *args): + accesslog = self.server.accesslog + accesslog.write("%s - - [%s] %s\n" % (self.address_string(), + self.log_date_time_string(), + format % args)) + + def do_POST(self): + try: + self.do_hgweb() + except socket.error, inst: + if inst[0] != errno.EPIPE: + raise + + def do_GET(self): + self.do_POST() + + def do_hgweb(self): + path_info, query = _splitURI(self.path) + + env = {} + env['GATEWAY_INTERFACE'] = 'CGI/1.1' + env['REQUEST_METHOD'] = self.command + env['SERVER_NAME'] = self.server.server_name + env['SERVER_PORT'] = str(self.server.server_port) + env['REQUEST_URI'] = "/" + env['PATH_INFO'] = path_info + if query: + env['QUERY_STRING'] = query + host = self.address_string() + if host != self.client_address[0]: + env['REMOTE_HOST'] = host + env['REMOTE_ADDR'] = self.client_address[0] + + if self.headers.typeheader is None: + env['CONTENT_TYPE'] = self.headers.type + else: + env['CONTENT_TYPE'] = self.headers.typeheader + length = self.headers.getheader('content-length') + if length: + env['CONTENT_LENGTH'] = length + accept = [] + for line in self.headers.getallmatchingheaders('accept'): + if line[:1] in "\t\n\r ": + accept.append(line.strip()) + else: + accept = accept + line[7:].split(',') + env['HTTP_ACCEPT'] = ','.join(accept) + + req = hgrequest(self.rfile, self.wfile, env) + self.send_response(200, "Script output follows") + self.server.make_and_run_handler(req) + +def create_server(ui, repo, webdirmaker, repoviewmaker): + use_threads = True + + def openlog(opt, default): + if opt and opt != '-': + return open(opt, 'w') + return default + + address = ui.config("web", "address", "") + port = int(ui.config("web", "port", 8000)) + use_ipv6 = ui.configbool("web", "ipv6") + webdir_conf = ui.config("web", "webdir_conf") + accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout) + errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr) + + if use_threads: + try: + from threading import activeCount + except ImportError: + use_threads = False + + if use_threads: + _mixin = SocketServer.ThreadingMixIn + else: + if hasattr(os, "fork"): + _mixin = SocketServer.ForkingMixIn + else: + class _mixin: pass + + class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer): + def __init__(self, *args, **kargs): + BaseHTTPServer.HTTPServer.__init__(self, *args, **kargs) + self.accesslog = accesslog + self.errorlog = errorlog + self.repo = repo + self.webdir_conf = webdir_conf + self.webdirmaker = webdirmaker + self.repoviewmaker = repoviewmaker + + def make_and_run_handler(self, req): + if self.webdir_conf: + hgwebobj = self.webdirmaker(self.server.webdir_conf) + elif self.repo is not None: + hgwebobj = self.repoviewmaker(repo.__class__(repo.ui, + repo.origroot)) + else: + raise hg.RepoError(_('no repo found')) + hgwebobj.run(req) + + class IPv6HTTPServer(MercurialHTTPServer): + address_family = getattr(socket, 'AF_INET6', None) + + def __init__(self, *args, **kwargs): + if self.address_family is None: + raise hg.RepoError(_('IPv6 not available on this system')) + super(IPv6HTTPServer, self).__init__(*args, **kargs) + + if use_ipv6: + return IPv6HTTPServer((address, port), _hgwebhandler) + else: + return MercurialHTTPServer((address, port), _hgwebhandler)