changeset 7309:e74a9173c2d7

hgweb: use patch.diff() to make sensible diffs (issue1223, issue1258) This gets us git diffs when enabled and doesn't pick erratic file parents.
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Mon, 03 Nov 2008 20:05:03 +0100
parents b6f5490effbf
children bd522d09d5e3
files mercurial/hgweb/hgweb_mod.py tests/test-hgweb-diffs tests/test-hgweb-diffs.out
diffstat 3 files changed, 324 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/hgweb/hgweb_mod.py	Mon Nov 03 16:48:23 2008 +0100
+++ b/mercurial/hgweb/hgweb_mod.py	Mon Nov 03 20:05:03 2008 +0100
@@ -9,7 +9,7 @@
 import os, mimetypes
 from mercurial.node import hex, nullid
 from mercurial.repo import RepoError
-from mercurial import mdiff, ui, hg, util, patch, hook
+from mercurial import ui, hg, util, patch, hook, match
 from mercurial import revlog, templater, templatefilters
 from common import get_mtime, style_map, paritygen, countgen, ErrorResponse
 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
@@ -277,27 +277,11 @@
             yield tmpl("fileellipses")
 
     def diff(self, tmpl, node1, node2, files):
-        def filterfiles(filters, files):
-            l = [x for x in files if x in filters]
-
-            for t in filters:
-                if t and t[-1] != os.sep:
-                    t += os.sep
-                l += [x for x in files if x.startswith(t)]
-            return l
-
-        parity = paritygen(self.stripecount)
-        def diffblock(diff, f, fn):
-            yield tmpl("diffblock",
-                       lines=prettyprintlines(diff),
-                       parity=parity.next(),
-                       file=f,
-                       filenode=hex(fn or nullid))
 
         blockcount = countgen()
         def prettyprintlines(diff):
             blockno = blockcount.next()
-            for lineno, l in enumerate(diff.splitlines(1)):
+            for lineno, l in enumerate(diff.splitlines(True)):
                 if blockno == 0:
                     lineno = lineno + 1
                 else:
@@ -315,33 +299,24 @@
                            lineid="l%s" % lineno,
                            linenumber="% 8s" % lineno)
 
-        r = self.repo
-        c1 = r[node1]
-        c2 = r[node2]
-        date1 = util.datestr(c1.date())
-        date2 = util.datestr(c2.date())
+        if files:
+            m = match.exact(self.repo.root, self.repo.getcwd(), files)
+        else:
+            m = match.always(self.repo.root, self.repo.getcwd())
 
-        modified, added, removed, deleted, unknown = r.status(node1, node2)[:5]
-        if files:
-            modified, added, removed = map(lambda x: filterfiles(files, x),
-                                           (modified, added, removed))
-
+        block = []
+        parity = paritygen(self.stripecount)
         diffopts = patch.diffopts(self.repo.ui, untrusted=True)
