Mercurial > hg-stable
changeset 138:c77a679e9cfa
Revamped templated hgweb
author | mpm@selenic.com |
---|---|
date | Mon, 23 May 2005 16:00:02 -0800 |
parents | b45b1b00fc9e |
children | 17e66e1a0382 |
files | mercurial/hgweb.py templates/changelog.tmpl templates/changelogentry.tmpl templates/changeset.tmpl templates/fileannotate.tmpl templates/filediff.tmpl templates/filelog.tmpl templates/filelogentry.tmpl templates/filerevision.tmpl templates/manifest.tmpl templates/map templates/template-vars.txt |
diffstat | 20 files changed, 730 insertions(+), 409 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/hgweb.py Sun May 22 08:13:38 2005 -0800 +++ b/mercurial/hgweb.py Mon May 23 16:00:02 2005 -0800 @@ -11,16 +11,45 @@ cgitb.enable() import os, cgi, time, re, difflib, sys, zlib -from mercurial import hg, mdiff +from mercurial.hg import * + +def age(t): + def plural(t, c): + if c == 1: return t + return t + "s" + def fmt(t, c): + return "%d %s" % (c, plural(t, c)) + + now = time.time() + delta = max(1, int(now - t)) + + scales = [["second", 1], + ["minute", 60], + ["hour", 3600], + ["day", 3600 * 24], + ["week", 3600 * 24 * 7], + ["month", 3600 * 24 * 30], + ["year", 3600 * 24 * 365]] + + scales.reverse() + + for t, s in scales: + n = delta / s + if n >= 1: return fmt(t, n) def nl2br(text): - return re.sub('\n', '<br />', text) + return text.replace('\n', '<br/>') def obfuscate(text): - l = [] - for c in text: - l.append('&#%d;' % ord(c)) - return ''.join(l) + return ''.join([ '&#%d' % ord(c) for c in text ]) + +def up(p): + if p[0] != "/": p = "/" + p + if p[-1] == "/": p = p[:-1] + up = os.path.dirname(p) + if up == "/": + return "/" + return up + "/" def httphdr(type): print 'Content-type: %s\n' % type @@ -33,365 +62,451 @@ else: sys.stdout.write(str(thing)) -class template: - def __init__(self, tmpl_dir): - self.tmpl_dir = tmpl_dir - def do_page(self, tmpl_fn, **map): - txt = file(os.path.join(self.tmpl_dir, tmpl_fn)).read() - while txt: - m = re.search(r"#([a-zA-Z0-9]+)#", txt) +def template(tmpl, **map): + while tmpl: + m = re.search(r"#([a-zA-Z0-9]+)#", tmpl) + if m: + yield tmpl[:m.start(0)] + v = map.get(m.group(1), "") + yield callable(v) and v() or v + tmpl = tmpl[m.end(0):] + else: + yield tmpl + return + +class templater: + def __init__(self, mapfile): + self.cache = {} + self.map = {} + self.base = os.path.dirname(mapfile) + + for l in file(mapfile): + m = re.match(r'(\S+)\s*=\s*"(.*)"$', l) if m: - yield txt[:m.start(0)] - v = map.get(m.group(1), "") - if callable(v): - for y in v(**map): yield y + self.cache[m.group(1)] = m.group(2) + else: + m = re.match(r'(\S+)\s*=\s*(\S+)', l) + if m: + self.map[m.group(1)] = os.path.join(self.base, m.group(2)) else: - yield v - txt = txt[m.end(0):] - else: - yield txt - txt = '' + raise "unknown map entry '%s'" % l -class page: - def __init__(self, tmpl_dir = "", type="text/html", title="Mercurial Web", - charset="ISO-8859-1"): - self.tmpl = template(tmpl_dir) + def __call__(self, t, **map): + try: + tmpl = self.cache[t] + except KeyError: + tmpl = self.cache[t] = file(self.map[t]).read() + return template(tmpl, **map) + +class hgweb: + maxchanges = 20 + maxfiles = 10 - print 'Content-type: %s; charset=%s\n' % (type, charset) - write(self.tmpl.do_page('htmlstart.tmpl', title = title)) + def __init__(self, path, name, templatemap): + self.reponame = name + self.repo = repository(ui(), path) + self.t = templater(templatemap) - def endpage(self): - print '</BODY>' - print '</HTML>' + def date(self, cs): + return time.asctime(time.gmtime(float(cs[2].split(' ')[0]))) + + def listfiles(self, files, mf): + for f in files[:self.maxfiles]: + yield self.t("filenodelink", node = hex(mf[f]), file = f) + if len(files) > self.maxfiles: + yield self.t("fileellipses") + + def listfilediffs(self, files, changeset): + for f in files[:self.maxfiles]: + yield self.t("filedifflink", node = hex(changeset), file = f) + if len(files) > self.maxfiles: + yield self.t("fileellipses") + + def diff(self, node1, node2, files): + def filterfiles(list, files): + l = [ x for x in list if x in files ] + + for f in files: + if f[-1] != os.sep: f += os.sep + l += [ x for x in list if x.startswith(f) ] + return l - def show_diff(self, a, b, fn): - a = a.splitlines(1) - b = b.splitlines(1) - l = difflib.unified_diff(a, b, fn, fn) - print '<pre>' - for line in l: - line = cgi.escape(line[:-1]) - if line.startswith('+'): - print '<span class="plusline">%s</span>' % (line, ) - elif line.startswith('-'): - print '<span class="minusline">%s</span>' % (line, ) - elif line.startswith('@'): - print '<span class="atline">%s</span>' % (line, ) - else: - print line - print '</pre>' + def prettyprint(diff): + for l in diff.splitlines(1): + line = cgi.escape(l) + if line.startswith('+'): + yield self.t("difflineplus", line = line) + elif line.startswith('-'): + yield self.t("difflineminus", line = line) + elif line.startswith('@'): + yield self.t("difflineat", line = line) + else: + yield self.t("diffline", line = line) -class errpage(page): - def __init__(self, tmpl_dir): - page.__init__(self, tmpl_dir, title="Mercurial Web Error Page") + r = self.repo + cl = r.changelog + mf = r.manifest + change1 = cl.read(node1) + change2 = cl.read(node2) + mmap1 = mf.read(change1[0]) + mmap2 = mf.read(change2[0]) + date1 = self.date(change1) + date2 = self.date(change2) -class change_list(page): - def __init__(self, repo, tmpl_dir, reponame, numchanges = 50): - page.__init__(self, tmpl_dir) - self.repo = repo - self.numchanges = numchanges - write(self.tmpl.do_page('changestitle.tmpl', reponame=reponame)) + c, a, d = r.diffrevs(node1, node2) + c, a, d = map(lambda x: filterfiles(x, files), (c, a, d)) - def content(self, hi=None): - cl = [] - count = self.repo.changelog.count() - if not hi: - hi = count - elif hi < self.numchanges: - hi = self.numchanges - - start = 0 - if hi - self.numchanges >= 0: - start = hi - self.numchanges + for f in c: + to = r.file(f).read(mmap1[f]) + tn = r.file(f).read(mmap2[f]) + yield prettyprint(mdiff.unidiff(to, date1, tn, date2, f)) + for f in a: + to = "" + tn = r.file(f).read(mmap2[f]) + yield prettyprint(mdiff.unidiff(to, date1, tn, date2, f)) + for f in d: + to = r.file(f).read(mmap1[f]) + tn = "" + yield prettyprint(mdiff.unidiff(to, date1, tn, date2, f)) - nav = "Displaying Revisions: %d-%d" % (start, hi-1) - if start != 0: - nav = ('<a href="?cmd=changes;hi=%d">Previous %d</a> ' \ - % (start, self.numchanges)) + nav - if hi != count: - if hi + self.numchanges <= count: - nav += ' <a href="?cmd=changes;hi=%d">Next %d</a>' \ - % (hi + self.numchanges, self.numchanges) - else: - nav += ' <a href="?cmd=changes">Next %d</a>' % \ - self.numchanges + def changelog(self, pos=None): + def changenav(): + def seq(factor = 1): + yield 1 * factor + yield 2 * factor + yield 5 * factor + for f in seq(factor * 10): + yield f + + linear = range(0, count - 2, self.maxchanges)[0:8] + + for i in linear: + yield self.t("naventry", rev = max(i, 1)) - print '<center>%s</center>' % nav + for s in seq(): + if s > count - 2: break + if s > linear[-1]: + yield self.t("naventry", rev = s) + + yield self.t("naventry", rev = count - 1) - for i in xrange(start, hi): - n = self.repo.changelog.node(i) - cl.append((n, self.repo.changelog.read(n))) - cl.reverse() + def changelist(): + cl = self.repo.changelog + l = [] # build a list in forward order for efficiency + for i in range(start, end + 1): + n = cl.node(i) + changes = cl.read(n) + hn = hex(n) + p1, p2 = cl.parents(n) + t = float(changes[2].split(' ')[0]) - print '<table summary="" width="100%" align="center">' - for n, ch in cl: - print '<tr><td>' - self.change_table(n, ch) - print '</td></tr>' - print '</table>' + l.insert(0, self.t( + 'changelogentry', + author = obfuscate(changes[1]), + shortdesc = cgi.escape(changes[4].splitlines()[0]), + age = age(t), + p1 = hex(p1), p2 = hex(p2), + p1rev = cl.rev(p1), p2rev = cl.rev(p2), + manifest = hex(changes[0]), + desc = nl2br(cgi.escape(changes[4])), + date = time.asctime(time.gmtime(t)), + files = self.listfilediffs(changes[3], n), + rev = i, + node = hn)) + + yield l - print '<center>%s</center>' % nav + count = self.repo.changelog.count() + pos = pos or count - 1 + end = min(pos, count - 1) + start = max(0, pos - self.maxchanges) + end = min(count - 1, start + self.maxchanges) + + yield self.t('changelog', repo = self.reponame, changenav = changenav, + rev = pos, changesets = count, changelist = changelist) - def change_table(self, nodeid, changes): - hn = hg.hex(nodeid) - i = self.repo.changelog.rev(nodeid) - (h1, h2) = [ hg.hex(x) for x in self.repo.changelog.parents(nodeid) ] - datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0]))) + def changeset(self, nodeid): + n = bin(nodeid) + cl = self.repo.changelog + changes = cl.read(n) + p1, p2 = cl.parents(n) + p1rev, p2rev = cl.rev(p1), cl.rev(p2) + t = float(changes[2].split(' ')[0]) + files = [] + mf = self.repo.manifest.read(changes[0]) for f in changes[3]: - files.append('<a href="?cmd=file;cs=%s;fn=%s">%s</a> ' \ - % (hn, f, cgi.escape(f))) - write(self.tmpl.do_page('change_table.tmpl', - author=obfuscate(changes[1]), - desc=nl2br(cgi.escape(changes[4])), date=datestr, - files=' '.join(files), revnum=i, revnode=hn)) + files.append(self.t("filenodelink", + filenode = hex(mf[f]), file = f)) + + def diff(): + yield self.diff(p1, n, changes[3]) -class checkin(page): - def __init__(self, repo, tmpl_dir, nodestr): - page.__init__(self, tmpl_dir) - self.repo = repo - self.node = hg.bin(nodestr) - self.nodestr = nodestr - print '<h3>Checkin: %s</h3>' % nodestr + yield self.t('changeset', + diff = diff, + rev = cl.rev(n), + node = nodeid, + shortdesc = cgi.escape(changes[4].splitlines()[0]), + p1 = hex(p1), p2 = hex(p2), + p1rev = cl.rev(p1), p2rev = cl.rev(p2), + manifest = hex(changes[0]), + author = obfuscate(changes[1]), + desc = nl2br(cgi.escape(changes[4])), + date = time.asctime(time.gmtime(t)), + files = files) - def content(self): - changes = self.repo.changelog.read(self.node) - i = self.repo.changelog.rev(self.node) - parents = self.repo.changelog.parents(self.node) - (h1, h2) = [ hg.hex(x) for x in parents ] - (i1, i2) = [ self.repo.changelog.rev(x) for x in parents ] - datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0]))) - mf = self.repo.manifest.read(changes[0]) - files = [] - for f in changes[3]: - files.append('<a href="?cmd=file;nd=%s;fn=%s">%s</a> ' \ - % (hg.hex(mf[f]), f, cgi.escape(f))) - p2link = h2 - if i2 != -1: - p2link = '<a href="?cmd=chkin;nd=%s">%s</a>' % (h2, h2) + def filelog(self, f, filenode): + cl = self.repo.changelog + fl = self.repo.file(f) + count = fl.count() + + def entries(): + l = [] + for i in range(count): + + n = fl.node(i) + lr = fl.linkrev(n) + cn = cl.node(lr) + cs = cl.read(cl.node(lr)) + p1, p2 = fl.parents(n) + t = float(cs[2].split(' ')[0]) - write(self.tmpl.do_page('checkin.tmpl', revnum=i, revnode=self.nodestr, - p1num=i1, p1node=h1, p2num=i2, p2node=h2, p2link=p2link, - mfnum=self.repo.manifest.rev(changes[0]), - mfnode=hg.hex(changes[0]), author=obfuscate(changes[1]), - desc=nl2br(cgi.escape(changes[4])), date=datestr, - files=' '.join(files))) + l.insert(0, self.t("filelogentry", + filenode = hex(n), + filerev = i, + file = f, + node = hex(cn), + author = obfuscate(cs[1]), + age = age(t), + date = time.asctime(time.gmtime(t)), + shortdesc = cgi.escape(cs[4].splitlines()[0]), + p1 = hex(p1), p2 = hex(p2), + p1rev = fl.rev(p1), p2rev = fl.rev(p2))) + + yield l + + yield self.t("filelog", + file = f, + filenode = filenode, + entries = entries) - (c, a, d) = self.repo.diffrevs(parents[0], self.node) - change = self.repo.changelog.read(parents[0]) - mf2 = self.repo.manifest.read(change[0]) - for f in c: - self.show_diff(self.repo.file(f).read(mf2[f]), \ - self.repo.file(f).read(mf[f]), f) - for f in a: - self.show_diff('', self.repo.file(f).read(mf[f]), f) - for f in d: - self.show_diff(self.repo.file(f).read(mf2[f]), '', f) + def filerevision(self, f, node): + fl = self.repo.file(f) + n = bin(node) + text = cgi.escape(fl.read(n)) + changerev = fl.linkrev(n) + cl = self.repo.changelog + cn = cl.node(changerev) + cs = cl.read(cn) + p1, p2 = fl.parents(n) + t = float(cs[2].split(' ')[0]) + mfn = cs[0] + + yield self.t("filerevision", file = f, + filenode = node, + path = up(f), + text = text, + rev = changerev, + node = hex(cn), + manifest = hex(mfn), + author = obfuscate(cs[1]), + age = age(t), + date = time.asctime(time.gmtime(t)), + shortdesc = cgi.escape(cs[4].splitlines()[0]), + p1 = hex(p1), p2 = hex(p2), + p1rev = fl.rev(p1), p2rev = fl.rev(p2)) + -class filepage(page): - def __init__(self, repo, tmpl_dir, fn, node=None, cs=None): - page.__init__(self, tmpl_dir) - self.repo = repo - self.fn = fn - if cs: - chng = self.repo.changelog.read(hg.bin(cs)) - mf = self.repo.manifest.read(chng[0]) - self.node = mf[self.fn] - self.nodestr = hg.hex(self.node) - else: - self.nodestr = node - self.node = hg.bin(node) - print '<div class="filename">%s (%s)</div>' % \ - (cgi.escape(self.fn), self.nodestr, ) - print '<a href="?cmd=hist;fn=%s">history</a><br />' % self.fn - print '<a href="?cmd=ann;fn=%s;nd=%s">annotate</a><br />' % \ - (self.fn, self.nodestr) + def fileannotate(self, f, node): + bcache = {} + ncache = {} + fl = self.repo.file(f) + n = bin(node) + changerev = fl.linkrev(n) + + cl = self.repo.changelog + cn = cl.node(changerev) + cs = cl.read(cn) + p1, p2 = fl.parents(n) + t = float(cs[2].split(' ')[0]) + mfn = cs[0] - def content(self): - print '<pre>' - print cgi.escape(self.repo.file(self.fn).read(self.node)) - print '</pre>' + def annotate(): + for r, l in fl.annotate(n): + try: + cnode = ncache[r] + except KeyError: + cnode = ncache[r] = self.repo.changelog.node(r) + + try: + name = bcache[r] + except KeyError: + cl = self.repo.changelog.read(cnode) + name = cl[1] + f = name.find('@') + if f >= 0: + name = name[:f] + bcache[r] = name -class annpage(page): - def __init__(self, repo, tmpl_dir, fn, node): - page.__init__(self, tmpl_dir) - self.repo = repo - self.fn = fn - self.nodestr = node - self.node = hg.bin(node) - print '<div class="annotation">Annotated: %s (%s)</div>' % \ - (cgi.escape(self.fn), self.nodestr, ) + yield self.t("annotateline", + node = hex(cnode), + rev = r, + author = name, + file = f, + line = cgi.escape(l)) + + yield self.t("fileannotate", + file = f, + filenode = node, + annotate = annotate, + path = up(f), + rev = changerev, + node = hex(cn), + manifest = hex(mfn), + author = obfuscate(cs[1]), + age = age(t), + date = time.asctime(time.gmtime(t)), + shortdesc = cgi.escape(cs[4].splitlines()[0]), + p1 = hex(p1), p2 = hex(p2), + p1rev = fl.rev(p1), p2rev = fl.rev(p2)) - def content(self): - print '<pre>' - for n, l in self.repo.file(self.fn).annotate(self.node): - cnode = self.repo.changelog.lookup(n) - write(self.tmpl.do_page('annline.tmpl', cnode=hg.hex(cnode), - cnum='% 6s' % n, fn=self.fn, line=cgi.escape(l[:-1]))) - print '</pre>' + def manifest(self, mnode, path): + mf = self.repo.manifest.read(bin(mnode)) + rev = self.repo.manifest.rev(bin(mnode)) + node = self.repo.changelog.node(rev) + + dirs = {} + files = {} + short = {} -class mfpage(page): - def __init__(self, repo, tmpl_dir, node): - page.__init__(self, tmpl_dir) - self.repo = repo - self.nodestr = node - self.node = hg.bin(node) + p = path[1:] + l = len(p) - def content(self): - mf = self.repo.manifest.read(self.node) - fns = mf.keys() - fns.sort() - write(self.tmpl.do_page('mftitle.tmpl', node = self.nodestr)) - for f in fns: - write(self.tmpl.do_page('mfentry.tmpl', fn=f, node=hg.hex(mf[f]))) + for f,n in mf.items(): + if f[:l] != p: + continue + remain = f[l:] + if "/" in remain: + short = remain[:remain.find("/") + 1] # bleah + dirs[short] = 1 + else: + short = os.path.basename(remain) + files[short] = (f, n) -class histpage(page): - def __init__(self, repo, tmpl_dir, fn): - page.__init__(self, tmpl_dir) - self.repo = repo - self.fn = fn + def dirlist(): + dl = dirs.keys() + dl.sort() + + for d in dl: + yield self.t("manifestdirentry", + path = os.path.join(path, d), + manifest = mnode, basename = d[:-1]) - def content(self): - print '<div class="filehist">File History: %s</div>' % self.fn - r = self.repo.file(self.fn) - print '<br />' - print '<table summary="" width="100%" align="center">' - for i in xrange(r.count()-1, -1, -1): - print '<tr><td>' - self.hist_ent(i, r) - print '</tr></td>' - print '</table>' + def filelist(): + fl = files.keys() + fl.sort() + for f in fl: + full, fnode = files[f] + yield self.t("manifestfileentry", + file = full, manifest = mnode, filenode = hex(fnode), + basename = f) + + yield self.t("manifest", + manifest = mnode, + rev = rev, + node = hex(node), + path = path, + up = up(path), + dirs = dirlist, + files = filelist) - def hist_ent(self, i, r): - n = r.node(i) - (p1, p2) = r.parents(n) - (h, h1, h2) = map(hg.hex, (n, p1, p2)) - (i1, i2) = map(r.rev, (p1, p2)) - ci = r.linkrev(n) - cn = self.repo.changelog.node(ci) - cs = hg.hex(cn) - changes = self.repo.changelog.read(cn) - datestr = time.asctime(time.gmtime(float(changes[2].split(' ')[0]))) - p2entry = '' - if i2 != -1: - p2entry = ' %d:<a href="?cmd=file;nd=%s;fn=%s">%s</a>' \ - % (i2, h2, self.fn, h2 ), - write(self.tmpl.do_page('hist_ent.tmpl', author=obfuscate(changes[1]), - csnode=cs, desc=nl2br(cgi.escape(changes[4])), - date = datestr, fn=self.fn, revnode=h, p1num = i1, - p1node=h1, p2entry=p2entry)) - -class hgweb: - repo_path = "." - numchanges = 50 - tmpl_dir = "templates" + def filediff(self, file, changeset): + n = bin(changeset) + cl = self.repo.changelog + p1 = cl.parents(n)[0] + cs = cl.read(n) + mf = self.repo.manifest.read(cs[0]) + + def diff(): + yield self.diff(p1, n, file) - def __init__(self): - pass + yield self.t("filediff", + file = file, + filenode = hex(mf[file]), + node = changeset, + rev = self.repo.changelog.rev(n), + p1 = hex(p1), + p1rev = self.repo.changelog.rev(p1), + diff = diff) + + # header and footer, css + # add tags to things + # show parents + # diff between rev and parent in changeset and file + # manifest links + # browse at top + # tags -> list of changesets corresponding to tags + # find tag, changeset, file def run(self): - args = cgi.parse() - ui = hg.ui() - repo = hg.repository(ui, self.repo_path) + if not args.has_key('cmd') or args['cmd'][0] == 'changelog': + hi = self.repo.changelog.count() + if args.has_key('pos'): + hi = int(args['pos'][0]) - if not args.has_key('cmd') or args['cmd'][0] == 'changes': - page = change_list(repo, self.tmpl_dir, 'Mercurial', - self.numchanges) - hi = args.get('hi', ( repo.changelog.count(), )) - page.content(hi = int(hi[0])) - page.endpage() + write(self.changelog(hi)) - elif args['cmd'][0] == 'chkin': - if not args.has_key('nd'): - page = errpage(self.tmpl_dir) - print '<div class="errmsg">No Node!</div>' - else: - page = checkin(repo, self.tmpl_dir, args['nd'][0]) - page.content() - page.endpage() + elif args['cmd'][0] == 'changeset': + write(self.changeset(args['node'][0])) + + elif args['cmd'][0] == 'manifest': + write(self.manifest(args['manifest'][0], args['path'][0])) + + elif args['cmd'][0] == 'filediff': + write(self.filediff(args['file'][0], args['node'][0])) elif args['cmd'][0] == 'file': - if not (args.has_key('nd') and args.has_key('fn')) and \ - not (args.has_key('cs') and args.has_key('fn')): - page = errpage(self.tmpl_dir) - print '<div class="errmsg">Invalid Args!</div>' - else: - if args.has_key('nd'): - page = filepage(repo, self.tmpl_dir, - args['fn'][0], node=args['nd'][0]) - else: - page = filepage(repo, self.tmpl_dir, - args['fn'][0], cs=args['cs'][0]) - page.content() - page.endpage() + write(self.filerevision(args['file'][0], args['filenode'][0])) - elif args['cmd'][0] == 'mf': - if not args.has_key('nd'): - page = errpage(self.tmpl_dir) - print '<div class="errmsg">No Node!</div>' - else: - page = mfpage(repo, self.tmpl_dir, args['nd'][0]) - page.content() - page.endpage() + elif args['cmd'][0] == 'annotate': + write(self.fileannotate(args['file'][0], args['filenode'][0])) - elif args['cmd'][0] == 'hist': - if not args.has_key('fn'): - page = errpage(self.tmpl_dir) - print '<div class="errmsg">No Filename!</div>' - else: - page = histpage(repo, self.tmpl_dir, args['fn'][0]) - page.content() - page.endpage() - - elif args['cmd'][0] == 'ann': - if not args.has_key('fn'): - page = errpage(self.tmpl_dir) - print '<div class="errmsg">No Filename!</div>' - elif not args.has_key('nd'): - page = errpage(self.tmpl_dir) - print '<div class="errmsg">No Node!</div>' - else: - page = annpage(repo, self.tmpl_dir, args['fn'][0], - args['nd'][0]) - page.content() - page.endpage() + elif args['cmd'][0] == 'filelog': + write(self.filelog(args['file'][0], args['filenode'][0])) elif args['cmd'][0] == 'branches': httphdr("text/plain") nodes = [] if args.has_key('nodes'): - nodes = map(hg.bin, args['nodes'][0].split(" ")) - for b in repo.branches(nodes): - print " ".join(map(hg.hex, b)) + nodes = map(bin, args['nodes'][0].split(" ")) + for b in self.repo.branches(nodes): + sys.stdout.write(" ".join(map(hex, b)) + "\n") elif args['cmd'][0] == 'between': httphdr("text/plain") nodes = [] if args.has_key('pairs'): - pairs = [ map(hg.bin, p.split("-")) + pairs = [ map(bin, p.split("-")) for p in args['pairs'][0].split(" ") ] - for b in repo.between(pairs): - print " ".join(map(hg.hex, b)) + for b in self.repo.between(pairs): + sys.stdout.write(" ".join(map(hex, b)) + "\n") elif args['cmd'][0] == 'changegroup': httphdr("application/hg-changegroup") nodes = [] if args.has_key('roots'): - nodes = map(hg.bin, args['roots'][0].split(" ")) + nodes = map(bin, args['roots'][0].split(" ")) z = zlib.compressobj() - for chunk in repo.changegroup(nodes): + for chunk in self.repo.changegroup(nodes): sys.stdout.write(z.compress(chunk)) sys.stdout.write(z.flush()) else: - page = errpage(self.tmpl_dir) - print '<div class="errmsg">unknown command: %s</div>' % \ - cgi.escape(args['cmd'][0]) - page.endpage() + write(self.t("error")) if __name__ == "__main__": hgweb().run()
--- a/templates/annline.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a class="revnumlink" href="?cmd=chkin;nd=#cnode#">#cnum#</a>:<a class="annlinelink" href="?cmd=file;fn=#fn#;cs=#cnode#">#line#</a>
--- a/templates/change_table.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<table summary="" width="100%" border="1"> - <tr> - <td valign="top" width="10%">author:</td> - <td valign="top" width="20%%">#author#</td> - <td valign="top" width="10%">description:</td> - <td width="60%"> - <a href="?cmd=chkin;nd=#revnode#">#desc#</a> - </td> - </tr> - <tr> - <td>date:</td> - <td>#date# UTC</td> - <td valign="top">files:</td> - <td valign="top">#files#</td> - </tr> - <tr> - <td>revision:</td> - <td colspan="3"> - #revnum#:<a href="?cmd=chkin;nd=#revnode#">#revnode#</a> - </td> - </tr> -</table> -<br /> -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/changelog.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,16 @@ +Content-Type: text/html + +<html> +<body> +<h2>changelog for #repo#</h2> + +navigate: #changenav#<br> + +<table> +#changelist# +</table> + +navigate: #changenav#<br> + +</body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/changelogentry.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,26 @@ +<tr> + <td align=right width="15%"><b>#age# ago:</b></td> + <td><b>#shortdesc#</b></td</tr> +<tr> + <td align=right>revision:</td> + <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=changeset;node=#p1#">#p1rev#:#p1#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=changeset;node=#p2#">#p2rev#:#p2#</a></td></tr> +<tr> + <td align=right>manifest:</td> + <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr> +<tr> + <td align=right>author:</td> + <td>#author#</td></tr> +<tr> + <td align=right>date:</td> + <td>#date#</td></tr> +<tr> + <td align=right valign=top>files:</td> + <td>#files#</td></tr> + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/changeset.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,46 @@ +Content-type: text/html + +<html> +<body> +<a href="?cmd=changelog&pos=#rev#">changelog</a> +<a href="?cmd=manifest;manifest=#manifest#;path=/">manifest</a> + +<h2>changeset: #shortdesc#</h2> + +<table> +<tr> + <td align=right>revision:</td> + <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=changeset;node=#p1#">#p1rev#:#p1#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=changeset;node=#p2#">#p2rev#:#p2#</a></td></tr> +<tr> + <td align=right>manifest:</td> + <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr> +<tr> + <td align=right>author:</td> + <td>#author#</td></tr> +<tr> + <td align=right>date:</td> + <td>#date#</td></tr> +<tr> + <td align=right valign=top>files:</td> + <td>#files#</td></tr> +<tr> + <td align=right valign=top>description:</td> + <td>#desc#</td></tr> +</table> + +<hr /> + +<pre> +#diff# +</pre> + +</body> +</html + +
--- a/templates/changestitle.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<h3>Changes For: #reponame#</h3>
--- a/templates/checkin.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -<table summary="" width="100%" border="1"> - <tr> - <td>revision:</td> - <td colspan="3"> - #revnum#: <a href="?cmd=chkin;nd=#revnode#">#revnode#</a> - </td> - </tr> - <tr> - <td>parent(s):</td> - <td colspan="3"> - #p1num#: - <a href="?cmd=chkin;nd=#p1node#">#p1node#</a> - #p2num#:#p2link# - </td> - </tr> - <tr> - <td>manifest:</td> - <td colspan="3"> - #mfnum#: <a href="?cmd=mf;nd=#mfnode#">#mfnode#</a> - </td> - </tr> - <tr> - <td valign="top" width="10%">author:</td> - <td valign="top" width="20%%">#author#</td> - <td valign="top" width="10%">description:</td> - <td width="60%"><a href="?cmd=chkin;nd=#revnode#">#desc#</a></td> - </tr> - <tr> - <td valign="top">date:</td> - <td valign="top">#date# UTC</td> - <td valign="top">files:</td> - <td valign="top">#files#</td> - </tr> -</table> -<br />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/fileannotate.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,42 @@ +Content-type: text/html + +<html> +<body> + +<a href="?cmd=changelog&rev=#rev#">changelog</a> +<a href="?cmd=changeset&node=#node#">changeset</a> +<a href="?cmd=manifest&manifest=#manifest#;path=#path#">manifest</a> +<a href="?cmd=file&file=#file#&filenode=#filenode#">file</a> +<a href="?cmd=filelog&file=#file#;filenode=#filenode#">revisions</a> + +<h2>Annotate #file# (#filenode#)</h2> + +<table> +<tr> + <td align=right>changeset:</td> + <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=file;file=#file#;node=#p1#">#p1rev#:#p1#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=file;file=#file#;node=#p2#">#p2rev#:#p2#</a></td></tr> +<tr> + <td align=right>manifest:</td> + <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr> +<tr> + <td align=right>author:</td> + <td>#author#</td></tr> +<tr> + <td align=right>date:</td> + <td>#date#</td></tr> +</table> + +<hr /> + +<table> +#annotate# +</table> + +</body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/filediff.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,30 @@ +Content-type: text/html + +<html> +<body> +<a href="?cmd=changelog&rev=#rev#">changelog</a> +<a href="?cmd=changeset&node=#node#">changeset</a> +<a href="?cmd=file&file=#file#&filenode=#filenode#">file</a> +<a href="?cmd=filelog&file=#file#&filenode=#filenode#">revisions</a> +<a href="?cmd=annotate&file=#file#&filenode=#filenode#">annotate</a> + +<h2>#file#</h2> + +<table> +<tr> + <td align=right>revision:</td> + <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=changeset;node=#p1#">#p1rev#:#p1#</a></td></tr> +</table> + +<hr /> +<pre> +#diff# +</pre> + +</body> +</html + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/filelog.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,17 @@ +Content-type: text/html + +<html> +<body> + +<a href="?cmd=changelog">changelog</a> +<a href="?cmd=file&file=#file#&filenode=#filenode#">file</a> +<a href="?cmd=annotate&file=#file#&filenode=#filenode#">annotate</a> + +<h2>#file# revision history</h2> + +<table> +#entries# +</table> + +</body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/filelogentry.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,18 @@ +<tr> + <td align=right width="15%"><b>#age# ago:</b></td> + <td><b><a href="?cmd=changeset;node=#changeset#">#shortdesc#</a></b></td</tr> +<tr> + <td align=right>revision:</td> + <td><a href="?cmd=file;file=#file#;filenode=#filenode#">#filerev#:#filenode#</a> +<a href="?cmd=filediff;file=#file#;node=#node#">(diff)</a> +<a href="?cmd=annotate;file=#file#;filenode=#filenode#">(annotate)</a> +</td></tr> +<tr> + <td align=right>author:</td> + <td>#author#</td></tr> +<tr> + <td align=right>date:</td> + <td>#date#</td></tr> + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/filerevision.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,42 @@ +Content-type: text/html + +<html> +<body> + +<a href="?cmd=changelog&rev=#rev#">changelog</a> +<a href="?cmd=changeset&node=#node#">changeset</a> +<a href="?cmd=manifest&manifest=#manifest#;path=#path#">manifest</a> +<a href="?cmd=filelog&file=#file#;filenode=#filenode#">revisions</a> +<a href="?cmd=annotate&file=#file#&filenode=#filenode#">annotate</a> + +<h2>#file# (revision #filenode#)</h2> + +<table> +<tr> + <td align=right>changeset:</td> + <td><a href="?cmd=changeset;node=#node#">#rev#:#node#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=file;file=#file#;node=#p1#">#p1rev#:#p1#</a></td></tr> +<tr> + <td align=right>parent:</td> + <td><a href="?cmd=file;file=#file#;node=#p2#">#p2rev#:#p2#</a></td></tr> +<tr> + <td align=right>manifest:</td> + <td><a href="?cmd=manifest;manifest=#manifest#;path=/">#rev#:#manifest#</a></td></tr> +<tr> + <td align=right>author:</td> + <td>#author#</td></tr> +<tr> + <td align=right>date:</td> + <td>#date#</td></tr> +</table> + +<hr /> + +<pre> +#text# +</pre> + +</body> +</html> \ No newline at end of file
--- a/templates/hist_ent.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -<table summary="" width="100%" border="1"> - <tr> - <td valign="top" width="10%">author:</td> - <td valign="top" width="20%%">#author#</td> - <td valign="top" width="10%">description:</td> - <td width="60%"><a href="?cmd=chkin;nd=#csnode#">#desc#</a></td> - </tr> - <tr> - <td>date:</td> - <td>#date# UTC</td> - <td>revision:</td> - <td><a href="?cmd=file;cs=#csnode#;fn=#fn#">#revnode#</a></td> - </tr> - <tr> - <td>parent(s):</td> - <td colspan="3"> - #p1num#: <a href="?cmd=file;nd=#p1node#;fn=#fn#">#p1node#</a> - #p2entry# - </td> - </tr> -</table> -<br />
--- a/templates/htmlstart.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<HTML> -<!-- created by hgweb 0.1 - jake@edge2.net --> -<HEAD><TITLE>#title#</TITLE> -<style type="text/css"> -body { font-family: sans-serif; font-size: 12px; } -table { font-size: 12px; } -.errmsg { font-size: 200%; color: red; } -.filename { font-size: 150%; color: purple; } -.manifest { font-size: 150%; color: purple; } -.filehist { font-size: 150%; color: purple; } -.annotation { font-size: 150%; color: purple; } -.plusline { color: green; } -.minusline { color: red; } -.atline { color: purple; } -a.annlinelink { text-decoration: none; color: black; } -a.revnumlink { text-decoration: none; color: black; } -a.annlinelink:hover { text-decoration: none; color: blue; } -a.revnumlink:hover { text-decoration: none; color: blue; } -</style> -</HEAD> -<BODY> -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/manifest.tmpl Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,19 @@ +Content-Type: text/html + +<html> +<body> + +<a href="?cmd=changelog&rev=#rev#">changelog</a> +<a href="?cmd=changeset&node=#node#">changeset</a> + +<h2>manifest: #path#</h2> +<p>(#rev#:#manifest#)</p> + +<p> +<a href="?cmd=manifest;manifest=#manifest#;path=#up#">[up]</a><br /> +#dirs#</p> + +<p>#files#</p> + +</body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/map Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,20 @@ +changelog = changelog.tmpl +naventry = "<a href="?cmd=changelog;pos=#rev#">#rev#</a> " +filedifflink = "<a href="?cmd=filediff;node=#node#;file=#file#">#file#</a> " +filenodelink = "<a href="?cmd=file;filenode=#filenode#;file=#file#">#file#</a> " +fileellipses = "..." +changelogentry = changelogentry.tmpl +changeset = changeset.tmpl +manifest = manifest.tmpl +manifestdirentry = "<a href="?cmd=manifest;manifest=#manifest#;path=#path#">#basename#/</a><br />" +manifestfileentry = "<a href="?cmd=file;filenode=#filenode#;file=#file#">#basename#</a><br /> " +filerevision = filerevision.tmpl +fileannotate = fileannotate.tmpl +filediff = filediff.tmpl +filelog = filelog.tmpl +filelogentry = filelogentry.tmpl +annotateline = "<tr><td align = right><a href="?cmd=changeset;node=#node#">#author#@#rev#</a>:</td><td><pre>#line#</pre></td></tr>" +difflineplus = "<span class=plusline>#line#</span>" +difflineminus = "<span class=minusline>#line#</span>" +difflineat = "<span class=atline>#line#</span>" +diffline = "#line#" \ No newline at end of file
--- a/templates/mfentry.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<a href="?cmd=file;fn=#fn#;nd=#node#">#fn#</a><br />
--- a/templates/mftitle.tmpl Sun May 22 08:13:38 2005 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -<div class="manifest">Manifest (#node#)</div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/template-vars.txt Mon May 23 16:00:02 2005 -0800 @@ -0,0 +1,38 @@ +repo the name of the repo +rev a changeset.manifest revision +node a changeset node +changesets total number of changesets +file a filename +filenode a file node +filerev a file revision +filerevs total number of file revisions +up the directory of the relevant file +path a path in the manifest, starting with "/" +basename a short pathname +manifest a manifest node +manifestrev a manifest revision +date a date string +age age in hours, days, etc +line a line of text (escaped) +desc a description (escaped, with breaks) +shortdesc a short description (escaped) +author a name or email addressv(obfuscated) +p1, p2 parent nodes +p1rev, p2rev parent revs + +header the global page header +footer the global page footer + +files a list of file links +dirs a set of directory links +diff a diff of one or more files +annotate an annotated file +entries the entries relevant to the page + +Templates and commands: + changelog(rev) - a page for browsing changesets + naventry - a link for jumping to a changeset number + filenodelink - jump to file diff + fileellipses - printed after maxfiles + changelogentry - an entry in the log + manifest - browse a manifest as a directory tree \ No newline at end of file