# HG changeset patch # User mpm@selenic.com # Date 1116910668 28800 # Node ID 529bf610092ed07deaffbb870cda939a3e0720cc # Parent 5f471a75d6074544ba0ac65931c8aef31e2829a5 Prettify the web interface Add header, footer templates Add null parent handling Combine files and directories Add parity flag for alternating line colors Add line numbers to filerevision diff --git a/hg b/hg --- a/hg +++ b/hg @@ -463,7 +463,7 @@ elif cmd == "verify": except Exception, inst: ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst)) errors += 1 - + ff = [ l.split('\0') for l in delta.splitlines() ] for f, fn in ff: filenodes.setdefault(f, {})[hg.bin(fn)] = 1 diff --git a/mercurial/hgweb.py b/mercurial/hgweb.py --- a/mercurial/hgweb.py +++ b/mercurial/hgweb.py @@ -122,6 +122,10 @@ class hgweb: if len(files) > self.maxfiles: yield self.t("fileellipses") + def parent(self, t1, node, rev): + if node != hex(nullid): + yield self.t(t1, node = node, rev = rev) + def diff(self, node1, node2, files): def filterfiles(list, files): l = [ x for x in list if x in files ] @@ -169,6 +173,12 @@ class hgweb: tn = "" yield prettyprint(mdiff.unidiff(to, date1, tn, date2, f)) + def header(self): + yield self.t("header", repo = self.reponame) + + def footer(self): + yield self.t("footer", repo = self.reponame) + def changelog(self, pos=None): def changenav(): def seq(factor = 1): @@ -191,6 +201,7 @@ class hgweb: yield self.t("naventry", rev = count - 1) def changelist(): + parity = (start - end) & 1 cl = self.repo.changelog l = [] # build a list in forward order for efficiency for i in range(start, end + 1): @@ -202,9 +213,14 @@ class hgweb: l.insert(0, self.t( 'changelogentry', + parity = parity, author = obfuscate(changes[1]), shortdesc = cgi.escape(changes[4].splitlines()[0]), age = age(t), + parent1 = self.parent("changelogparent", + hex(p1), cl.rev(p1)), + parent2 = self.parent("changelogparent", + hex(p2), cl.rev(p2)), p1 = hex(p1), p2 = hex(p2), p1rev = cl.rev(p1), p2rev = cl.rev(p2), manifest = hex(changes[0]), @@ -213,6 +229,7 @@ class hgweb: files = self.listfilediffs(changes[3], n), rev = i, node = hn)) + parity = 1 - parity yield l @@ -222,8 +239,12 @@ class hgweb: 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) + yield self.t('changelog', + header = self.header(), + footer = self.footer(), + repo = self.reponame, + changenav = changenav, + rev = pos, changesets = count, entries = changelist) def changeset(self, nodeid): n = bin(nodeid) @@ -243,10 +264,17 @@ class hgweb: yield self.diff(p1, n, changes[3]) yield self.t('changeset', + header = self.header(), + footer = self.footer(), + repo = self.reponame, diff = diff, rev = cl.rev(n), node = nodeid, shortdesc = cgi.escape(changes[4].splitlines()[0]), + parent1 = self.parent("changesetparent", + hex(p1), cl.rev(p1)), + parent2 = self.parent("changesetparent", + hex(p2), cl.rev(p2)), p1 = hex(p1), p2 = hex(p2), p1rev = cl.rev(p1), p2rev = cl.rev(p2), manifest = hex(changes[0]), @@ -262,6 +290,8 @@ class hgweb: def entries(): l = [] + parity = (count - 1) & 1 + for i in range(count): n = fl.node(i) @@ -272,6 +302,7 @@ class hgweb: t = float(cs[2].split(' ')[0]) l.insert(0, self.t("filelogentry", + parity = parity, filenode = hex(n), filerev = i, file = f, @@ -282,10 +313,14 @@ class hgweb: shortdesc = cgi.escape(cs[4].splitlines()[0]), p1 = hex(p1), p2 = hex(p2), p1rev = fl.rev(p1), p2rev = fl.rev(p2))) + parity = 1 - parity yield l yield self.t("filelog", + header = self.header(), + footer = self.footer(), + repo = self.reponame, file = f, filenode = filenode, entries = entries) @@ -301,11 +336,21 @@ class hgweb: p1, p2 = fl.parents(n) t = float(cs[2].split(' ')[0]) mfn = cs[0] + + def lines(): + for l, t in enumerate(text.splitlines(1)): + yield self.t("fileline", + line = t, + linenumber = "% 6d" % (l + 1), + parity = l & 1) yield self.t("filerevision", file = f, + header = self.header(), + footer = self.footer(), + repo = self.reponame, filenode = node, path = up(f), - text = text, + text = lines(), rev = changerev, node = hex(cn), manifest = hex(mfn), @@ -313,6 +358,10 @@ class hgweb: age = age(t), date = time.asctime(time.gmtime(t)), shortdesc = cgi.escape(cs[4].splitlines()[0]), + parent1 = self.parent("filerevparent", + hex(p1), fl.rev(p1)), + parent2 = self.parent("filerevparent", + hex(p2), fl.rev(p2)), p1 = hex(p1), p2 = hex(p2), p1rev = fl.rev(p1), p2rev = fl.rev(p2)) @@ -332,6 +381,8 @@ class hgweb: mfn = cs[0] def annotate(): + parity = 1 + last = None for r, l in fl.annotate(n): try: cnode = ncache[r] @@ -348,7 +399,12 @@ class hgweb: name = name[:f] bcache[r] = name + if last != cnode: + parity = 1 - parity + last = cnode + yield self.t("annotateline", + parity = parity, node = hex(cnode), rev = r, author = name, @@ -356,6 +412,9 @@ class hgweb: line = cgi.escape(l)) yield self.t("fileannotate", + header = self.header(), + footer = self.footer(), + repo = self.reponame, file = f, filenode = node, annotate = annotate, @@ -367,6 +426,10 @@ class hgweb: age = age(t), date = time.asctime(time.gmtime(t)), shortdesc = cgi.escape(cs[4].splitlines()[0]), + parent1 = self.parent("filerevparent", + hex(p1), fl.rev(p1)), + parent2 = self.parent("filerevparent", + hex(p2), fl.rev(p2)), p1 = hex(p1), p2 = hex(p2), p1rev = fl.rev(p1), p2rev = fl.rev(p2)) @@ -375,10 +438,8 @@ class hgweb: rev = self.repo.manifest.rev(bin(mnode)) node = self.repo.changelog.node(rev) - dirs = {} files = {} - short = {} - + p = path[1:] l = len(p) @@ -388,37 +449,41 @@ class hgweb: remain = f[l:] if "/" in remain: short = remain[:remain.find("/") + 1] # bleah - dirs[short] = 1 + files[short] = (f, None) else: short = os.path.basename(remain) files[short] = (f, n) - 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 filelist(): + parity = 0 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) + if fnode: + yield self.t("manifestfileentry", + file = full, + manifest = mnode, + filenode = hex(fnode), + parity = parity, + basename = f) + else: + yield self.t("manifestdirentry", + parity = parity, + path = os.path.join(path, f), + manifest = mnode, basename = f[:-1]) + parity = 1 - parity yield self.t("manifest", + header = self.header(), + footer = self.footer(), + repo = self.reponame, manifest = mnode, rev = rev, node = hex(node), path = path, up = up(path), - dirs = dirlist, - files = filelist) + entries = filelist) def filediff(self, file, changeset): n = bin(changeset) @@ -431,6 +496,9 @@ class hgweb: yield self.diff(p1, n, file) yield self.t("filediff", + header = self.header(), + footer = self.footer(), + repo = self.reponame, file = file, filenode = hex(mf[file]), node = changeset, @@ -439,12 +507,7 @@ class hgweb: 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 diff --git a/templates/changelog.tmpl b/templates/changelog.tmpl --- a/templates/changelog.tmpl +++ b/templates/changelog.tmpl @@ -1,16 +1,13 @@ -Content-Type: text/html - - +#header# +#repo#: changelog +

