changeset 7300:591767e6ea7a

hgweb: conditionally show file logs for deleted files
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Sat, 01 Nov 2008 13:07:24 +0100
parents 288dda59233c
children 00d76fa3ffba
files mercurial/hgweb/webcommands.py tests/test-hgweb-filelog tests/test-hgweb-filelog.out
diffstat 3 files changed, 482 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/hgweb/webcommands.py	Sat Nov 01 13:07:20 2008 +0100
+++ b/mercurial/hgweb/webcommands.py	Sat Nov 01 13:07:24 2008 +0100
@@ -500,15 +500,30 @@
                 permissions=fctx.manifest().flags(f))
 
 def filelog(web, req, tmpl):
-    fctx = webutil.filectx(web.repo, req)
-    f = fctx.path()
-    fl = fctx.filelog()
-    count = len(fl)
+
+    try:
+        fctx = webutil.filectx(web.repo, req)
+        f = fctx.path()
+        fl = fctx.filelog()
+    except revlog.LookupError:
+        f = webutil.cleanpath(web.repo, req.form['file'][0])
+        fl = web.repo.file(f)
+        numrevs = len(fl)
+        if not numrevs: # file doesn't exist at all
+            raise
+        rev = webutil.changectx(web.repo, req).rev()
+        first = fl.linkrev(fl.node(0))
+        if rev < first: # current rev is from before file existed
+            raise
+        frev = numrevs - 1
+        while fl.linkrev(fl.node(frev)) > rev:
+            frev -= 1
+        fctx = web.repo.filectx(f, fl.linkrev(fl.node(frev)))
+
+    count = fctx.filerev() + 1
     pagelen = web.maxshortchanges
-    pos = fctx.filerev()
-    start = max(0, pos - pagelen + 1)
-    end = min(count, start + pagelen)
-    pos = end - 1
+    start = max(0, fctx.filerev() - pagelen + 1) # first rev on this page
+    end = min(count, start + pagelen) # last rev on this page
     parity = paritygen(web.stripecount, offset=start-end)
 
     def entries(limit=0, **map):
@@ -535,7 +550,7 @@
             yield e
 
     nodefunc = lambda x: fctx.filectx(fileid=x)
-    nav = webutil.revnavgen(pos, pagelen, count, nodefunc)
+    nav = webutil.revnavgen(end - 1, pagelen, count, nodefunc)
     return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
                 entries=lambda **x: entries(limit=0, **x),
                 latestentry=lambda **x: entries(limit=1, **x))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgweb-filelog	Sat Nov 01 13:07:24 2008 +0100
