--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/hgweb/hgwebdir_mod.py Wed May 31 10:42:44 2006 -0700
@@ -0,0 +1,152 @@
+# 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.
+
+import os
+from mercurial.demandload import demandload
+demandload(globals(), "ConfigParser")
+demandload(globals(), "mercurial:ui,hg,util,templater")
+demandload(globals(), "mercurial.hgweb.request:hgrequest")
+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]
+
+ 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()
+
+ def run(self, req=hgrequest()):
+ def header(**map):
+ yield tmpl("header", **map)
+
+ 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):
+ for i in ['zip', 'gz', 'bz2']:
+ if ui.configbool("web", "allow" + i, False):
+ 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]
+ req.write(staticfile(static, fname)
+ 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)))