changelog for #repo#

navigate: #changenav#
- -#changelist# -
+#entries# navigate: #changenav#
- - \ No newline at end of file +#footer# diff --git a/templates/changelogentry.tmpl b/templates/changelogentry.tmpl --- a/templates/changelogentry.tmpl +++ b/templates/changelogentry.tmpl @@ -1,26 +1,25 @@ +
+ - + - + +#parent1# +#parent2# - - - - - - - + - + - + - + +
#age# ago:#age# ago:  #shortdesc#
revision:revision:  #rev#:#node#
parent:#p1rev#:#p1#
parent:#p2rev#:#p2#
manifest:manifest:  #rev#:#manifest#
author:author:  #author#
date:date:  #date#
files:files:  #files#
+
- diff --git a/templates/changeset.tmpl b/templates/changeset.tmpl --- a/templates/changeset.tmpl +++ b/templates/changeset.tmpl @@ -1,42 +1,39 @@ -Content-type: text/html +#header# +#repo#: changeset #node# + + - - +
changelog manifest +

changeset: #shortdesc#

- + +#parent1# +#parent2# - - - - - - - + - + - + - + - +
revision:revision: #rev#:#node#
parent:#p1rev#:#p1#
parent:#p2rev#:#p2#
manifest:manifest: #rev#:#manifest#
author:author: #author#
date:date: #date#
files:files: #files#
description:description: #desc#
-
- -
+
 #diff#
 
