t6423: test directory renames causing rename-to-self
Directory rename detection can cause transitive renames, e.g. if the two
different sides of history each do one half of:
A/file -> B/file
B/ -> C/
then directory rename detection transitively renames to give us C/file.
Since the default for merge.directoryRenames is conflict, this results
in an error message saying it is unclear whether the file should be
placed at B/file or C/file.
What if C/ is A/, though? In such a case, the transitive rename would
give us A/file, the original name we started with. Logically, having
an error message with B/file vs. A/file should be fine, as should
leaving the file where it started. But the logic in both
merge-recursive and merge-ort did not handle a case of a filename being
renamed to itself correctly; merge-recursive had two bugs, and merge-ort
had one. Add some testcases covering such a scenario.
Based-on-testcase-by: Anders Kaseorg <andersk@mit.edu>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committedJun 30, 2021 at 17:29 UTC806f83287f8d6c0568beed7ca5d603f936d53c40
1 file changed+175
t/t6423-merge-rename-directories.sh
+175
index 7134769149..afb88c347f 100755--- a/t/t6423-merge-rename-directories.sh+++ b/t/t6423-merge-rename-directories.sh@@ -4966,6 +4966,181 @@ test_expect_success '12g: Testcase with two kinds of "relevant" renames' ' ) '+# Testcase 12i, Directory rename causes rename-to-self+# Commit O: source/{subdir/foo, bar, baz_1}+# Commit A: source/{foo, bar, baz_1}+# Commit B: source/{subdir/{foo, bar}, baz_2}+# Expected: source/{foo, bar, baz_2}, with conflicts on+# source/bar vs. source/subdir/bar++test_setup_12i () {+ test_create_repo 12i &&+ (+ cd 12i &&++ mkdir -p source/subdir &&+ echo foo >source/subdir/foo &&+ echo bar >source/bar &&+ echo baz >source/baz &&+ git add source &&+ git commit -m orig &&++ git branch O &&+ git branch A &&+ git branch B &&++ git switch A &&+ git mv source/subdir/foo source/foo &&+ git commit -m A &&++ git switch B &&+ git mv source/bar source/subdir/bar &&+ echo more baz >>source/baz &&+ git commit -m B+ )+}++test_expect_merge_algorithm failure failure '12i: Directory rename causes rename-to-self' '+ test_setup_12i &&+ (+ cd 12i &&++ git checkout A^0 &&++ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&++ test_path_is_missing source/subdir &&+ test_path_is_file source/bar &&+ test_path_is_file source/baz &&++ git ls-files | uniq >tracked &&+ test_line_count = 3 tracked &&++ git status --porcelain -uno >actual &&+ cat >expect <<-\EOF &&+ UU source/bar+ M source/baz+ EOF+ test_cmp expect actual+ )+'++# Testcase 12j, Directory rename to root causes rename-to-self+# Commit O: {subdir/foo, bar, baz_1}+# Commit A: {foo, bar, baz_1}+# Commit B: {subdir/{foo, bar}, baz_2}+# Expected: {foo, bar, baz_2}, with conflicts on bar vs. subdir/bar++test_setup_12j () {+ test_create_repo 12j &&+ (+ cd 12j &&++ mkdir -p subdir &&+ echo foo >subdir/foo &&+ echo bar >bar &&+ echo baz >baz &&+ git add . &&+ git commit -m orig &&++ git branch O &&+ git branch A &&+ git branch B &&++ git switch A &&+ git mv subdir/foo foo &&+ git commit -m A &&++ git switch B &&+ git mv bar subdir/bar &&+ echo more baz >>baz &&+ git commit -m B+ )+}++test_expect_merge_algorithm failure failure '12j: Directory rename to root causes rename-to-self' '+ test_setup_12j &&+ (+ cd 12j &&++ git checkout A^0 &&++ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&++ test_path_is_missing subdir &&+ test_path_is_file bar &&+ test_path_is_file baz &&++ git ls-files | uniq >tracked &&+ test_line_count = 3 tracked &&++ git status --porcelain -uno >actual &&+ cat >expect <<-\EOF &&+ UU bar+ M baz+ EOF+ test_cmp expect actual+ )+'++# Testcase 12k, Directory rename with sibling causes rename-to-self+# Commit O: dirB/foo, dirA/{bar, baz_1}+# Commit A: dirA/{foo, bar, baz_1}+# Commit B: dirB/{foo, bar}, dirA/baz_2+# Expected: dirA/{foo, bar, baz_2}, with conflicts on dirA/bar vs. dirB/bar++test_setup_12k () {+ test_create_repo 12k &&+ (+ cd 12k &&++ mkdir dirA dirB &&+ echo foo >dirB/foo &&+ echo bar >dirA/bar &&+ echo baz >dirA/baz &&+ git add . &&+ git commit -m orig &&++ git branch O &&+ git branch A &&+ git branch B &&++ git switch A &&+ git mv dirB/* dirA/ &&+ git commit -m A &&++ git switch B &&+ git mv dirA/bar dirB/bar &&+ echo more baz >>dirA/baz &&+ git commit -m B+ )+}++test_expect_merge_algorithm failure failure '12k: Directory rename with sibling causes rename-to-self' '+ test_setup_12k &&+ (+ cd 12k &&++ git checkout A^0 &&++ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&++ test_path_is_missing dirB &&+ test_path_is_file dirA/bar &&+ test_path_is_file dirA/baz &&++ git ls-files | uniq >tracked &&+ test_line_count = 3 tracked &&++ git status --porcelain -uno >actual &&+ cat >expect <<-\EOF &&+ UU dirA/bar+ M dirA/baz+ EOF+ test_cmp expect actual+ )+'+ ########################################################################### # SECTION 13: Checking informational and conflict messages #