-        for f in modified:
-            to = c1.filectx(f).data()
-            tn = c2.filectx(f).data()
-            yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f,
-                                          opts=diffopts), f, tn)
-        for f in added:
-            to = None
-            tn = c2.filectx(f).data()
-            yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f,
-                                          opts=diffopts), f, tn)
-        for f in removed:
-            to = c1.filectx(f).data()
-            tn = None
-            yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, f,
-                                          opts=diffopts), f, tn)
+        for chunk in patch.diff(self.repo, node1, node2, m, opts=diffopts):
+            if chunk.startswith('diff') and block:
+                yield tmpl('diffblock', parity=parity.next(),
+                           lines=prettyprintlines(''.join(block)))
+                block = []
+            if chunk.startswith('diff'):
+                chunk = ''.join(chunk.splitlines(True)[1:])
+            block.append(chunk)
+        yield tmpl('diffblock', parity=parity.next(),
+                   lines=prettyprintlines(''.join(block)))
 
     archive_specs = {
         'bz2': ('application/x-tar', 'tbz2', '.tar.bz2', None),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgweb-diffs	Mon Nov 03 20:05:03 2008 +0100
@@ -0,0 +1,34 @@
+echo % setting up repo
+hg init test
+cd test
+echo a > a
+echo b > b
+hg ci -Ama
+
+echo % change permissions for git diffs
+chmod 755 a
+hg ci -Amb
+
+echo % set up hgweb
+hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+cat hg.pid >> $DAEMON_PIDS
+
+echo % revision
+"$TESTDIR/get-with-headers.py" localhost:$HGPORT '/rev/0'
+
+echo % diff removed file
+"$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/a'
+
+echo % set up hgweb with git diffs
+kill `cat hg.pid`
+hg serve --config 'diff.git=1' -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+cat hg.pid >> $DAEMON_PIDS
+
+echo % revision
+"$TESTDIR/get-with-headers.py" localhost:$HGPORT '/rev/0'
+
+echo % diff removed file
+"$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/a'
+
+echo % errors
+cat errors.log
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgweb-diffs.out	Mon Nov 03 20:05:03 2008 +0100
@@ -0,0 +1,272 @@
+% setting up repo
+adding a
+adding b
+% change permissions for git diffs
+% set up hgweb
+% revision
+200 Script output follows
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="/static/hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="/static/style.css" type="text/css" />
+
+<title>test: changeset 0cd96de13884</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log/0">changelog</a>
+<a href="/shortlog/0">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/file/0cd96de13884">files</a>
+<a href="/raw-rev/0cd96de13884">raw</a>
+
+</div>
+
+<h2>changeset: a</h2>
+
+<table id="changesetEntry">
+<tr>
+ <th class="changeset">changeset 0:</th>
+ <td class="changeset"><a href="/rev/0cd96de13884">0cd96de13884</a></td>
+</tr>
+
+<tr><th class="child">child 1:</th><td class="child"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td></tr>
+
+<tr>
+ <th class="author">author:</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date:</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
+</tr>
+<tr>
+ <th class="files">files:</th>
+ <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
+</tr>
+<tr>
+ <th class="description">description:</th>
+ <td class="description">a</td>
+</tr>
+</table>
+
+<div id="changesetDiff">
+<pre class="parity0"><span class="minusline"><a class="lineno" href="#l1" id="l1">       1</a>--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><span class="plusline"><a class="lineno" href="#l2" id="l2">       2</a>+++ b/a	Thu Jan 01 00:00:00 1970 +0000
+</span><span class="atline"><a class="lineno" href="#l3" id="l3">       3</a>@@ -0,0 +1,1 @@
+</span><span class="plusline"><a class="lineno" href="#l4" id="l4">       4</a>+a
+</span></pre><pre class="parity1"><span class="minusline"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><span class="plusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>+++ b/b	Thu Jan 01 00:00:00 1970 +0000
+</span><span class="atline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>@@ -0,0 +1,1 @@
+</span><span class="plusline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>+b
+</span></pre>
+</div>
+
+
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+
+</body>
+</html>
+
+
+
+% diff removed file
+200 Script output follows
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="/static/hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="/static/style.css" type="text/css" />
+
+<title>test: a diff</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log/1">changelog</a>
+<a href="/shortlog/1">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/rev/78e4ebad7cdf">changeset</a>
+<a href="/file/78e4ebad7cdf/a">file</a>
+<a href="/log/78e4ebad7cdf/a">revisions</a>
+<a href="/annotate/78e4ebad7cdf/a">annotate</a>
+<a href="/raw-diff/78e4ebad7cdf/a">raw</a>
+</div>
+
+<h2>a</h2>
+
+<table id="filediffEntry">
+<tr>
+ <th class="revision">revision 1:</th>
+ <td class="revision"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+</tr>
+
+
+</table>
+
+<div id="fileDiff">
+<pre class="parity0"><span class="minusline"><a class="lineno" href="#l1" id="l1">       1</a>--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><span class="plusline"><a class="lineno" href="#l2" id="l2">       2</a>+++ b/a	Thu Jan 01 00:00:00 1970 +0000
+</span><span class="atline"><a class="lineno" href="#l3" id="l3">       3</a>@@ -0,0 +1,1 @@
+</span><span class="plusline"><a class="lineno" href="#l4" id="l4">       4</a>+a
+</span></pre>
+</div>
+
+
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+
+</body>
+</html>
+
+
+
+% set up hgweb with git diffs
+% revision
+200 Script output follows
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="/static/hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="/static/style.css" type="text/css" />
+
+<title>test: changeset 0cd96de13884</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log/0">changelog</a>
+<a href="/shortlog/0">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/file/0cd96de13884">files</a>
+<a href="/raw-rev/0cd96de13884">raw</a>
+
+</div>
+
+<h2>changeset: a</h2>
+
+<table id="changesetEntry">
+<tr>
+ <th class="changeset">changeset 0:</th>
+ <td class="changeset"><a href="/rev/0cd96de13884">0cd96de13884</a></td>
+</tr>
+
+<tr><th class="child">child 1:</th><td class="child"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td></tr>
+
+<tr>
+ <th class="author">author:</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date:</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
+</tr>
+<tr>
+ <th class="files">files:</th>
+ <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
+</tr>
+<tr>
+ <th class="description">description:</th>
+ <td class="description">a</td>
+</tr>
+</table>
+
+<div id="changesetDiff">
+<pre class="parity0"><a class="lineno" href="#l1" id="l1">       1</a>new file mode 100644
+<span class="minusline"><a class="lineno" href="#l2" id="l2">       2</a>--- /dev/null
+</span><span class="plusline"><a class="lineno" href="#l3" id="l3">       3</a>+++ b/a
+</span><span class="atline"><a class="lineno" href="#l4" id="l4">       4</a>@@ -0,0 +1,1 @@
+</span><span class="plusline"><a class="lineno" href="#l5" id="l5">       5</a>+a
+</span></pre><pre class="parity1"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>new file mode 100644
+<span class="minusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>--- /dev/null
+</span><span class="plusline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>+++ b/b
+</span><span class="atline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>@@ -0,0 +1,1 @@
+</span><span class="plusline"><a class="lineno" href="#l1.5" id="l1.5">     1.5</a>+b
+</span></pre>
+</div>
+
+
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+
+</body>
+</html>
+
+
+
+% diff removed file
+200 Script output follows
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="/static/hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="/static/style.css" type="text/css" />
+
+<title>test: a diff</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log/1">changelog</a>
+<a href="/shortlog/1">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/rev/78e4ebad7cdf">changeset</a>
+<a href="/file/78e4ebad7cdf/a">file</a>
+<a href="/log/78e4ebad7cdf/a">revisions</a>
+<a href="/annotate/78e4ebad7cdf/a">annotate</a>
+<a href="/raw-diff/78e4ebad7cdf/a">raw</a>
+</div>
+
+<h2>a</h2>
+
+<table id="filediffEntry">
+<tr>
+ <th class="revision">revision 1:</th>
+ <td class="revision"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+</tr>
+
+
+</table>
+
+<div id="fileDiff">
+<pre class="parity0"><a class="lineno" href="#l1" id="l1">       1</a>new file mode 100755
+<span class="minusline"><a class="lineno" href="#l2" id="l2">       2</a>--- /dev/null
+</span><span class="plusline"><a class="lineno" href="#l3" id="l3">       3</a>+++ b/a
+</span><span class="atline"><a class="lineno" href="#l4" id="l4">       4</a>@@ -0,0 +1,1 @@
+</span><span class="plusline"><a class="lineno" href="#l5" id="l5">       5</a>+a
+</span></pre>
+</div>
+
+
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+
+</body>
+</html>
+
+
+
+% errors