hgweb: use introrev() for finding parents (
issue4506)
The issue is titled "filtered revision 'XXX' (not in 'served' subset)" and that
is the error message you sometimes get when trying to look at a file (/file or
/annotate) in hgweb. For example:
http://hg.intevation.org/mercurial/crew/file/
90cf454edd70/mercurial/cmdutil.py
This happens when a parent revision for a file is hidden, thus it is
not 'served' and isn't accessible in hgweb by default. When hgweb tries to
access such changeset, it produces the error and HTTP status code 404.
Another detail is that the parents() function, that is used in multiple places
in hgweb, sometimes returned changesets that were obsoleted by the current
changeset for the file. For example, when using rebase with evolve and rebasing
a divergent changeset that introduces a file on top of current branch. Or
grafting a change and making the new grafted changeset obsolete the source
(shown in the test case). The result is the same - the obsoleted changeset was
mistakingly returned from parents(), even though it's not a parent and the only
link to the new changeset is an obsoletion marker (and rebase/graft metadata?
not sure it matters).
The problem is fixed by using introrev() instead of linkrev() for finding
parents. This prevents parents() function from returning unrelated obsolete
changesets.
The test case prepares a separate repo because (afaict) all other test cases
never reuse file names, so there are no files that were changed in multiple
changesets. So no previously available files have obsolete changesets in their
history.
--- a/mercurial/hgweb/webutil.py Sun Feb 08 00:56:40 2015 -0500
+++ b/mercurial/hgweb/webutil.py Thu Feb 19 19:32:06 2015 +0800
@@ -138,9 +138,10 @@
yield d
def parents(ctx, hide=None):
- if (isinstance(ctx, context.basefilectx) and
- ctx.changectx().rev() != ctx.linkrev()):
- return _siblings([ctx._repo[ctx.linkrev()]], hide)
+ if isinstance(ctx, context.basefilectx):
+ introrev = ctx.introrev()
+ if ctx.changectx().rev() != introrev:
+ return _siblings([ctx._repo[introrev]], hide)
return _siblings(ctx.parents(), hide)
def children(ctx, hide=None):
--- a/tests/test-obsolete.t Sun Feb 08 00:56:40 2015 -0500
+++ b/tests/test-obsolete.t Thu Feb 19 19:32:06 2015 +0800
@@ -754,6 +754,45 @@
visible 0:193e9254ce7e
tip 0:193e9254ce7e
+#if serve
+
+Test issue 4506
+
+ $ cd ..
+ $ hg init repo-issue4506
+ $ cd repo-issue4506
+ $ echo "0" > foo
+ $ hg add foo
+ $ hg ci -m "content-0"
+
+ $ hg up null
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ echo "1" > bar
+ $ hg add bar
+ $ hg ci -m "content-1"
+ created new head
+ $ hg up 0
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg graft 1
+ grafting 1:1c9eddb02162 "content-1" (tip)
+
+ $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
+
+ $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+ $ cat hg.pid >> $DAEMON_PIDS
+
+ $ "$TESTDIR/get-with-headers.py" --headeronly localhost:$HGPORT 'rev/1'
+ 404 Not Found
+ [1]
+ $ "$TESTDIR/get-with-headers.py" --headeronly localhost:$HGPORT 'file/tip/bar'
+ 200 Script output follows
+ $ "$TESTDIR/get-with-headers.py" --headeronly localhost:$HGPORT 'annotate/tip/bar'
+ 200 Script output follows
+
+ $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
+
+#endif
+
$ hg init a
$ cd a
$ touch foo