diff --git a/templates/fileannotate.tmpl b/templates/fileannotate.tmpl --- a/templates/fileannotate.tmpl +++ b/templates/fileannotate.tmpl @@ -1,42 +1,39 @@ -Content-type: text/html - - +#header# +#repo#: #file# annotate + +
changelog changeset manifest file revisions +

Annotate #file# (#filenode#)

- + +#parent1# +#parent2# - - - - - - - + - + - +
changeset:changeset: #rev#:#node#
parent:#p1rev#:#p1#
parent:#p2rev#:#p2#
manifest:manifest: #rev#:#manifest#
author:author: #author#
date:date: #date#
-
+
- +
#annotate#
- - \ No newline at end of file +#footer# diff --git a/templates/filediff.tmpl b/templates/filediff.tmpl --- a/templates/filediff.tmpl +++ b/templates/filediff.tmpl @@ -1,30 +1,31 @@ -Content-type: text/html +#header# +#repo#: #file# diff + + - - +
changelog changeset file revisions annotate +

#file#

- + - +
revision:revision: #rev#:#node#
parent:parent: #p1rev#:#p1#
-
-
+
 #diff#
 
- - +#header# +#repo#: #file# history + +

#file# revision history

- #entries# -
- - \ No newline at end of file +#footer# diff --git a/templates/filelogentry.tmpl b/templates/filelogentry.tmpl --- a/templates/filelogentry.tmpl +++ b/templates/filelogentry.tmpl @@ -1,18 +1,19 @@ + - - + - + - + - + +
#age# ago:#shortdesc# + #age# ago: #shortdesc#
revision:revision:  #filerev#:#filenode# (diff) (annotate)
author:author:  #author#
date:date:  #date#
- diff --git a/templates/filerevision.tmpl b/templates/filerevision.tmpl --- a/templates/filerevision.tmpl +++ b/templates/filerevision.tmpl @@ -1,42 +1,37 @@ -Content-type: text/html - - +#header# +#repo#:#file# + +

#file# (revision #filenode#)

- + +#parent1# +#parent2# - - - - - - - + - + - +
changeset:changeset: #rev#:#node#
parent:#p1rev#:#p1#
parent:#p2rev#:#p2#
manifest:manifest: #rev#:#manifest#
author:author: #author#
date:date: #date#
-
-
 #text#
 
- - \ No newline at end of file +#footer# diff --git a/templates/footer.tmpl b/templates/footer.tmpl new file mode 100644 --- /dev/null +++ b/templates/footer.tmpl @@ -0,0 +1,2 @@ + + diff --git a/templates/header.tmpl b/templates/header.tmpl new file mode 100644 --- /dev/null +++ b/templates/header.tmpl @@ -0,0 +1,31 @@ +Content-type: text/html + + + + + + + + diff --git a/templates/manifest.tmpl b/templates/manifest.tmpl --- a/templates/manifest.tmpl +++ b/templates/manifest.tmpl @@ -1,19 +1,16 @@ -Content-Type: text/html - - +#header# +#repo#: manifest #manifest# + +

manifest: #path#

-

(#rev#:#manifest#)

-

-[up]
-#dirs#

+ +#entries# -

#files#

- - - \ No newline at end of file +#footer# \ No newline at end of file diff --git a/templates/map b/templates/map --- a/templates/map +++ b/templates/map @@ -1,3 +1,5 @@ +header = header.tmpl +footer = footer.tmpl changelog = changelog.tmpl naventry = "#rev# " filedifflink = "#file# " @@ -6,15 +8,20 @@ fileellipses = "..." changelogentry = changelogentry.tmpl changeset = changeset.tmpl manifest = manifest.tmpl -manifestdirentry = "#basename#/
" -manifestfileentry = "#basename#
" +manifestdirentry = "" +manifestfileentry = "" filerevision = filerevision.tmpl fileannotate = fileannotate.tmpl filediff = filediff.tmpl filelog = filelog.tmpl +fileline = "
#linenumber# #line#
" filelogentry = filelogentry.tmpl -annotateline = "#author#@#rev#:
#line#
" +annotateline = "#author#@#rev#
#line#
" difflineplus = "#line#" difflineminus = "#line#" difflineat = "#line#" -diffline = "#line#" \ No newline at end of file +diffline = "#line#" +changelogparent = "parent: #rev#:#node#" +changesetparent = "parent:#rev#:#node#" +filerevparent = "parent:#rev#:#node#" +fileannotateparent = "parent:#rev#:#node#"