Splitting up hgweb so it's easier to change.
--- 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)