[patch][preliminary] hgweb: arbitrary diff support
Csaba Henk
csaba-ml at creo.hu
Fri May 19 09:17:02 CDT 2006
Hi folks,
The attached patch lets you view the diff of arbitrary two revisions via
the web interface.
TODO: cleanup template handling (in particular that of those parts which
appear optionally), add support for gitweb style interface.
However, I think the main question is if the UI is useable/acceptable,
or can be easily tuned to be so.
Regrads,
Csaba
# HG changeset patch
# User csaba.henk at creo.hu
# Node ID 3c2da2df1685dcce7c2936548806cfd75fdafadd
# Parent 4be9a79b49b177f5c44c4f32b22999ff5583880a
Add basic support for diffing arbitrary revisions via the web interface
- Add "diffnodes" cgi command for diffing arbitrary two revisions.
- Introduce the so-called "reference changeset". This can be set and
preserved in a changelog/changset context. When it's set, each
changelog entry will have a link to the diff taken against the ref cset.
- Changeset pages got a button which returns to the changelog with
setting the current changeset node as the ref cset; changelog page
got a button which clears the ref cset value.
diff -r 4be9a79b49b1 -r 3c2da2df1685 mercurial/hgweb.py
--- a/mercurial/hgweb.py Wed May 17 13:21:36 2006 -0500
+++ b/mercurial/hgweb.py Fri May 19 07:24:10 2006 +0200
@@ -222,7 +222,7 @@ class hgweb(object):
yield diffblock(mdiff.unidiff(to, date1, tn, date2, f,
showfunc=showfunc, ignorews=ignorews), f, tn)
- def changelog(self, pos):
+ def changelog(self, pos, ref=None):
def changenav(**map):
def seq(factor, maxchanges=None):
if maxchanges:
@@ -265,19 +265,28 @@ class hgweb(object):
changes = cl.read(n)
hn = hex(n)
- l.insert(0, {"parity": parity,
- "author": changes[1],
- "parent": self.siblings(cl.parents(n), cl.rev,
- cl.rev(n) - 1),
- "child": self.siblings(cl.children(n), cl.rev,
- cl.rev(n) + 1),
- "changelogtag": self.showtag("changelogtag",n),
- "manifest": hex(changes[0]),
- "desc": changes[4],
- "date": changes[2],
- "files": self.listfilediffs(changes[3], n),
- "rev": i,
- "node": hn})
+ dic = {"parity": parity,
+ "author": changes[1],
+ "parent": self.siblings(cl.parents(n), cl.rev,
+ cl.rev(n) - 1),
+ "child": self.siblings(cl.children(n), cl.rev,
+ cl.rev(n) + 1),
+ "changelogtag": self.showtag("changelogtag",n),
+ "manifest": hex(changes[0]),
+ "desc": changes[4],
+ "date": changes[2],
+ "files": self.listfilediffs(changes[3], n),
+ "rev": i,
+ "node": hn,
+ "nodesave": hn}
+
+ if ref and refrev != i:
+ dic["ref"] = ref
+ dic["refrev"] = [[[str(refrev), ""], ["", ""]]]
+ else:
+ dic["refrev"] = []
+
+ l.insert(0, dic)
parity = 1 - parity
for e in l:
@@ -290,10 +299,17 @@ class hgweb(object):
end = min(count, start + self.maxchanges)
pos = end - 1
+ if ref:
+ refrev = cl.rev(self.repo.lookup(ref))
+ refhack = [[["",""],["",""]]]
+ else:
+ refhack = []
+
yield self.t('changelog',
changenav=changenav,
manifest=hex(mf),
rev=pos, changesets=count, entries=changelist,
+ ref=ref or "", refhack=refhack,
archives=self.archivelist("tip"))
def search(self, query):
@@ -352,7 +368,7 @@ class hgweb(object):
manifest=hex(mf),
entries=changelist)
- def changeset(self, nodeid):
+ def changeset(self, nodeid, ref=None):
cl = self.repo.changelog
n = self.repo.lookup(nodeid)
nodeid = hex(n)
@@ -380,7 +396,31 @@ class hgweb(object):
desc=changes[4],
date=changes[2],
files=files,
+ ref = ref or "",
archives=self.archivelist(nodeid))
+
+ def diffnodes(self, nodeid0, nodeid1, files):
+ cl = self.repo.changelog
+ ns = [ self.repo.lookup(nodeid) for nodeid in [nodeid0, nodeid1] ]
+ nodeids = [ hex(n) for n in ns ]
+ revs = [ cl.rev(n) for n in ns ]
+ if revs[0] > revs[1]:
+ for x in ns, nodeids, revs:
+ x.reverse()
+
+ def diff(**map):
+ yield self.diff(ns[0], ns[1], files)
+
+ if files:
+ files = " ".join(files)
+
+ yield self.t('diffnodes',
+ diff=diff,
+ rev0=revs[0],
+ node0=nodeids[0],
+ rev1=revs[1],
+ node1=nodeids[1],
+ files=files)
def filelog(self, f, filenode):
cl = self.repo.changelog
@@ -802,10 +842,32 @@ class hgweb(object):
req.write(self.search(hi)) # XXX redirect to 404 page?
return
- req.write(self.changelog(hi))
+ if req.form.has_key('ref'):
+ ref = req.form['ref'][0]
+ else:
+ ref = None
+
+ req.write(self.changelog(hi, ref))
elif cmd == 'changeset':
- req.write(self.changeset(req.form['node'][0]))
+ if req.form.has_key('ref'):
+ ref = req.form['ref'][0]
+ else:
+ ref = None
+
+ req.write(self.changeset(req.form['node'][0], ref))
+
+ elif cmd == 'diffnodes':
+ if req.form.has_key('files'):
+ if req.form.has_key('filesep'):
+ filesep = req.form['filesep'][0]
+ else:
+ filesep = ' '
+ files = req.form['files'][0].split(filesep)
+ else:
+ files = None
+ req.write(self.diffnodes(req.form['node0'][0],
+ req.form['node1'][0], files))
elif cmd == 'manifest':
req.write(self.manifest(req.form['manifest'][0],
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/changelog.tmpl
--- a/templates/changelog.tmpl Wed May 17 13:21:36 2006 -0500
+++ b/templates/changelog.tmpl Fri May 19 07:24:10 2006 +0200
@@ -10,6 +10,7 @@
<a href="?mf=#manifest|short#;path=/">manifest</a>
#archives%archiveentry#
<a type="application/rss+xml" href="?style=rss">rss</a>
+#refhack%resetref#
</div>
<h2>changelog for #repo|escape#</h2>
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/changelogentry.tmpl
--- a/templates/changelogentry.tmpl Wed May 17 13:21:36 2006 -0500
+++ b/templates/changelogentry.tmpl Fri May 19 07:24:10 2006 +0200
@@ -5,7 +5,7 @@
</tr>
<tr>
<th class="revision">changeset #rev#:</th>
- <td class="node"><a href="?cs=#node|short#">#node|short#</a></td>
+ <td class="node"><a href="?cs=#node|short#;ref=#ref#">#node|short#</a></td>
</tr>
#parent%changelogparent#
#child%changelogchild#
@@ -22,4 +22,5 @@
<th class="files"><a href="?mf=#manifest|short#;path=/">files</a>:</th>
<td class="files">#files#</td>
</tr>
+ #refrev%diffvs#
</table>
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/changeset.tmpl
--- a/templates/changeset.tmpl Wed May 17 13:21:36 2006 -0500
+++ b/templates/changeset.tmpl Fri May 19 07:24:10 2006 +0200
@@ -4,7 +4,8 @@
<body>
<div class="buttons">
-<a href="?cl=#rev#">changelog</a>
+<a href="?cl=#rev#;ref=#ref#">changelog</a>
+<a href="?cl=#rev#;ref=#node|short#">chlog + set ref cset</a>
<a href="?cmd=tags">tags</a>
<a href="?mf=#manifest|short#;path=/">manifest</a>
<a href="?cs=#node|short#;style=raw">raw</a>
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/map
--- a/templates/map Wed May 17 13:21:36 2006 -0500
+++ b/templates/map Fri May 19 07:24:10 2006 +0200
@@ -3,13 +3,15 @@ footer = footer.tmpl
footer = footer.tmpl
search = search.tmpl
changelog = changelog.tmpl
-naventry = '<a href="?cl=#rev#">#label|escape#</a> '
+naventry = '<a href="?cl=#rev#;ref=#ref#">#label|escape#</a> '
filedifflink = '<a href="?fd=#node|short#;file=#file|urlescape#">#file|escape#</a> '
filenodelink = '<a href="?f=#filenode|short#;file=#file|urlescape#">#file|escape#</a> '
fileellipses = '...'
changelogentry = changelogentry.tmpl
searchentry = changelogentry.tmpl
changeset = changeset.tmpl
+diffnodes = diffnodes.tmpl
+resetref = '<a href="?cl=#rev#">reset ref cset</a>'
manifest = manifest.tmpl
manifestdirentry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt> <td><a href="?cmd=manifest;manifest=#manifest#;path=#path|urlescape#">#basename|escape#/</a>'
manifestfileentry = '<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt> <td><a href="?f=#filenode|short#;file=#file|urlescape#">#basename|escape#</a>'
@@ -26,6 +28,7 @@ diffline = '#line|escape#'
diffline = '#line|escape#'
changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
changesetparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>'
+diffvs = '<tr><th class="refrev">diff to #refrev#:</th><td class="refrev"><a href="?cmd=diffnodes;node0=#nodesave|short#;node1=#ref#">#ref#</a></td></tr>'
filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#node|short#</a></td></tr>'
filerename = '<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file|urlescape#">#file|escape#@#node|short#</a></td></tr>'
filelogrename = '<tr><th>base:</th><td><a href="?f=#node|short#;file=#file|urlescape#">#file|escape#@#node|short#</a></td></tr>'
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/map-raw
--- a/templates/map-raw Wed May 17 13:21:36 2006 -0500
+++ b/templates/map-raw Fri May 19 07:24:10 2006 +0200
@@ -14,3 +14,4 @@ filediff = filediff-raw.tmpl
filediff = filediff-raw.tmpl
fileannotate = fileannotate-raw.tmpl
annotateline = '#author#@#rev#: #line#'
+diffnodes = diffnodes-raw.tmpl
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/diffnodes-raw.tmpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/diffnodes-raw.tmpl Fri May 19 07:24:10 2006 +0200
@@ -0,0 +1,7 @@
+#header#
+# HG diff
+# changeset0 #rev0#: #node0|short#
+# changeset1 #rev1#: #node1|short#
+# files: #files#
+
+#diff#
diff -r 4be9a79b49b1 -r 3c2da2df1685 templates/diffnodes.tmpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/diffnodes.tmpl Fri May 19 07:24:10 2006 +0200
@@ -0,0 +1,30 @@
+#header#
+<title>#repo|escape#: diff #rev0# => #rev1#</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="?cmd=diffnodes;node0=#node0|short#;node1=#node1|short#;style=raw">raw</a>
+</div>
+
+<h2>diff: #rev0# => #rev1#</h2>
+
+<table id="changesetEntry">
+<tr>
+ <th class="changeset">changeset0 #rev0#:</th>
+ <td class="changeset"><a href="?cs=#node0|short#">#node0|short#</a></td>
+</tr>
+<tr>
+ <th class="changeset">changeset1 #rev1#:</th>
+ <td class="changeset"><a href="?cs=#node1|short#">#node1|short#</a></td>
+</tr>
+<tr>
+ <th class="files">files:</th>
+ <td class="files">#files#</td></tr>
+</table>
+
+<div id="changesetDiff">
+#diff#
+</div>
+
+#footer#
More information about the Mercurial
mailing list