diff tests/test-merge-changedelete.t @ 27137:25e4b2f000c5

merge: move almost all change/delete conflicts to resolve phase (BC) (API) We have finally laid all the groundwork to make this happen. The only change/delete conflicts that haven't been moved are .hgsubstate conflicts. Those are trickier to deal with and well outside the scope of this series. We add comprehensive testing not just for the initial selections but also for re-resolves and all possible dirstate transitions caused by merge tools. That testing managed to shake out several bugs in the way we were handling dirstate transitions. The other test changes are because we now treat change/delete conflicts as proper merges, and increment the 'merged' counter rather than the 'updated' counter. I believe this is the right approach here. For third-party extensions, if they're interacting with filemerge code they might have to deal with an absentfilectx rather than a regular filectx. Still to come: - add a 'leave unresolved' option to merges - change the default for non-interactive change/delete conflicts to be 'leave unresolved' - add debug output to go alongside debug outputs for binary and symlink file merges
author Siddharth Agarwal <sid0@fb.com>
date Wed, 25 Nov 2015 14:25:33 -0800
parents 29b08ca680b0
children 4ab69be0ea15
line wrap: on
line diff
--- a/tests/test-merge-changedelete.t	Wed Nov 25 14:26:46 2015 -0800
+++ b/tests/test-merge-changedelete.t	Wed Nov 25 14:25:33 2015 -0800
@@ -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 @@
   >     done
   > }
 
-  $ hg init
+  $ hg init repo
+  $ cd repo
 
   $ echo 1 > file1
   $ echo 2 > file2
@@ -59,7 +60,7 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   --- 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)
+