changeset 2128:150208e0d94b

Merge with crew
author Thomas Arendsen Hein <thomas@intevation.de>
date Tue, 25 Apr 2006 19:38:45 +0200
parents 8a85dbbadddf (diff) e296dee1cd9a (current diff)
children e5f5c21f4169
files
diffstat 5 files changed, 87 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -21,6 +21,7 @@ Vicent SeguĂ­ Pascual <vseguip at gmail.com>
 Sean Perry <shaleh at speakeasy.net>
 Nguyen Anh Quynh <aquynh at gmail.com>
 Ollivier Robert <roberto at keltia.freenix.fr>
+Alexander Schremmer <alex at alexanderweb.de>
 Arun Sharma <arun at sharma-home.net>
 Josef "Jeff" Sipek <jeffpc at optonline.net>
 Kevin Smith <yarcs at qualitycode.com>
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2495,6 +2495,8 @@ def serve(ui, repo, **opts):
     """
 
     if opts["stdio"]:
+        if repo is None:
+            raise hg.RepoError(_('no repo found'))
         fin, fout = sys.stdin, sys.stdout
         sys.stdout = sys.stderr
 
@@ -2566,11 +2568,15 @@ def serve(ui, repo, **opts):
                 r = repo.addchangegroup(fin)
                 respond(str(r))
 
-    optlist = "name templates style address port ipv6 accesslog errorlog"
+    optlist = ("name templates style address port ipv6"
+               " accesslog errorlog webdir_conf")
     for o in optlist.split():
         if opts[o]:
             ui.setconfig("web", o, opts[o])
 
+    if repo is None and not ui.config("web", "webdir_conf"):
+        raise hg.RepoError(_('no repo found'))
+
     if opts['daemon'] and not opts['daemon_pipefds']:
         rfd, wfd = os.pipe()
         args = sys.argv[:]
@@ -2582,7 +2588,7 @@ def serve(ui, repo, **opts):
         os._exit(0)
 
     try:
-        httpd = hgweb.create_server(repo)
+        httpd = hgweb.create_server(ui, repo)
     except socket.error, inst:
         raise util.Abort(_('cannot start server: ') + inst.args[1])
 
@@ -2997,8 +3003,8 @@ table = {
     "import|patch":
         (import_,
          [('p', 'strip', 1,
-           _('directory strip option for patch. This has the same\n') +
-           _('meaning as the corresponding patch option')),
+           _('directory strip option for patch. This has the same\n'
+             'meaning as the corresponding patch option')),
           ('b', 'base', '', _('base path')),
           ('f', 'force', None,
            _('skip check for outstanding uncommitted changes'))],
@@ -3127,6 +3133,8 @@ table = {
           ('a', 'address', '', _('address to use')),
           ('n', 'name', '',
            _('name to show in web pages (default: working dir)')),
+          ('', 'webdir-conf', '', _('name of the webdir config file'
+                                    ' (serve more than one repo)')),
           ('', 'pid-file', '', _('name of file to write process ID to')),
           ('', 'stdio', None, _('for remote clients')),
           ('t', 'templates', '', _('web templates to use')),
@@ -3199,7 +3207,7 @@ globalopts = [
 
 norepo = ("clone init version help debugancestor debugcomplete debugdata"
           " debugindex debugindexdot")
-optionalrepo = ("paths debugconfig")
+optionalrepo = ("paths serve debugconfig")
 
 def findpossible(cmd):
     """
--- a/mercurial/hgweb.py
+++ b/mercurial/hgweb.py
@@ -10,11 +10,23 @@ import os, cgi, sys
 import mimetypes
 from demandload import demandload
 demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser")
-demandload(globals(), "tempfile StringIO BaseHTTPServer util")
-demandload(globals(), "archival mimetypes templater")
+demandload(globals(), "tempfile StringIO BaseHTTPServer util SocketServer")
+demandload(globals(), "archival mimetypes templater urllib")
 from node import *
 from 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
@@ -776,54 +788,54 @@ class hgweb(object):
         if not req.form.has_key('cmd'):
             req.form['cmd'] = [self.t.cache['default'],]
 
-        if req.form['cmd'][0] == 'changelog':
-            c = self.repo.changelog.count() - 1
-            hi = c
+        cmd = req.form['cmd'][0]
+        if cmd == 'changelog':
+            hi = self.repo.changelog.count() - 1
             if req.form.has_key('rev'):
                 hi = req.form['rev'][0]
                 try:
                     hi = self.repo.changelog.rev(self.repo.lookup(hi))
                 except hg.RepoError:
-                    req.write(self.search(hi))
+                    req.write(self.search(hi)) # XXX redirect to 404 page?
                     return
 
             req.write(self.changelog(hi))
 
-        elif req.form['cmd'][0] == 'changeset':
+        elif cmd == 'changeset':
             req.write(self.changeset(req.form['node'][0]))
 
-        elif req.form['cmd'][0] == 'manifest':
+        elif cmd == 'manifest':
             req.write(self.manifest(req.form['manifest'][0],
                                     clean(req.form['path'][0])))
 
-        elif req.form['cmd'][0] == 'tags':
+        elif cmd == 'tags':
             req.write(self.tags())
 
-        elif req.form['cmd'][0] == 'summary':
+        elif cmd == 'summary':
             req.write(self.summary())
 
