Add 'hg serve' command for stand-alone server
authormpm@selenic.com
Wed, 25 May 2005 16:27:10 -0800
changeset 158 be7103467d2e0051928e8c0e74988632d1e25734
parent 157 2653740d811892ea471bd70441b8c8f31e40105d
child 159 f9d8620ef4699375f5251a5e49e4faa94543f8a6
push id1
push usergszorc@mozilla.com
push dateWed, 18 Mar 2015 16:34:57 +0000
Add 'hg serve' command for stand-alone server This adds a simple stand-alone web server mode to hg that exports the current repo for merging and browsing. The default port is 8000.
hg
mercurial/hgweb.py
--- a/hg
+++ b/hg
@@ -32,16 +32,17 @@ def help():
  diff [files...]       diff working directory (or selected files)
  dump <file> [rev]     dump the latest or given revision of a file
  dumpmanifest [rev]    dump the latest or given revision of the manifest
  history               show changeset history
  init                  create a new repository in this directory
  log <file>            show revision history of a single file
  merge <path>          merge changes from <path> into local repository
  remove [files...]     remove the given files in the next commit
+ serve                 export the repository via HTTP
  status                show new, missing, and changed files in working dir
  tags                  show current changeset tags
 """
 
 def filterfiles(list, files):
     l = [ x for x in list if x in files ]
 
     for f in files:
@@ -543,13 +544,29 @@ elif cmd == "verify":
             errors += 1
 
     ui.status("%d files, %d changesets, %d total revisions\n" %
               (files, changesets, revisions))
     
     if errors:
         ui.warn("%d integrity errors encountered!\n" % errors)
         sys.exit(1)
+
+elif cmd == "serve":
+    from mercurial import hgweb
+    
+    soptions = {}
+    opts = [('p', 'port', 8000, 'listen port'),
+            ('a', 'address', '', 'interface address'),
+            ('n', 'name', os.getcwd(), 'repository name'),
+            ('t', 'templates', "", 'template map')
+            ]
+    
+    args = fancyopts.fancyopts(args, opts, soptions,
+                              'hg serve [options]')
+
+    hgweb.server(repo.root, soptions["name"], soptions["templates"],
+                 soptions["address"], soptions["port"])
     
 else:
     print "unknown command\n"
     help()
     sys.exit(1)
--- a/mercurial/hgweb.py
+++ b/mercurial/hgweb.py
@@ -573,10 +573,69 @@ class hgweb:
             for chunk in self.repo.changegroup(nodes):
                 sys.stdout.write(z.compress(chunk))
 
             sys.stdout.write(z.flush())
 
         else:
             write(self.t("error"))
 
-if __name__ == "__main__":
-    hgweb().run()
+def server(path, name, templates, address, port):
+
+    import BaseHTTPServer
+    import sys, os
+
+    class hgwebhandler(BaseHTTPServer.BaseHTTPRequestHandler):
+        def do_POST(self):
+            self.do_hgweb()
+
+        def do_GET(self):
+            self.do_hgweb()
+
+        def do_hgweb(self):
+            query = ""
+            p = self.path.find("?")
+            if p:
+                query = self.path[p + 1:]
+                query = query.replace('+', ' ')
+        
+            env = {}
+            env['GATEWAY_INTERFACE'] = 'CGI/1.1'
+            env['REQUEST_METHOD'] = self.command
+            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)
+
+            os.environ.update(env)
+
+            save = sys.argv, sys.stdin, sys.stdout, sys.stderr
+            try:
+                sys.stdin = self.rfile
+                sys.stdout = self.wfile
+                sys.argv = ["hgweb.py"]
+                if '=' not in query:
+                    sys.argv.append(query)
+                self.send_response(200, "Script output follows")
+                hg.run()
+            finally:
+                sys.argv, sys.stdin, sys.stdout, sys.stderr = save
+
+    hg = hgweb(path, name, templates)
+    httpd = BaseHTTPServer.HTTPServer((address, port), hgwebhandler)
+    httpd.serve_forever()