##// END OF EJS Templates
Arrange for old copies of CGI scripts to still work.
Arrange for old copies of CGI scripts to still work.

File last commit:

r2535:b8ccf638 default
r2535:b8ccf638 default
Show More
hgwebdir_mod.py
167 lines | 7.0 KiB | text/x-python | PythonLexer
Eric Hopper
Fixing up comment headers for split up code.
r2391 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
Eric Hopper
Final stage of the hgweb split up....
r2356 #
# 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.
import os
from mercurial.demandload import demandload
Eric Hopper
Really fix http headers for web UI and issue 254....
r2514 demandload(globals(), "ConfigParser mimetools cStringIO")
Eric Hopper
Final stage of the hgweb split up....
r2356 demandload(globals(), "mercurial:ui,hg,util,templater")
TK Soh
hgweb: fix tracebacks on both index and repo pages
r2360 demandload(globals(), "mercurial.hgweb.hgweb_mod:hgweb")
demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile")
Eric Hopper
Final stage of the hgweb split up....
r2356 from mercurial.i18n import gettext as _
# This is a stopgap
class hgwebdir(object):
def __init__(self, config):
def cleannames(items):
return [(name.strip(os.sep), path) for name, path in items]
Eric Hopper
Arrange for old copies of CGI scripts to still work.
r2535 self.origconfig = config
Eric Hopper
Final stage of the hgweb split up....
r2356 self.motd = ""
self.repos_sorted = ('name', False)
if isinstance(config, (list, tuple)):
self.repos = cleannames(config)
self.repos_sorted = ('', False)
elif isinstance(config, dict):
self.repos = cleannames(config.items())
self.repos.sort()
else:
cp = ConfigParser.SafeConfigParser()
cp.read(config)
self.repos = []
if cp.has_section('web') and cp.has_option('web', 'motd'):
self.motd = cp.get('web', 'motd')
if cp.has_section('paths'):
self.repos.extend(cleannames(cp.items('paths')))
if cp.has_section('collections'):
for prefix, root in cp.items('collections'):
for path in util.walkrepos(root):
repo = os.path.normpath(path)
name = repo
if name.startswith(prefix):
name = name[len(prefix):]
self.repos.append((name.lstrip(os.sep), repo))
self.repos.sort()
Eric Hopper
Arrange for old copies of CGI scripts to still work.
r2535 def run(self):
if os.environ['GATEWAY_INTERFACE'][0:6] != "CGI/1.":
raise RuntimeError("This function is only intended to be called while running as a CGI script.")
import mercurial.hgweb.wsgicgi as wsgicgi
from request import wsgiapplication
def make_web_app():
return self.__class__(self.origconfig)
wsgicgi.launch(wsgiapplication(make_web_app))
def run_wsgi(self, req):
Eric Hopper
Final stage of the hgweb split up....
r2356 def header(**map):
Eric Hopper
Really fix http headers for web UI and issue 254....
r2514 header_file = cStringIO.StringIO(''.join(tmpl("header", **map)))
msg = mimetools.Message(header_file, 0)
req.header(msg.items())
yield header_file.read()
Eric Hopper
Final stage of the hgweb split up....
r2356
def footer(**map):
yield tmpl("footer", motd=self.motd, **map)
m = os.path.join(templater.templatepath(), "map")
tmpl = templater.templater(m, templater.common_filters,
defaults={"header": header,
"footer": footer})
def archivelist(ui, nodeid, url):
Thomas Arendsen Hein
Fixed [web] allow_archive for comma separated parameters by using ui.configlist....
r2500 allowed = ui.configlist("web", "allow_archive")
Eric Hopper
Final stage of the hgweb split up....
r2356 for i in ['zip', 'gz', 'bz2']:
Thomas Arendsen Hein
Allow comma to separate types in allow_archive, too. Use longer variable name.
r2359 if i in allowed or ui.configbool("web", "allow" + i):
Eric Hopper
Final stage of the hgweb split up....
r2356 yield {"type" : i, "node": nodeid, "url": url}
def entries(sortcolumn="", descending=False, **map):
rows = []
parity = 0
for name, path in self.repos:
u = ui.ui()
try:
u.readconfig(os.path.join(path, '.hg', 'hgrc'))
except IOError:
pass
get = u.config
url = ('/'.join([req.env["REQUEST_URI"].split('?')[0], name])
.replace("//", "/"))
# update time with local timezone
try:
d = (get_mtime(path), util.makedate()[1])
except OSError:
continue
contact = (get("ui", "username") or # preferred
get("web", "contact") or # deprecated
get("web", "author", "")) # also
description = get("web", "description", "")
name = get("web", "name", name)
row = dict(contact=contact or "unknown",
contact_sort=contact.upper() or "unknown",
name=name,
name_sort=name,
url=url,
description=description or "unknown",
description_sort=description.upper() or "unknown",
lastchange=d,
lastchange_sort=d[1]-d[0],
archives=archivelist(u, "tip", url))
if (not sortcolumn
or (sortcolumn, descending) == self.repos_sorted):
# fast path for unsorted output
row['parity'] = parity
parity = 1 - parity
yield row
else:
rows.append((row["%s_sort" % sortcolumn], row))
if rows:
rows.sort()
if descending:
rows.reverse()
for key, row in rows:
row['parity'] = parity
parity = 1 - parity
yield row
virtual = req.env.get("PATH_INFO", "").strip('/')
if virtual:
real = dict(self.repos).get(virtual)
if real:
try:
hgweb(real).run(req)
except IOError, inst:
req.write(tmpl("error", error=inst.strerror))
except hg.RepoError, inst:
req.write(tmpl("error", error=str(inst)))
else:
req.write(tmpl("notfound", repo=virtual))
else:
if req.form.has_key('static'):
static = os.path.join(templater.templatepath(), "static")
fname = req.form['static'][0]
Eric Hopper
Really fix http headers for web UI and issue 254....
r2514 req.write(staticfile(static, fname, req)
Eric Hopper
Final stage of the hgweb split up....
r2356 or tmpl("error", error="%r not found" % fname))
else:
sortable = ["name", "description", "contact", "lastchange"]
sortcolumn, descending = self.repos_sorted
if req.form.has_key('sort'):
sortcolumn = req.form['sort'][0]
descending = sortcolumn.startswith('-')
if descending:
sortcolumn = sortcolumn[1:]
if sortcolumn not in sortable:
sortcolumn = ""
sort = [("sort_%s" % column,
"%s%s" % ((not descending and column == sortcolumn)
and "-" or "", column))
for column in sortable]
req.write(tmpl("index", entries=entries,
sortcolumn=sortcolumn, descending=descending,
**dict(sort)))