]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'en/merge-dir-rename-corner-case-fix'
authorJunio C Hamano <gitster@pobox.com>
Sat, 17 Jul 2021 00:42:45 +0000 (17:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 17 Jul 2021 00:42:45 +0000 (17:42 -0700)
The merge code had funny interactions between content based rename
detection and directory rename detection.

* en/merge-dir-rename-corner-case-fix:
  merge-recursive: handle rename-to-self case
  merge-ort: ensure we consult df_conflict and path_conflicts
  t6423: test directory renames causing rename-to-self

1  2 
merge-ort.c
merge-recursive.c
t/t6423-merge-rename-directories.sh

diff --cc merge-ort.c
Simple merge
Simple merge
index e834b7e6efe05e12d88672e5fcff969db31d9c76,4d056f046514a4a97e0f9f315efac20a1d275887..4af4fb00386efe0430e41fc4c120f9cdc1d37478
@@@ -4966,64 -4966,181 +4966,239 @@@ test_expect_success '12g: Testcase wit
        )
  '
  
 +# Testcase 12h, Testcase with two kinds of "relevant" renames
 +#   Commit O: olddir/{a_1, b}
 +#   Commit A: newdir/{a_2, b}
 +#   Commit B: olddir/{alpha_1, b}
 +#   Expected: newdir/{alpha_2, b}
 +
 +test_setup_12h () {
 +      test_create_repo 12h &&
 +      (
 +              cd 12h &&
 +
 +              mkdir olddir &&
 +              test_seq 3 8 >olddir/a &&
 +              >olddir/b &&
 +              git add olddir &&
 +              git commit -m orig &&
 +
 +              git branch O &&
 +              git branch A &&
 +              git branch B &&
 +
 +              git switch A &&
 +              test_seq 3 10 >olddir/a &&
 +              git add olddir/a &&
 +              git mv olddir newdir &&
 +              git commit -m A &&
 +
 +              git switch B &&
 +
 +              git mv olddir/a olddir/alpha &&
 +              git commit -m B
 +      )
 +}
 +
 +test_expect_failure '12h: renaming a file within a renamed directory' '
 +      test_setup_12h &&
 +      (
 +              cd 12h &&
 +
 +              git checkout A^0 &&
 +
 +              test_might_fail git -c merge.directoryRenames=true merge -s recursive B^0 &&
 +
 +              git ls-files >tracked &&
 +              test_line_count = 2 tracked &&
 +
 +              test_path_is_missing olddir/a &&
 +              test_path_is_file newdir/alpha &&
 +              test_path_is_file newdir/b &&
 +
 +              git rev-parse >actual \
 +                      HEAD:newdir/alpha  HEAD:newdir/b &&
 +              git rev-parse >expect \
 +                      A:newdir/a         O:oldir/b &&
 +              test_cmp expect actual
 +      )
 +'
 +
+ # 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_success '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_success '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_success '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
  #