Patchwork [2,of,2] linkrev-filelog: handle filtered linkrev with no visible children (issue4307)

login
register
mail settings
Submitter Pierre-Yves David
Date Jan. 2, 2015, 6:50 a.m.
Message ID <99384eba145190237924.1420181438@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/7298/
State Accepted
Headers show

Comments

Pierre-Yves David - Jan. 2, 2015, 6:50 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1419906923 28800
#      Mon Dec 29 18:35:23 2014 -0800
# Node ID 99384eba14519023792496d2db739d14b8c92ba8
# Parent  ddf4f983fde248df05e45229af5e173ba7680ca8
linkrev-filelog: handle filtered linkrev with no visible children (issue4307)

If the file revision with a filtered linkrev does not have any (unfiltered)
children, we cannot use it to bound the search for another introduction.
Instead, we have to look at the file revision used by all head changesets. If
one of them use this file revision, we know there is other occurrence and we have
a starting point. See inline comments for details.

Adding some kind of permanent reference of all the introduction of a
file revision instead of just the first one would be much better. But this is
more difficult. I hope to take that into account in the next repository format.
Matt Mackall - Jan. 2, 2015, 11:18 p.m.
On Thu, 2015-01-01 at 22:50 -0800, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1419906923 28800
> #      Mon Dec 29 18:35:23 2014 -0800
> # Node ID 99384eba14519023792496d2db739d14b8c92ba8
> # Parent  ddf4f983fde248df05e45229af5e173ba7680ca8
> linkrev-filelog: handle filtered linkrev with no visible children (issue4307)

These are queued for default, thanks.

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -790,10 +790,11 @@  def filelog(repo, subset, x):
 
     for f in files:
         backrevref = {}  # final value for: changerev -> filerev
         lowestchild = {} # lowest known filerev child of a filerev
         delayed = []     # filerev with filtered linkrev, for post-processing
+        lowesthead = None # cache for manifest content of all head revisions
         fl = repo.file(f)
         for fr in list(fl):
             lkr = rev = fl.linkrev(fr)
             if rev not in cl:
                 # changerev pointed in linkrev is filtered
@@ -823,13 +824,28 @@  def filelog(repo, subset, x):
             lkr = rev
 
             child = lowestchild.get(fr)
 
             if child is None:
-                # XXX content could be linkrev-shadowed in a head, but lets
-                # ignore this case for now.
-                continue
+                # search for existence of this file revision in a head revision.
+                # There is three possibilities:
+                # - the revision exists in a head and we can find an
+                #   introduction from there,
+                # - the revision does not exist in a head because it has been
+                #   changed since its introduction: we would have found a child
+                #   and be in the other 'else' clause,
+                # - all versions of the revision are hidden.
+                if lowesthead is None:
+                    lowesthead = {}
+                    for h in repo.heads():
+                        fnode = repo[h].manifest()[f]
+                        lowesthead[fl.rev(fnode)] = h
+                headrev = lowesthead.get(fr)
+                if headrev is None:
+                    # content is nowhere unfiltered
+                    continue
+                rev = repo[headrev][f].introrev()
             else:
                 # the lowest known child is a good upper bound
                 childcrev = backrevref[child]
                 # XXX this does not grantee to return the lowest introduction
                 # of this revision, but this give result which a good start and
diff --git a/tests/test-log.t b/tests/test-log.t
--- a/tests/test-log.t
+++ b/tests/test-log.t
@@ -1723,6 +1723,24 @@  Check that log on the file does not drop
      user:        test
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     content1
   
 
+Even when a head content is linkrev-shadowed.
+
+  $ hg log -T '{node}\n' -r 4
+  50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
+  $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
+  $ hg log -G a
+  @  changeset:   3:15b2327059e5
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     content2
+  |
+  o  changeset:   0:ae0a3c9f9e95
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     content1
+  
+
   $ cd ..