From bbafc9c44ae7109f636772350934b3c5d747da44 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 7 Nov 2018 20:40:27 -0800 Subject: merge-recursive: improve handling for rename/rename(2to1) conflicts This makes the rename/rename(2to1) conflicts use the new handle_file_collision() function. Since that function was based originally on the rename/rename(2to1) handling code, the main differences here are in what was added. In particular: * Instead of storing files at collide_path~HEAD and collide_path~MERGE, the files are two-way merged and recorded at collide_path. * Instead of recording the version of the renamed file that existed on the renamed side in the index (thus ignoring any changes that were made to the file on the side of history without the rename), we do a three-way content merge on the renamed path, then store that at either stage 2 or stage 3. * Note that since the content merge for each rename may have conflicts, and then we have to merge the two renamed files, we can end up with nested conflict markers. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- t/t6043-merge-rename-directories.sh | 83 +++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 35 deletions(-) (limited to 't/t6043-merge-rename-directories.sh') diff --git a/t/t6043-merge-rename-directories.sh b/t/t6043-merge-rename-directories.sh index 4a71f17edd..fedaeafc55 100755 --- a/t/t6043-merge-rename-directories.sh +++ b/t/t6043-merge-rename-directories.sh @@ -278,7 +278,7 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >actual \ :0:x/b :0:x/c :0:x/d :0:x/e :0:x/m :0:x/n && @@ -293,15 +293,16 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con A:y/wham B:z/wham && test_cmp expect actual && - test_path_is_missing x/wham && - test_path_is_file x/wham~HEAD && - test_path_is_file x/wham~B^0 && - - git hash-object >actual \ - x/wham~HEAD x/wham~B^0 && - git rev-parse >expect \ - A:y/wham B:z/wham && - test_cmp expect actual + # Test that the two-way merge in x/wham is as expected + git cat-file -p :2:x/wham >expect && + git cat-file -p :3:x/wham >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect x/wham ) ' @@ -1670,7 +1671,7 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >actual \ :0:y/b :0:y/c :2:y/d :3:y/d && @@ -1678,15 +1679,16 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r O:z/b O:z/c O:w/d O:x/d && test_cmp expect actual && - test_path_is_missing y/d && - test_path_is_file y/d~HEAD && - test_path_is_file y/d~B^0 && - - git hash-object >actual \ - y/d~HEAD y/d~B^0 && - git rev-parse >expect \ - O:w/d O:x/d && - test_cmp expect actual + # Test that the two-way merge in y/d is as expected + git cat-file -p :2:y/d >expect && + git cat-file -p :3:y/d >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect y/d ) ' @@ -3165,7 +3167,7 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2) # Commit O: z/{a,b,c_1}, x/{d,e,f_2} # Commit A: y/{a,b}, x/{d,e,f_2,wham_1} + untracked y/wham # Commit B: z/{a,b,c_1,wham_2}, y/{d,e} -# Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~B^0,wham~HEAD}+ +# Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~merged}+ # CONFLICT(rename/rename) z/c_1 vs x/f_2 -> y/wham # ERROR_MSG(Refusing to lose untracked file at y/wham) @@ -3219,7 +3221,7 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 4 out && + test_line_count = 3 out && git rev-parse >actual \ :0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham && @@ -3232,11 +3234,16 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' echo important >expect && test_cmp expect y/wham && - git hash-object >actual \ - y/wham~B^0 y/wham~HEAD && - git rev-parse >expect \ - O:x/f O:z/c && - test_cmp expect actual + # Test that the two-way merge in y/wham~merged is as expected + git cat-file -p :2:y/wham >expect && + git cat-file -p :3:y/wham >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect y/wham~merged ) ' @@ -3689,7 +3696,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena # Commit O: z/{a,b}, x/{c_1,d_2} # Commit A: y/{a,b,wham_1}, x/d_2, except y/wham has uncommitted mods # Commit B: z/{a,b,wham_2}, x/c_1 -# Expected: Failed Merge; y/{a,b} + untracked y/{wham~B^0,wham~B^HEAD} + +# Expected: Failed Merge; y/{a,b} + untracked y/{wham~merged} + # y/wham with dirty changes from before merge + # CONFLICT(rename/rename) x/c vs x/d -> y/wham # ERROR_MSG(Refusing to lose dirty file at y/wham) @@ -3741,24 +3748,30 @@ test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rena git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 4 out && + test_line_count = 3 out && test_seq 1 10 >expected && echo important >>expected && test_cmp expected y/wham && test_must_fail git rev-parse :1:y/wham && - git hash-object >actual \ - y/wham~B^0 y/wham~HEAD && - git rev-parse >expect \ - O:x/d O:x/c && - test_cmp expect actual && git rev-parse >actual \ :0:y/a :0:y/b :2:y/wham :3:y/wham && git rev-parse >expect \ O:z/a O:z/b O:x/c O:x/d && - test_cmp expect actual + test_cmp expect actual && + + # Test that the two-way merge in y/wham~merged is as expected + git cat-file -p :2:y/wham >expect && + git cat-file -p :3:y/wham >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect y/wham~merged ) ' -- cgit v1.2.3 From 48c9cb9d6d058bcf18e931a1ed0d88792bb506c9 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 7 Nov 2018 20:40:29 -0800 Subject: merge-recursive: improve rename/rename(1to2)/add[/add] handling When we have a rename/rename(1to2) conflict, each of the renames can collide with a file addition. Each of these rename/add conflicts suffered from the same kinds of problems that normal rename/add suffered from. Make the code use handle_file_conflicts() as well so that we get all the same fixes and consistent behavior between the different conflict types. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- t/t6043-merge-rename-directories.sh | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 't/t6043-merge-rename-directories.sh') diff --git a/t/t6043-merge-rename-directories.sh b/t/t6043-merge-rename-directories.sh index fedaeafc55..5c01a0c14a 100755 --- a/t/t6043-merge-rename-directories.sh +++ b/t/t6043-merge-rename-directories.sh @@ -1078,7 +1078,7 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam git ls-files -u >out && test_line_count = 6 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >actual \ :0:y/b :0:y/c :0:y/e && @@ -1094,9 +1094,9 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam test_cmp expect actual && git hash-object >actual \ - w/d~HEAD w/d~B^0 z/d && + z/d && git rev-parse >expect \ - O:x/d B:w/d O:x/d && + O:x/d && test_cmp expect actual && test_path_is_missing x/d && test_path_is_file y/d && @@ -3672,7 +3672,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena git ls-files -u >out && test_line_count = 4 out && git ls-files -o >out && - test_line_count = 4 out && + test_line_count = 3 out && echo different >expected && echo mods >>expected && @@ -3684,11 +3684,17 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena O:z/a O:z/b O:x/d O:x/c O:x/c A:y/c O:x/c && test_cmp expect actual && - git hash-object >actual \ - y/c~B^0 y/c~HEAD && - git rev-parse >expect \ - O:x/c A:y/c && - test_cmp expect actual + # See if y/c~merged has expected contents; requires manually + # doing the expected file merge + git cat-file -p A:y/c >c1 && + git cat-file -p B:z/c >c2 && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + c1 empty c2 && + test_cmp c1 y/c~merged ) ' -- cgit v1.2.3 From b8cd1bb71306e489d73e5cf4ef75a6cdb4c223b7 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 7 Nov 2018 20:40:30 -0800 Subject: t6036, t6043: increase code coverage for file collision handling Stolee's coverage reports found a few code blocks for file collision conflicts that had not previously been covered by testcases; add a few more testcases to cover those too. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- t/t6043-merge-rename-directories.sh | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 't/t6043-merge-rename-directories.sh') diff --git a/t/t6043-merge-rename-directories.sh b/t/t6043-merge-rename-directories.sh index 5c01a0c14a..62c564707b 100755 --- a/t/t6043-merge-rename-directories.sh +++ b/t/t6043-merge-rename-directories.sh @@ -3163,6 +3163,43 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2) ) ' +test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2), other direction' ' + ( + cd 10c && + + git reset --hard && + git clean -fdqx && + + git checkout B^0 && + mkdir y && + echo important >y/c && + + test_must_fail git merge -s recursive A^0 >out 2>err && + test_i18ngrep "CONFLICT (rename/rename)" out && + test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && + + git ls-files -s >out && + test_line_count = 6 out && + git ls-files -u >out && + test_line_count = 3 out && + git ls-files -o >out && + test_line_count = 3 out && + + git rev-parse >actual \ + :0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c && + git rev-parse >expect \ + O:z/a O:z/b O:x/d O:x/c O:x/c O:x/c && + test_cmp expect actual && + + git hash-object y/c~HEAD >actual && + git rev-parse O:x/c >expect && + test_cmp expect actual && + + echo important >expect && + test_cmp expect y/c + ) +' + # Testcase 10d, Delete untracked w/ dir rename/rename(2to1) # Commit O: z/{a,b,c_1}, x/{d,e,f_2} # Commit A: y/{a,b}, x/{d,e,f_2,wham_1} + untracked y/wham -- cgit v1.2.3