# HG changeset patch # User Pierre-Yves David # Date 1419906923 28800 # Node ID 8ec03e0ef51a863a8d5a977cdd275313355c8d00 # Parent 34364a4b25ebc62148fd012fe3ecb385872e5547 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 each head changeset. If one of them uses this file revision, we know there is another occurrence and we have a starting point. See inline comments for details. Adding some kind of permanent reference of all the introductions 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. diff -r 34364a4b25eb -r 8ec03e0ef51a mercurial/revset.py --- a/mercurial/revset.py Mon Dec 29 17:23:16 2014 -0800 +++ b/mercurial/revset.py Mon Dec 29 18:35:23 2014 -0800 @@ -792,6 +792,7 @@ 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) @@ -825,9 +826,24 @@ 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 are 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] diff -r 34364a4b25eb -r 8ec03e0ef51a tests/test-log.t --- a/tests/test-log.t Mon Dec 29 17:23:16 2014 -0800 +++ b/tests/test-log.t Mon Dec 29 18:35:23 2014 -0800 @@ -1725,4 +1725,22 @@ summary: content1 +Even when a head revision 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 ..