-        elif req.form['cmd'][0] == 'filediff':
+        elif cmd == 'filediff':
             req.write(self.filediff(clean(req.form['file'][0]),
                                     req.form['node'][0]))
 
-        elif req.form['cmd'][0] == 'file':
+        elif cmd == 'file':
             req.write(self.filerevision(clean(req.form['file'][0]),
                                         req.form['filenode'][0]))
 
-        elif req.form['cmd'][0] == 'annotate':
+        elif cmd == 'annotate':
             req.write(self.fileannotate(clean(req.form['file'][0]),
                                         req.form['filenode'][0]))
 
-        elif req.form['cmd'][0] == 'filelog':
+        elif cmd == 'filelog':
             req.write(self.filelog(clean(req.form['file'][0]),
                                    req.form['filenode'][0]))
 
-        elif req.form['cmd'][0] == 'heads':
+        elif cmd == 'heads':
             req.httphdr("application/mercurial-0.1")
             h = self.repo.heads()
             req.write(" ".join(map(hex, h)) + "\n")
 
-        elif req.form['cmd'][0] == 'branches':
+        elif cmd == 'branches':
             req.httphdr("application/mercurial-0.1")
             nodes = []
             if req.form.has_key('nodes'):
@@ -831,7 +843,7 @@ class hgweb(object):
             for b in self.repo.branches(nodes):
                 req.write(" ".join(map(hex, b)) + "\n")
 
-        elif req.form['cmd'][0] == 'between':
+        elif cmd == 'between':
             req.httphdr("application/mercurial-0.1")
             nodes = []
             if req.form.has_key('pairs'):
@@ -840,7 +852,7 @@ class hgweb(object):
             for b in self.repo.between(pairs):
                 req.write(" ".join(map(hex, b)) + "\n")
 
-        elif req.form['cmd'][0] == 'changegroup':
+        elif cmd == 'changegroup':
             req.httphdr("application/mercurial-0.1")
             nodes = []
             if not self.allowpull:
@@ -859,7 +871,7 @@ class hgweb(object):
 
             req.write(z.flush())
 
-        elif req.form['cmd'][0] == 'archive':
+        elif cmd == 'archive':
             changeset = self.repo.lookup(req.form['node'][0])
             type = req.form['type'][0]
             if (type in self.archives and
@@ -869,7 +881,7 @@ class hgweb(object):
 
             req.write(self.t("error"))
 
-        elif req.form['cmd'][0] == 'static':
+        elif cmd == 'static':
             fname = req.form['file'][0]
             req.write(staticfile(static, fname)
                       or self.t("error", error="%r not found" % fname))
@@ -877,20 +889,39 @@ class hgweb(object):
         else:
             req.write(self.t("error"))
 
-def create_server(repo):
+def create_server(ui, repo):
+    use_threads = True
 
     def openlog(opt, default):
         if opt and opt != '-':
             return open(opt, 'w')
         return default
 
-    address = repo.ui.config("web", "address", "")
-    port = int(repo.ui.config("web", "port", 8000))
-    use_ipv6 = repo.ui.configbool("web", "ipv6")
-    accesslog = openlog(repo.ui.config("web", "accesslog", "-"), sys.stdout)
-    errorlog = openlog(repo.ui.config("web", "errorlog", "-"), sys.stderr)
+    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
 
-    class IPv6HTTPServer(BaseHTTPServer.HTTPServer):
+    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):
@@ -899,6 +930,7 @@ def create_server(repo):
             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(),
@@ -920,11 +952,7 @@ def create_server(repo):
             self.do_POST()
 
         def do_hgweb(self):
-            query = ""
-            p = self.path.find("?")
-            if p:
-                query = self.path[p + 1:]
-                query = query.replace('+', ' ')
+            path_info, query = splitURI(self.path)
 
             env = {}
             env['GATEWAY_INTERFACE'] = 'CGI/1.1'
@@ -932,6 +960,7 @@ def create_server(repo):
             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()
@@ -956,13 +985,20 @@ def create_server(repo):
 
             req = hgrequest(self.rfile, self.wfile, env)
             self.send_response(200, "Script output follows")
-            hg.run(req)
 
-    hg = hgweb(repo)
+            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 BaseHTTPServer.HTTPServer((address, port), hgwebhandler)
+        return MercurialHTTPServer((address, port), hgwebhandler)
 
 # This is a stopgap
 class hgwebdir(object):
--- a/templates/header-gitweb.tmpl
+++ b/templates/header-gitweb.tmpl
@@ -7,5 +7,5 @@ Content-type: text/html
 <link rel="icon" href="?static=hgicon.png" type="image/png">
 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
 <meta name="robots" content="index, nofollow"/>
-<style type="text/css">/*<![CDATA[*/ @import "?static=style-gitweb.css"; /*]]>*/</style>
+<link rel="stylesheet" href="?static=style-gitweb.css" type="text/css" />
 
--- a/templates/header.tmpl
+++ b/templates/header.tmpl
@@ -5,4 +5,4 @@ Content-type: text/html
 <head>
 <link rel="icon" href="?static=hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<style type="text/css">/*<![CDATA[*/ @import "?static=style.css"; /*]]>*/</style>
+<link rel="stylesheet" href="?static=style.css" type="text/css" />