# HG changeset patch # User Nicolas Dumazet # Date 1281881873 -32400 # Node ID 99cafcae25d995554156e2adf34c91b9cb12763c # Parent 7dc8b9e25f1946fe400bc0f354b7408fd96cbde3 log: do not --follow file that is deleted and recreated later (issue732) == What == issue732 is only one example of a buggy behaviour, but there are in fact many intricated cases. For example: ( "o" contains an alive version of the tracked file, "x" does not) tip - o - o - x - o - o - x ... \ o - o - o - o - x ... \ / o - o This repository contains at least two instances of the tracked file, but when calling "hg log -f file" only the latest one (the one alive in tip) matters to us. == How == We must extract from the filelog the history of the file instance we're interested in and discard changes related to other instances of that file. We see that we're only interested in ancestors(node), and that all other nodes in the filelog should not be considered. diff -r 7dc8b9e25f19 -r 99cafcae25d9 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Sun Aug 15 22:44:15 2010 +0900 +++ b/mercurial/cmdutil.py Sun Aug 15 23:17:53 2010 +0900 @@ -1059,8 +1059,14 @@ # We only have to read through the filelog to find wanted revisions minrev, maxrev = min(revs), max(revs) - # Only files, no patterns. Check the history of each file. def filerevgen(filelog, last): + """ + Only files, no patterns. Check the history of each file. + + Examines filelog entries within minrev, maxrev linkrev range + Returns an iterator yielding (linkrev, parentlinkrevs, copied) + tuples in backwards order + """ cl_count = len(repo) revs = [] for j in xrange(0, last + 1): @@ -1071,8 +1077,13 @@ # happen while doing "hg log" during a pull or commit if linkrev > maxrev or linkrev >= cl_count: break + + parentlinkrevs = [] + for p in filelog.parentrevs(j): + if p != nullrev: + parentlinkrevs.append(filelog.linkrev(p)) n = filelog.node(j) - revs.append((filelog.linkrev(j), + revs.append((linkrev, parentlinkrevs, follow and filelog.renamed(n))) for rev in reversed(revs): @@ -1101,7 +1112,18 @@ else: last = filelog.rev(node) - for rev, copied in filerevgen(filelog, last): + + # keep track of all ancestors of the file + ancestors = set([filelog.linkrev(last)]) + + # iterate from latest to oldest revision + for rev, flparentlinkrevs, copied in filerevgen(filelog, last): + if rev not in ancestors: + continue + # XXX insert 1327 fix here + if flparentlinkrevs: + ancestors.update(flparentlinkrevs) + fncache.setdefault(rev, []) fncache[rev].append(file_) wanted.add(rev) diff -r 7dc8b9e25f19 -r 99cafcae25d9 tests/test-log --- a/tests/test-log Sun Aug 15 22:44:15 2010 +0900 +++ b/tests/test-log Sun Aug 15 23:17:53 2010 +0900 @@ -200,4 +200,53 @@ hg log -p -R .. ../a +cd .. +hg init follow2 +cd follow2 + +# Build the following history: +# tip - o - x - o - x - x +# \ / +# o - o - o - x +# \ / +# o +# +# Where "o" is a revision containing "foo" and +# "x" is a revision without "foo" +touch init +hg ci -A -m "init, unrelated" +echo 'foo' > init +hg ci -m "change, unrelated" +echo 'foo' > foo +hg ci -A -m "add unrelated old foo" +hg rm foo +hg ci -m "delete foo, unrelated" +echo 'related' > foo +hg ci -A -m "add foo, related" + +hg up 0 +touch branch +hg ci -A -m "first branch, unrelated" +touch foo +hg ci -A -m "create foo, related" +echo 'change' > foo +hg ci -m "change foo, related" + +hg up 6 +echo 'change foo in branch' > foo +hg ci -m "change foo in branch, related" +hg merge 7 +echo 'merge 1' > foo +hg resolve -m foo +hg ci -m "First merge, related" + +hg merge 4 +echo 'merge 2' > foo +hg resolve -m foo +hg ci -m "Last merge, related" + +hg --config "extensions.graphlog=" glog + +hg --traceback log -f foo + exit 0 diff -r 7dc8b9e25f19 -r 99cafcae25d9 tests/test-log.out --- a/tests/test-log.out Sun Aug 15 22:44:15 2010 +0900 +++ b/tests/test-log.out Sun Aug 15 23:17:53 2010 +0900 @@ -611,3 +611,120 @@ @@ -0,0 +1,1 @@ +a +adding init +adding foo +adding foo +1 files updated, 0 files merged, 1 files removed, 0 files unresolved +adding branch +created new head +adding foo +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +created new head +merging foo +warning: conflicts during merge. +merging foo failed! +0 files updated, 0 files merged, 0 files removed, 1 files unresolved +use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon +merging foo +warning: conflicts during merge. +merging foo failed! +1 files updated, 0 files merged, 0 files removed, 1 files unresolved +use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon +@ changeset: 10:4dae8563d2c5 +|\ tag: tip +| | parent: 9:7b35701b003e +| | parent: 4:88176d361b69 +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: Last merge, related +| | +| o changeset: 9:7b35701b003e +| |\ parent: 8:e5416ad8a855 +| | | parent: 7:87fe3144dcfa +| | | user: test +| | | date: Thu Jan 01 00:00:00 1970 +0000 +| | | summary: First merge, related +| | | +| | o changeset: 8:e5416ad8a855 +| | | parent: 6:dc6c325fe5ee +| | | user: test +| | | date: Thu Jan 01 00:00:00 1970 +0000 +| | | summary: change foo in branch, related +| | | +| o | changeset: 7:87fe3144dcfa +| |/ user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: change foo, related +| | +| o changeset: 6:dc6c325fe5ee +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: create foo, related +| | +| o changeset: 5:73db34516eb9 +| | parent: 0:e87515fd044a +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: first branch, unrelated +| | +o | changeset: 4:88176d361b69 +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: add foo, related +| | +o | changeset: 3:dd78ae4afb56 +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: delete foo, unrelated +| | +o | changeset: 2:c4c64aedf0f7 +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: add unrelated old foo +| | +o | changeset: 1:e5faa7440653 +|/ user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: change, unrelated +| +o changeset: 0:e87515fd044a + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: init, unrelated + +changeset: 10:4dae8563d2c5 +tag: tip +parent: 9:7b35701b003e +parent: 4:88176d361b69 +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: Last merge, related + +changeset: 9:7b35701b003e +parent: 8:e5416ad8a855 +parent: 7:87fe3144dcfa +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: First merge, related + +changeset: 8:e5416ad8a855 +parent: 6:dc6c325fe5ee +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: change foo in branch, related + +changeset: 7:87fe3144dcfa +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: change foo, related + +changeset: 6:dc6c325fe5ee +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: create foo, related + +changeset: 4:88176d361b69 +user: test +date: Thu Jan 01 00:00:00 1970 +0000 +summary: add foo, related +