@@ -0,0 +1,40 @@
+hg init test
+cd test
+
+echo b > b
+hg ci -Am "b"
+
+echo a > a
+hg ci -Am "first a"
+
+hg rm a
+hg ci -m "del a"
+
+echo b > a
+hg ci -Am "second a"
+
+hg rm a
+hg ci -m "del2 a"
+
+hg log -p
+
+hg serve -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
+cat hg.pid >> $DAEMON_PIDS
+
+echo % tip - two revisions
+("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log/tip/a')
+
+echo % second version - two revisions
+("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log/3/a')
+
+echo % first deleted - one revision
+("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log/2/a')
+
+echo % first version - one revision
+("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log/1/a')
+
+echo % before addition - error
+("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/log/0/a')
+
+echo % errors
+cat errors.log
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgweb-filelog.out	Sat Nov 01 13:07:24 2008 +0100
@@ -0,0 +1,418 @@
+adding b
+adding a
+adding a
+changeset:   4:52e848cdcd88
+tag:         tip
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     del2 a
+
+diff -r 01de2d66a28d -r 52e848cdcd88 a
+--- a/a	Thu Jan 01 00:00:00 1970 +0000
++++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+@@ -1,1 +0,0 @@
+-b
+
+changeset:   3:01de2d66a28d
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     second a
+
+diff -r be3ebcc91739 -r 01de2d66a28d a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:00 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+changeset:   2:be3ebcc91739
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     del a
+
+diff -r 5ed941583260 -r be3ebcc91739 a
+--- a/a	Thu Jan 01 00:00:00 1970 +0000
++++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+@@ -1,1 +0,0 @@
+-a
+
+changeset:   1:5ed941583260
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     first a
+
+diff -r 6563da9dcf87 -r 5ed941583260 a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:00 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+changeset:   0:6563da9dcf87
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     b
+
+diff -r 000000000000 -r 6563da9dcf87 b
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b	Thu Jan 01 00:00:00 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+% tip - two revisions
+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 history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="/atom-log/tip/a" title="Atom feed for test:a">
+<link rel="alternate" type="application/rss+xml"
+   href="/rss-log/tip/a" title="RSS feed for test:a">
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log">changelog</a>
+<a href="/shortlog">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/file/01de2d66a28d/a">file</a>
+<a href="/annotate/01de2d66a28d/a">annotate</a>
+<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
+<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
+</div>
+
+<h2>a revision history</h2>
+
+<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
+
+<table class="logEntry parity0">
+ <tr>
+  <th class="age">38 years ago:</th>
+  <th class="firstline"><a href="/rev/01de2d66a28d">second a</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision 1:</td>
+  <td class="node">
+   <a href="/file/01de2d66a28d/a">01de2d66a28d</a>
+   <a href="/diff/01de2d66a28d/a">(diff)</a>
+   <a href="/annotate/01de2d66a28d/a">(annotate)</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</td>
+ </tr>
+</table>
+
+
+<table class="logEntry parity1">
+ <tr>
+  <th class="age">38 years ago:</th>
+  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision 0:</td>
+  <td class="node">
+   <a href="/file/5ed941583260/a">5ed941583260</a>
+   <a href="/diff/5ed941583260/a">(diff)</a>
+   <a href="/annotate/5ed941583260/a">(annotate)</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</td>
+ </tr>
+</table>
+
+
+
+
+
+<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>
+
+% second version - two revisions
+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 history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="/atom-log/tip/a" title="Atom feed for test:a">
+<link rel="alternate" type="application/rss+xml"
+   href="/rss-log/tip/a" title="RSS feed for test:a">
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log">changelog</a>
+<a href="/shortlog">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/file/01de2d66a28d/a">file</a>
+<a href="/annotate/01de2d66a28d/a">annotate</a>
+<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
+<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
+</div>
+
+<h2>a revision history</h2>
+
+<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
+
+<table class="logEntry parity0">
+ <tr>
+  <th class="age">38 years ago:</th>
+  <th class="firstline"><a href="/rev/01de2d66a28d">second a</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision 1:</td>
+  <td class="node">
+   <a href="/file/01de2d66a28d/a">01de2d66a28d</a>
+   <a href="/diff/01de2d66a28d/a">(diff)</a>
+   <a href="/annotate/01de2d66a28d/a">(annotate)</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</td>
+ </tr>
+</table>
+
+
+<table class="logEntry parity1">
+ <tr>
+  <th class="age">38 years ago:</th>
+  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision 0:</td>
+  <td class="node">
+   <a href="/file/5ed941583260/a">5ed941583260</a>
+   <a href="/diff/5ed941583260/a">(diff)</a>
+   <a href="/annotate/5ed941583260/a">(annotate)</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</td>
+ </tr>
+</table>
+
+
+
+
+
+<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>
+
+% first deleted - one 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: a history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="/atom-log/tip/a" title="Atom feed for test:a">
+<link rel="alternate" type="application/rss+xml"
+   href="/rss-log/tip/a" title="RSS feed for test:a">
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log">changelog</a>
+<a href="/shortlog">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/file/5ed941583260/a">file</a>
+<a href="/annotate/5ed941583260/a">annotate</a>
+<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
+<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
+</div>
+
+<h2>a revision history</h2>
+
+<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
+
+<table class="logEntry parity0">
+ <tr>
+  <th class="age">38 years ago:</th>
+  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision 0:</td>
+  <td class="node">
+   <a href="/file/5ed941583260/a">5ed941583260</a>
+   <a href="/diff/5ed941583260/a">(diff)</a>
+   <a href="/annotate/5ed941583260/a">(annotate)</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</td>
+ </tr>
+</table>
+
+
+
+
+
+<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>
+
+% first version - one 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: a history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="/atom-log/tip/a" title="Atom feed for test:a">
+<link rel="alternate" type="application/rss+xml"
+   href="/rss-log/tip/a" title="RSS feed for test:a">
+</head>
+<body>
+
+<div class="buttons">
+<a href="/log">changelog</a>
+<a href="/shortlog">shortlog</a>
+<a href="/graph">graph</a>
+<a href="/tags">tags</a>
+<a href="/file/5ed941583260/a">file</a>
+<a href="/annotate/5ed941583260/a">annotate</a>
+<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
+<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
+</div>
+
+<h2>a revision history</h2>
+
+<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
+
+<table class="logEntry parity0">
+ <tr>
+  <th class="age">38 years ago:</th>
+  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision 0:</td>
+  <td class="node">
+   <a href="/file/5ed941583260/a">5ed941583260</a>
+   <a href="/diff/5ed941583260/a">(diff)</a>
+   <a href="/annotate/5ed941583260/a">(annotate)</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</td>
+ </tr>
+</table>
+
+
+
+
+
+<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>
+
+% before addition - error
+404 Not Found
+
+<!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>Mercurial Error</title>
+</head>
+<body>
+
+<h2>Mercurial Error</h2>
+
+<p>
+An error occurred while processing your request:
+</p>
+<p>
+a@6563da9dcf87: not found in manifest
+</p>
+
+
+<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