comparison mercurial/hgweb.py @ 941:4cf418c2a013

Add a multi-repository server This merges a bunch of the ideas for a multi-repository CGI script and simplifies things a bit. It uses PATH_INFO so it generally wants paths of the form: http://host/hg.cgi/virtualpath This gets mapped via a simple config file to the real path. All info about the repo is read from the repo's hgrc.
author mpm@selenic.com
date Fri, 19 Aug 2005 16:38:25 -0800
parents 6b735e0ddd81
children ffb0665028f0
comparison
equal deleted inserted replaced
940:1300271ba8de 941:4cf418c2a013
112 return template(tmpl, self.filters, **m) 112 return template(tmpl, self.filters, **m)
113 113
114 def rfc822date(x): 114 def rfc822date(x):
115 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(x)) 115 return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(x))
116 116
117 common_filters = {
118 "escape": cgi.escape,
119 "age": age,
120 "date": (lambda x: time.asctime(time.gmtime(x))),
121 "addbreaks": nl2br,
122 "obfuscate": obfuscate,
123 "short": (lambda x: x[:12]),
124 "firstline": (lambda x: x.splitlines(1)[0]),
125 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"),
126 "rfc822date": rfc822date,
127 }
128
117 class hgweb: 129 class hgweb:
118 maxchanges = 10 130 maxchanges = 10
119 maxfiles = 10 131 maxfiles = 10
120 132
121 def __init__(self, path, name, templates = ""): 133 def __init__(self, path, name=None, templates=""):
122 self.templates = templates 134 self.templates = templates
123 self.reponame = name 135 self.reponame = name
124 self.path = path 136 self.path = path
125 self.mtime = -1 137 self.mtime = -1
126 self.viewonly = 0 138 self.viewonly = 0
127
128 self.filters = {
129 "escape": cgi.escape,
130 "age": age,
131 "date": (lambda x: time.asctime(time.gmtime(x))),
132 "addbreaks": nl2br,
133 "obfuscate": obfuscate,
134 "short": (lambda x: x[:12]),
135 "firstline": (lambda x: x.splitlines(1)[0]),
136 "permissions": (lambda x: x and "-rwxr-xr-x" or "-rw-r--r--"),
137 "rfc822date": rfc822date,
138 }
139 139
140 def refresh(self): 140 def refresh(self):
141 s = os.stat(os.path.join(self.path, ".hg", "00changelog.i")) 141 s = os.stat(os.path.join(self.path, ".hg", "00changelog.i"))
142 if s.st_mtime != self.mtime: 142 if s.st_mtime != self.mtime:
143 self.mtime = s.st_mtime 143 self.mtime = s.st_mtime
617 if "?" in uri: uri = uri.split("?")[0] 617 if "?" in uri: uri = uri.split("?")[0]
618 url = "http://%s%s%s" % (os.environ["SERVER_NAME"], port, uri) 618 url = "http://%s%s%s" % (os.environ["SERVER_NAME"], port, uri)
619 619
620 name = self.reponame or self.repo.ui.config("web", "name", os.getcwd()) 620 name = self.reponame or self.repo.ui.config("web", "name", os.getcwd())
621 621
622 self.t = templater(m, self.filters, 622 self.t = templater(m, common_filters,
623 {"url":url, 623 {"url":url,
624 "repo":name, 624 "repo":name,
625 "header":header, 625 "header":header,
626 "footer":footer, 626 "footer":footer,
627 }) 627 })
816 def server(path, name, templates, address, port, use_ipv6 = False, 816 def server(path, name, templates, address, port, use_ipv6 = False,
817 accesslog = sys.stdout, errorlog = sys.stderr): 817 accesslog = sys.stdout, errorlog = sys.stderr):
818 httpd = create_server(path, name, templates, address, port, use_ipv6, 818 httpd = create_server(path, name, templates, address, port, use_ipv6,
819 accesslog, errorlog) 819 accesslog, errorlog)
820 httpd.serve_forever() 820 httpd.serve_forever()
821
822 # This is a stopgap
823 class hgwebdir:
824 def __init__(self, config):
825 self.cp = ConfigParser.SafeConfigParser()
826 self.cp.read(config)
827
828 def run(self):
829 try:
830 virtual = os.environ["PATH_INFO"]
831 except:
832 virtual = ""
833
834 if virtual:
835 real = self.cp.get("paths", virtual[1:])
836 h = hgweb.hgweb(real)
837 h.run()
838 return
839
840 def header(**map):
841 yield tmpl("header", **map)
842
843 def footer(**map):
844 yield tmpl("footer", **map)
845
846 templates = templatepath()
847 m = os.path.join(templates, "map")
848 tmpl = templater(m, common_filters,
849 {"header": header, "footer": footer})
850
851 def entries(**map):
852 parity = 0
853 for v,r in self.cp.items("paths"):
854 cp2 = ConfigParser.SafeConfigParser()
855 cp2.read(os.path.join(r, ".hg", "hgrc"))
856
857 def get(sec, val, default):
858 try:
859 return cp2.get(sec, val)
860 except:
861 return default
862
863 yield tmpl("indexentry",
864 author = get("web", "author", "unknown"),
865 name = get("web", "name", v),
866 url = os.environ["REQUEST_URI"] + "/" + v,
867 parity = parity,
868 shortdesc = get("web", "description", "unknown"),
869 lastupdate = os.stat(os.path.join(r, ".hg",
870 "00changelog.d")).st_mtime)
871
872 parity = 1 - parity
873
874 write(tmpl("index", entries = entries))