diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -997,8 +997,11 @@ def applyupdates(repo, actions, wctx, mc for m, l in actions.items(): l.sort() - # prescan for merges - for f, args, msg in actions['m']: + # 'cd' and 'dc' actions are treated like other merge conflicts + mergeactions = sorted(actions['cd']) + mergeactions.extend(sorted(actions['dc'])) + mergeactions.extend(actions['m']) + for f, args, msg in mergeactions: f1, f2, fa, move, anc = args if f == '.hgsubstate': # merged internally continue @@ -1111,7 +1114,6 @@ def applyupdates(repo, actions, wctx, mc util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags) updated += 1 - mergeactions = actions['m'] # the ordering is important here -- ms.mergedriver will raise if the merge # driver has changed, and we want to be able to bypass it when overwrite is # True @@ -1419,8 +1421,12 @@ def update(repo, node, branchmerge, forc else: _checkcollision(repo, wc.manifest(), actions) - # Prompt and create actions. TODO: Move this towards resolve phase. + # Prompt and create actions. Most of this is in the resolve phase + # already, but we can't handle .hgsubstate in filemerge or + # subrepo.submerge yet so we have to keep prompting for it. for f, args, msg in sorted(actions['cd']): + if f != '.hgsubstate': + continue if repo.ui.promptchoice( _("local changed %s which remote deleted\n" "use (c)hanged version or (d)elete?" @@ -1432,6 +1438,8 @@ def update(repo, node, branchmerge, forc actions['a'].append((f, None, "prompt keep")) for f, args, msg in sorted(actions['dc']): + if f != '.hgsubstate': + continue f1, f2, fa, move, anc = args flags = p2[f2].flags() if repo.ui.promptchoice( diff --git a/tests/test-merge-changedelete.t b/tests/test-merge-changedelete.t --- a/tests/test-merge-changedelete.t +++ b/tests/test-merge-changedelete.t @@ -1,4 +1,4 @@ -Test for +Tests for change/delete conflicts, including: b5605d88dc27: Make ui.prompt repeat on "unrecognized response" again (issue897) @@ -25,7 +25,8 @@ Make sure HGMERGE doesn't interfere with > done > } - $ hg init + $ hg init repo + $ cd repo $ echo 1 > file1 $ echo 2 > file2 @@ -59,7 +60,7 @@ Non-interactive merge: use (c)hanged version or leave (d)eleted? c merging file3 warning: conflicts while merging file3! (edit, then use 'hg resolve --mark') - 1 files updated, 0 files merged, 0 files removed, 1 files unresolved + 0 files updated, 2 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] @@ -69,11 +70,21 @@ Non-interactive merge: M file3 C file1 --- resolve --list --- + R file1 + R file2 U file3 --- debugmergestate --- * version 2 records local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) local path: file3 (flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -108,7 +119,7 @@ Interactive merge: use (c)hanged version or leave (d)eleted? d merging file3 warning: conflicts while merging file3! (edit, then use 'hg resolve --mark') - 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + 0 files updated, 2 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] @@ -118,11 +129,21 @@ Interactive merge: M file3 C file1 --- resolve --list --- + R file1 + R file2 U file3 --- debugmergestate --- * version 2 records local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) local path: file3 (flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -167,7 +188,7 @@ Interactive merge with bad input: use (c)hanged version or leave (d)eleted? c merging file3 warning: conflicts while merging file3! (edit, then use 'hg resolve --mark') - 1 files updated, 0 files merged, 1 files removed, 1 files unresolved + 0 files updated, 1 files merged, 1 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] @@ -177,11 +198,21 @@ Interactive merge with bad input: M file3 R file1 --- resolve --list --- + R file1 + R file2 U file3 --- debugmergestate --- * version 2 records local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) local path: file3 (flags "") ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) @@ -210,17 +241,83 @@ Interactive merge with not enough input: local changed file1 which remote deleted use (c)hanged version or (d)elete? d remote changed file2 which local deleted - use (c)hanged version or leave (d)eleted? abort: response expected - [255] + use (c)hanged version or leave (d)eleted? + merging file3 + warning: conflicts while merging file3! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 1 files removed, 2 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] $ status --- status --- + M file2 + M file3 + R file1 + --- resolve --list --- + R file1 + U file2 + U file3 + --- debugmergestate --- + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "u", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) + *** file1 does not exist + --- file2 --- + 2 + changed + --- file3 --- + 3 + <<<<<<< local: 13910f48cf7b - test: changed file1, removed file2, changed file3 + changed2 + ======= + changed1 + >>>>>>> other: 10f9a0a634e8 - test: removed file1, changed file2, changed file3 + +Choose local versions of files + + $ hg co -C + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg merge --tool :local + 0 files updated, 3 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ status 2>&1 | tee $TESTTMP/local.status + --- status --- file2: * (glob) + M file3 C file1 - C file3 --- resolve --list --- + R file1 + R file2 + R file3 --- debugmergestate --- - no merge state found + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "r", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) --- file1 --- 1 changed @@ -229,6 +326,350 @@ Interactive merge with not enough input: 3 changed2 +Choose other versions of files + + $ hg co -C + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg merge --tool :other + 0 files updated, 2 files merged, 1 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ status 2>&1 | tee $TESTTMP/other.status + --- status --- + M file2 + M file3 + R file1 + --- resolve --list --- + R file1 + R file2 + R file3 + --- debugmergestate --- + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "r", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) + *** file1 does not exist + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed1 + +Fail + + $ hg co -C + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg merge --tool :fail + 0 files updated, 0 files merged, 0 files removed, 3 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ status 2>&1 | tee $TESTTMP/fail.status + --- status --- + M file2 + M file3 + C file1 + --- resolve --list --- + U file1 + U file2 + U file3 + --- debugmergestate --- + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "u", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed2 + +Force prompts with no input (should be similar to :fail) + + $ hg co -C + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg merge --config ui.interactive=True --tool :prompt + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + no tool found to merge file3 + keep (l)ocal or take (o)ther? + 0 files updated, 0 files merged, 0 files removed, 3 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ status 2>&1 | tee $TESTTMP/prompt.status + --- status --- + M file2 + M file3 + C file1 + --- resolve --list --- + U file1 + U file2 + U file3 + --- debugmergestate --- + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "u", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed2 + $ diff -U8 $TESTTMP/fail.status $TESTTMP/prompt.status + + +Force prompts + + $ hg co -C + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg merge --tool :prompt + local changed file1 which remote deleted + use (c)hanged version or (d)elete? c + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? c + no tool found to merge file3 + keep (l)ocal or take (o)ther? l + 0 files updated, 3 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ status + --- status --- + M file2 + M file3 + C file1 + --- resolve --list --- + R file1 + R file2 + R file3 + --- debugmergestate --- + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "r", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed2 + +Choose to merge all files + + $ hg co -C + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg merge --tool :merge3 + local changed file1 which remote deleted + use (c)hanged version or (d)elete? c + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? c + merging file3 + warning: conflicts while merging file3! (edit, then use 'hg resolve --mark') + 0 files updated, 2 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ status + --- status --- + M file2 + M file3 + C file1 + --- resolve --list --- + R file1 + R file2 + U file3 + --- debugmergestate --- + * version 2 records + local: 13910f48cf7bdb2a0ba6e24b4900e4fdd5739dd4 + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + file: file3 (record type "F", state "u", hash d5b0a58bc47161b1b8a831084b366f757c4f0b11) + local path: file3 (flags "") + ancestor path: file3 (node 2661d26c649684b482d10f91960cc3db683c38b4) + other path: file3 (node a2644c43e210356772c7772a8674544a62e06beb) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + <<<<<<< local: 13910f48cf7b - test: changed file1, removed file2, changed file3 + changed2 + ||||||| base + ======= + changed1 + >>>>>>> other: 10f9a0a634e8 - test: removed file1, changed file2, changed file3 + +Exercise transitions between local, other, fail and prompt, and make sure the +dirstate stays consistent. (Compare with each other and to the above +invocations.) + + $ testtransitions() { + > # this traversal order covers every transition + > tools="local other prompt local fail other local prompt other fail prompt fail local" + > lasttool="merge3" + > for tool in $tools; do + > echo "=== :$lasttool -> :$tool ===" + > ref="$TESTTMP/$tool.status" + > hg resolve --unmark --all + > hg resolve --tool ":$tool" --all --config ui.interactive=True + > status > "$TESTTMP/compare.status" 2>&1 + > echo '--- diff of status ---' + > if diff -U8 "$TESTTMP/$tool.status" "$TESTTMP/compare.status"; then + > echo '(status identical)' + > fi + > lasttool="$tool" + > echo + > done + > } + + $ testtransitions + === :merge3 -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :local -> :other === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :other -> :prompt === + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + no tool found to merge file3 + keep (l)ocal or take (o)ther? + --- diff of status --- + (status identical) + + === :prompt -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :local -> :fail === + --- diff of status --- + (status identical) + + === :fail -> :other === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :other -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :local -> :prompt === + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + no tool found to merge file3 + keep (l)ocal or take (o)ther? + --- diff of status --- + (status identical) + + === :prompt -> :other === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :other -> :fail === + --- diff of status --- + (status identical) + + === :fail -> :prompt === + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + no tool found to merge file3 + keep (l)ocal or take (o)ther? + --- diff of status --- + (status identical) + + === :prompt -> :fail === + --- diff of status --- + (status identical) + + === :fail -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + + Non-interactive linear update $ hg co -C 0 @@ -240,15 +681,139 @@ Non-interactive linear update use (c)hanged version or (d)elete? c remote changed file2 which local deleted use (c)hanged version or leave (d)eleted? c - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 2 files merged, 0 files removed, 0 files unresolved $ status --- status --- A file1 C file2 C file3 --- resolve --list --- + R file1 + R file2 --- debugmergestate --- - no merge state found + * version 2 records + local: ab57bf49aa276a22d35a473592d4c34b5abc3eff + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed1 + +Choose local versions of files + + $ hg co -C 0 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo changed >> file1 + $ hg rm file2 + $ hg update 1 --tool :local + 1 files updated, 2 files merged, 0 files removed, 0 files unresolved + $ status 2>&1 | tee $TESTTMP/local.status + --- status --- + file2: * (glob) + A file1 + C file3 + --- resolve --list --- + R file1 + R file2 + --- debugmergestate --- + * version 2 records + local: ab57bf49aa276a22d35a473592d4c34b5abc3eff + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + --- file1 --- + 1 + changed + *** file2 does not exist + --- file3 --- + 3 + changed1 + +Choose other versions of files + + $ hg co -C 0 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo changed >> file1 + $ hg rm file2 + $ hg update 1 --tool :other + 1 files updated, 1 files merged, 1 files removed, 0 files unresolved + $ status 2>&1 | tee $TESTTMP/other.status + --- status --- + file1: * (glob) + C file2 + C file3 + --- resolve --list --- + R file1 + R file2 + --- debugmergestate --- + * version 2 records + local: ab57bf49aa276a22d35a473592d4c34b5abc3eff + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + *** file1 does not exist + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed1 + +Fail + + $ hg co -C 0 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo changed >> file1 + $ hg rm file2 + $ hg update 1 --tool :fail + 1 files updated, 0 files merged, 0 files removed, 2 files unresolved + use 'hg resolve' to retry unresolved file merges + [1] + $ status 2>&1 | tee $TESTTMP/fail.status + --- status --- + A file1 + C file2 + C file3 + --- resolve --list --- + U file1 + U file2 + --- debugmergestate --- + * version 2 records + local: ab57bf49aa276a22d35a473592d4c34b5abc3eff + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "u", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) --- file1 --- 1 changed @@ -258,3 +823,165 @@ Non-interactive linear update --- file3 --- 3 changed1 + +Force prompts with no input + + $ hg co -C 0 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo changed >> file1 + $ hg rm file2 + $ hg update 1 --config ui.interactive=True --tool :prompt + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + 1 files updated, 0 files merged, 0 files removed, 2 files unresolved + use 'hg resolve' to retry unresolved file merges + [1] + $ status 2>&1 | tee $TESTTMP/prompt.status + --- status --- + A file1 + C file2 + C file3 + --- resolve --list --- + U file1 + U file2 + --- debugmergestate --- + * version 2 records + local: ab57bf49aa276a22d35a473592d4c34b5abc3eff + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "u", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed1 + $ diff -U8 $TESTTMP/fail.status $TESTTMP/prompt.status + +Choose to merge all files + + $ hg co -C 0 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo changed >> file1 + $ hg rm file2 + $ hg update 1 --tool :merge3 + local changed file1 which remote deleted + use (c)hanged version or (d)elete? c + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? c + 1 files updated, 2 files merged, 0 files removed, 0 files unresolved + $ status + --- status --- + A file1 + C file2 + C file3 + --- resolve --list --- + R file1 + R file2 + --- debugmergestate --- + * version 2 records + local: ab57bf49aa276a22d35a473592d4c34b5abc3eff + other: 10f9a0a634e82080907e62f075ab119cbc565ea6 + file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) + local path: file1 (flags "") + ancestor path: file1 (node b8e02f6433738021a065f94175c7cd23db5f05be) + other path: file1 (node null) + file: file2 (record type "C", state "r", hash null) + local path: file2 (flags "") + ancestor path: file2 (node 5d9299349fc01ddd25d0070d149b124d8f10411e) + other path: file2 (node e7c1328648519852e723de86c0c0525acd779257) + --- file1 --- + 1 + changed + --- file2 --- + 2 + changed + --- file3 --- + 3 + changed1 + +Test transitions between different merge tools + + $ testtransitions + === :merge3 -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :local -> :other === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :other -> :prompt === + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + --- diff of status --- + (status identical) + + === :prompt -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :local -> :fail === + --- diff of status --- + (status identical) + + === :fail -> :other === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :other -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :local -> :prompt === + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + --- diff of status --- + (status identical) + + === :prompt -> :other === + (no more unresolved files) + --- diff of status --- + (status identical) + + === :other -> :fail === + --- diff of status --- + (status identical) + + === :fail -> :prompt === + local changed file1 which remote deleted + use (c)hanged version or (d)elete? + remote changed file2 which local deleted + use (c)hanged version or leave (d)eleted? + --- diff of status --- + (status identical) + + === :prompt -> :fail === + --- diff of status --- + (status identical) + + === :fail -> :local === + (no more unresolved files) + --- diff of status --- + (status identical) + diff --git a/tests/test-merge-force.t b/tests/test-merge-force.t --- a/tests/test-merge-force.t +++ b/tests/test-merge-force.t @@ -5,7 +5,8 @@ file that was modified in the remote cha local changeset, and then modified in the working copy to match the remote content, then finally forgotten. - $ hg init + $ hg init repo + $ cd repo Create base changeset @@ -214,7 +215,7 @@ Merge with remote warning: conflicts while merging missing_content2_content3_content4-tracked! (edit, then use 'hg resolve --mark') warning: conflicts while merging missing_content2_missing_content4-tracked! (edit, then use 'hg resolve --mark') warning: conflicts while merging missing_content2_missing_content4-untracked! (edit, then use 'hg resolve --mark') - 39 files updated, 3 files merged, 8 files removed, 10 files unresolved + 18 files updated, 28 files merged, 8 files removed, 10 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] @@ -226,14 +227,39 @@ Interestingly, one untracked file got me odd 'if force and branchmerge and different' case in manifestmerge(). $ hg resolve -l + R content1_content2_content1_content1-untracked + R content1_content2_content1_content2-untracked U content1_content2_content1_content4-tracked + R content1_content2_content1_content4-untracked + R content1_content2_content1_missing-tracked + R content1_content2_content1_missing-untracked R content1_content2_content2_content1-tracked + R content1_content2_content2_content1-untracked + R content1_content2_content2_content2-untracked U content1_content2_content2_content4-tracked + R content1_content2_content2_content4-untracked + R content1_content2_content2_missing-tracked + R content1_content2_content2_missing-untracked R content1_content2_content3_content1-tracked + R content1_content2_content3_content1-untracked + R content1_content2_content3_content2-untracked U content1_content2_content3_content3-tracked + R content1_content2_content3_content3-untracked U content1_content2_content3_content4-tracked + R content1_content2_content3_content4-untracked + R content1_content2_content3_missing-tracked + R content1_content2_content3_missing-untracked R content1_content2_missing_content1-tracked + R content1_content2_missing_content1-untracked + R content1_content2_missing_content2-untracked U content1_content2_missing_content4-tracked + R content1_content2_missing_content4-untracked + R content1_content2_missing_missing-tracked + R content1_content2_missing_missing-untracked + R content1_missing_content1_content4-tracked + R content1_missing_content3_content3-tracked + R content1_missing_content3_content4-tracked + R content1_missing_missing_content4-tracked U missing_content2_content2_content4-tracked U missing_content2_content3_content3-tracked U missing_content2_content3_content4-tracked @@ -260,17 +286,20 @@ almost as strange. missing_missing_content3_missing-tracked becomes removed ('R'), even though the remote side did not touch the file - $ for f in `python $TESTDIR/generate-working-copy-states.py filelist 3` - > do - > echo - > hg status -A $f - > if test -f $f - > then - > cat $f - > else - > echo '' - > fi - > done + $ checkstatus() { + > for f in `python $TESTDIR/generate-working-copy-states.py filelist 3` + > do + > echo + > hg status -A $f + > if test -f $f + > then + > cat $f + > else + > echo '' + > fi + > done + > } + $ checkstatus 2>&1 | tee $TESTTMP/status1 C content1_content1_content1_content1-tracked content1 @@ -667,3 +696,87 @@ the remote side did not touch the file content4 missing_content2_missing_content4-untracked.orig: content4 + +Re-resolve and check status + + $ hg resolve --unmark --all + $ hg resolve --all --tool :local + (no more unresolved files) + $ hg resolve --unmark --all + $ hg resolve --all --tool internal:merge3 + remote changed content1_content2_content1_content1-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content1_content2-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_content1_content4-tracked + remote changed content1_content2_content1_content4-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content1_missing-tracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content1_missing-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_content2_content1-tracked + remote changed content1_content2_content2_content1-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content2_content2-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_content2_content4-tracked + remote changed content1_content2_content2_content4-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content2_missing-tracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content2_missing-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_content3_content1-tracked + remote changed content1_content2_content3_content1-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content3_content2-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_content3_content3-tracked + remote changed content1_content2_content3_content3-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_content3_content4-tracked + remote changed content1_content2_content3_content4-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content3_missing-tracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_content3_missing-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_missing_content1-tracked + remote changed content1_content2_missing_content1-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_missing_content2-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + merging content1_content2_missing_content4-tracked + remote changed content1_content2_missing_content4-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_missing_missing-tracked which local deleted + use (c)hanged version or leave (d)eleted? c + remote changed content1_content2_missing_missing-untracked which local deleted + use (c)hanged version or leave (d)eleted? c + local changed content1_missing_content1_content4-tracked which remote deleted + use (c)hanged version or (d)elete? c + local changed content1_missing_content3_content3-tracked which remote deleted + use (c)hanged version or (d)elete? c + local changed content1_missing_content3_content4-tracked which remote deleted + use (c)hanged version or (d)elete? c + local changed content1_missing_missing_content4-tracked which remote deleted + use (c)hanged version or (d)elete? c + merging missing_content2_content2_content4-tracked + merging missing_content2_content3_content3-tracked + merging missing_content2_content3_content4-tracked + merging missing_content2_missing_content4-tracked + merging missing_content2_missing_content4-untracked + warning: conflicts while merging content1_content2_content1_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging content1_content2_content2_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging content1_content2_content3_content3-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging content1_content2_content3_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging content1_content2_missing_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging missing_content2_content2_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging missing_content2_content3_content3-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging missing_content2_content3_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging missing_content2_missing_content4-tracked! (edit, then use 'hg resolve --mark') + warning: conflicts while merging missing_content2_missing_content4-untracked! (edit, then use 'hg resolve --mark') + [1] + $ checkstatus > $TESTTMP/status2 2>&1 + $ diff -U8 $TESTTMP/status1 $TESTTMP/status2 diff --git a/tests/test-merge-remove.t b/tests/test-merge-remove.t --- a/tests/test-merge-remove.t +++ b/tests/test-merge-remove.t @@ -105,7 +105,7 @@ Those who use force will lose remote changed bar which local deleted use (c)hanged version or leave (d)eleted? c merging foo1 and foo to foo1 - 1 files updated, 1 files merged, 0 files removed, 0 files unresolved + 0 files updated, 2 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ cat bar bleh diff --git a/tests/test-rename-merge2.t b/tests/test-rename-merge2.t --- a/tests/test-rename-merge2.t +++ b/tests/test-rename-merge2.t @@ -679,12 +679,12 @@ m "um a c" "um x c" " " "10 do merg resolving manifests branchmerge: True, force: False, partial: False ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a + preserving b for resolve of b + preserving rev for resolve of rev + a: prompt deleted/changed -> m (premerge) + picked tool ':prompt' for a (binary False symlink False) remote changed a which local deleted use (c)hanged version or leave (d)eleted? c - preserving b for resolve of b - preserving rev for resolve of rev - a: prompt recreating -> g - getting a b: both created -> m (premerge) picked tool 'python ../merge' for b (binary False symlink False) merging b @@ -703,7 +703,7 @@ m "um a c" "um x c" " " "10 do merg my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob) merge tool returned: 0 - 1 files updated, 2 files merged, 0 files removed, 0 files unresolved + 0 files updated, 3 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) -------------- M a @@ -721,11 +721,13 @@ m "um a c" "um x c" " " "10 do merg resolving manifests branchmerge: True, force: False, partial: False ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a + preserving a for resolve of a + preserving b for resolve of b + preserving rev for resolve of rev + a: prompt changed/deleted -> m (premerge) + picked tool ':prompt' for a (binary False symlink False) local changed a which remote deleted use (c)hanged version or (d)elete? c - preserving b for resolve of b - preserving rev for resolve of rev - a: prompt keep -> am b: both created -> m (premerge) picked tool 'python ../merge' for b (binary False symlink False) merging b @@ -744,7 +746,7 @@ m "um a c" "um x c" " " "10 do merg my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob) merge tool returned: 0 - 0 files updated, 2 files merged, 0 files removed, 0 files unresolved + 0 files updated, 3 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) -------------- M b