diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2855,6 +2855,39 @@ fparent1, fparent2 = fparent2, nullid elif fparent2 in fparentancestors: fparent2 = nullid + elif not fparentancestors: + # The two file seems entirely unrelated, one might be a full + # replacement of the other. + # + # At that point, the logic get complicated enough that we reuse + # the existing one. + # + # Ideally, we would store this information in the mergestate a + # simply reuse it. It could probably simplify the surounding + # code too. + p1ctx = fctx._changectx.p1() + p2ctx = fctx._changectx.p2() + matcher = matchmod.exact([fctx.path()]) + if self.ui.configlist(b'merge', b'preferancestor') == [b'*']: + cahs = self.changelog.commonancestorsheads( + p1ctx.node(), p2ctx.node() + ) + pas = [self[anc] for anc in (sorted(cahs) or [nullid])] + else: + pas = [p1ctx.ancestor(p2ctx, warn=False)] + actionbyfile, __, __ = mergemod.calculateupdates( + self, + p1ctx, + p2ctx, + pas, + branchmerge=True, + force=True, + acceptremote=False, + followcopies=True, + matcher=matcher, + ) + if actionbyfile[fctx.path()][0] == mergemod.ACTION_GET: + fparent1, fparent2 = fparent2, nullid # is the file changed? text = fctx.data() diff --git a/tests/test-convert-hg-source.t b/tests/test-convert-hg-source.t --- a/tests/test-convert-hg-source.t +++ b/tests/test-convert-hg-source.t @@ -62,9 +62,9 @@ 6 make bar and baz copies of foo 5 merge local copy 4 merge remote copy - 3 Added tag that for changeset 88586c4e9f02 + 3 Added tag that for changeset 8601262d7472 2 Removed tag that - 1 Added tag this for changeset c56a7f387039 + 1 Added tag this for changeset 706614b458c1 0 mark baz executable updating bookmarks $ cd new @@ -76,7 +76,7 @@ #if execbit $ hg bookmarks premerge1 3:973ef48a98a4 - premerge2 8:91d107c423ba + premerge2 8:c4968fdf2e5d #else Different hash because no x bit $ hg bookmarks @@ -96,19 +96,19 @@ 6 make bar and baz copies of foo 5 merge local copy 4 merge remote copy - 3 Added tag that for changeset 88586c4e9f02 + 3 Added tag that for changeset 8601262d7472 2 Removed tag that - 1 Added tag this for changeset c56a7f387039 + 1 Added tag this for changeset 706614b458c1 0 mark baz executable updating bookmarks $ hg -R new log -G -T '{rev} {desc}' o 8 mark baz executable | - o 7 Added tag this for changeset c56a7f387039 + o 7 Added tag this for changeset 706614b458c1 | o 6 Removed tag that | - o 5 Added tag that for changeset 88586c4e9f02 + o 5 Added tag that for changeset 8601262d7472 | o 4 merge remote copy |\ diff --git a/tests/test-copies-chain-merge.t b/tests/test-copies-chain-merge.t --- a/tests/test-copies-chain-merge.t +++ b/tests/test-copies-chain-merge.t @@ -212,7 +212,7 @@ (branch merge, don't forget to commit) $ hg ci -m 'mBDm-0 simple merge - one way' $ hg up 'desc("d-2")' - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("b-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -314,8 +314,7 @@ rev linkrev nodeid p1 p2 0 2 01c2f5eabdc4 000000000000 000000000000 1 10 b004912a8510 000000000000 000000000000 - 2 15 0bb5445dc4d0 01c2f5eabdc4 b004912a8510 - 3 22 c72365ee036f 000000000000 000000000000 + 2 22 c72365ee036f 000000000000 000000000000 $ hg up 'desc("b-1")' 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("f-2")' @@ -323,7 +322,7 @@ (branch merge, don't forget to commit) $ hg ci -m 'mBFm-0 simple merge - one way' $ hg up 'desc("f-2")' - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg merge 'desc("b-1")' 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) @@ -537,17 +536,12 @@ - one with change to an unrelated file - one deleting and recreating the change -Note: -| In this case, one of the merge wrongly record a merge while there is none. -| This lead to bad copy tracing information to be dug up. - $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBDm-0")' M d $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mDBm-0")' M d $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mBDm-0")' M b - M d $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDBm-0")' M b $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBDm-0")' @@ -557,18 +551,14 @@ M b M d -The bugs makes recorded copy is different depending of where we started the merge from since + +The result must be the same for both merges $ hg manifest --debug --rev 'desc("mBDm-0")' | grep '644 d' - 0bb5445dc4d02f4e0d86cf16f9f3a411d0f17744 644 d + b004912a8510032a0350a74daa2803dadfb00e12 644 d $ hg manifest --debug --rev 'desc("mDBm-0")' | grep '644 d' b004912a8510032a0350a74daa2803dadfb00e12 644 d -The 0bb5445dc4d02f4e0d86cf16f9f3a411d0f17744 entry is wrong, since the file was -deleted on one side (then recreate) and untouched on the other side, no "merge" -has happened. The resulting `d` file is the untouched version from branch `D`, -not a merge. - $ hg manifest --debug --rev 'desc("d-2")' | grep '644 d' b004912a8510032a0350a74daa2803dadfb00e12 644 d $ hg manifest --debug --rev 'desc("b-1")' | grep '644 d' @@ -577,29 +567,16 @@ rev linkrev nodeid p1 p2 0 2 01c2f5eabdc4 000000000000 000000000000 1 10 b004912a8510 000000000000 000000000000 - 2 15 0bb5445dc4d0 01c2f5eabdc4 b004912a8510 - 3 22 c72365ee036f 000000000000 000000000000 - 4 23 863d9bc49190 01c2f5eabdc4 c72365ee036f - 5 25 7bded9d9da1f 01c2f5eabdc4 000000000000 - 6 26 f04cac32d703 b004912a8510 7bded9d9da1f - 7 27 d7a5eafb9322 7bded9d9da1f b004912a8510 - 8 28 2ed7a51aed47 c72365ee036f 7bded9d9da1f - -(This `hg log` output if wrong, since no merge actually happened). + 2 22 c72365ee036f 000000000000 000000000000 + 3 25 7bded9d9da1f 01c2f5eabdc4 000000000000 + 4 26 f04cac32d703 b004912a8510 7bded9d9da1f + 5 27 d7a5eafb9322 7bded9d9da1f b004912a8510 + 6 28 2ed7a51aed47 c72365ee036f 7bded9d9da1f $ hg log -Gfr 'desc("mBDm-0")' d - o 15 mBDm-0 simple merge - one way] - |\ - o : 14 d-2 re-add d] - :/ - o 2 i-2: c -move-> d] + o 14 d-2 re-add d] | - o 1 i-1: a -move-> c] - | - o 0 i-0 initial commit: a b h] - - -This `hg log` output is correct + ~ $ hg log -Gfr 'desc("mDBm-0")' d o 14 d-2 re-add d] @@ -609,7 +586,6 @@ $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBDm-0")' M b A d - a R a $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDBm-0")' M b @@ -685,8 +661,7 @@ $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBFm-0")' M b A d - a (true !) - h (false !) + h R a R h $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFBm-0")' @@ -700,7 +675,6 @@ R h $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBFm-0")' M b - M d $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBFm-0")' M b M d @@ -718,16 +692,10 @@ The following graphlog is wrong, the "a -> c -> d" chain was overwritten and should not appear. $ hg log -Gfr 'desc("mBFm-0")' d - o 23 mBFm-0 simple merge - one way] - |\ - o : 22 f-2: rename i -> d] - | : - o : 21 f-1: rename h -> i] - :/ - o 2 i-2: c -move-> d] + o 22 f-2: rename i -> d] | - o 1 i-1: a -move-> c] - | + o 21 f-1: rename h -> i] + : o 0 i-0 initial commit: a b h]