Add a new testcase for basic rename/rename (+modify/modify) -- temp12 Add a testcase for tough-to-handle rename/rename + criss-cross merges Fix up most of temp12 testcase, but not yet handling merging of info from other side of history. --- merge-recursive.c | 24 ++++++++-------- t/temp12.sh | 59 +++++++++++++++++++++++++++++++++++++++ t/temp13.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 12 deletions(-) create mode 100755 t/temp12.sh create mode 100755 t/temp13.sh diff --git a/merge-recursive.c b/merge-recursive.c index 544c504..cea6e27 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -991,12 +991,12 @@ static int process_renames(struct merge_options *o, for (i = 0; i < a_renames->nr; i++) { sre = a_renames->items[i].util; string_list_insert(&a_by_dst, sre->pair->two->path)->util - = sre->dst_entry; + = (void*)sre; } for (i = 0; i < b_renames->nr; i++) { sre = b_renames->items[i].util; string_list_insert(&b_by_dst, sre->pair->two->path)->util - = sre->dst_entry; + = (void*)sre; } for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) { @@ -1110,6 +1110,16 @@ static int process_renames(struct merge_options *o, clean_merge = 0; conflict_rename_delete(o, ren1->pair, branch1, branch2); } + } else if ((item = string_list_lookup(renames2Dst, ren1_dst))) { + ren2 = item->util; + clean_merge = 0; + ren2->processed = 1; + output(o, 1, "CONFLICT (rename/rename): " + "Rename %s->%s in %s. " + "Rename %s->%s in %s", + ren1_src, ren1_dst, branch1, + ren2->pair->one->path, ren2->pair->two->path, branch2); + conflict_rename_rename_2to1(o, ren1, branch1, ren2, branch2); } else if ((dst_other.mode == ren1->pair->two->mode) && sha_eq(dst_other.sha1, ren1->pair->two->sha1)) { /* Added file on the other side @@ -1150,16 +1160,6 @@ static int process_renames(struct merge_options *o, output(o, 1, "Adding as %s instead", new_path); update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); } - } else if ((item = string_list_lookup(renames2Dst, ren1_dst))) { - ren2 = item->util; - clean_merge = 0; - ren2->processed = 1; - output(o, 1, "CONFLICT (rename/rename): " - "Rename %s->%s in %s. " - "Rename %s->%s in %s", - ren1_src, ren1_dst, branch1, - ren2->pair->one->path, ren2->pair->two->path, branch2); - conflict_rename_rename_2to1(o, ren1, branch1, ren2, branch2); } else try_merge = 1; diff --git a/t/temp12.sh b/t/temp12.sh new file mode 100755 index 0000000..47e657b --- /dev/null +++ b/t/temp12.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +test_description='rename/rename (2to1) handling' + +. ./test-lib.sh + +# Current git gets all kinds of things wrong with rename/rename (2to1); setup: +# Commit A: new files: a & b +# Commit B: rename a->c, modify b +# Commit C: rename b->c, modify a +# +# Merging of B & C should NOT be clean. Questions: +# * Both a & b should be removed by the merge; are they? +# * The two c's should contain modifications to a & b; do they? +# * The index should contain two files, both for c; does it? +# * The working copy should have two files, both of form c~<unique>; does it? +# * Nothing else should be present. Is anything? + +test_expect_success 'setup rename/rename (+ modify/modify)' ' + printf "1\n2\n3\n4\n5\n" >a && + printf "5\n4\n3\n2\n1\n" >b && + git add a b && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a c && + echo 0 >>b && + git add b && + git commit -m B && + + git checkout -b C A && + git mv b c && + echo 6 >>a && + git add a && + git commit -m C +' + +test_expect_success 'handle rename/rename conflict correctly' ' + git checkout B^0 && + + test_must_fail git merge -s recursive C^0 >out && + grep "CONFLICT (rename/rename)" out && + + test 2 -eq $(git ls-files -s | wc -l) && + test 2 -eq $(git ls-files -u | wc -l) && + test 2 -eq $(git ls-files -u c | wc -l) && + test 3 -eq $(git ls-files -o | wc -l) && + + test ! -f a && + test ! -f b && + test -f c~HEAD && + test -f c~C^0 && + + test $(git hash-object c~HEAD) = $(git rev-parse C:a) && + test $(git hash-object c~B) = $(git rev-parse B:b) +' + +test_done diff --git a/t/temp13.sh b/t/temp13.sh new file mode 100755 index 0000000..b455a8c --- /dev/null +++ b/t/temp13.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +test_description='recursive merge corner case: rename/rename (2to1) + criss-cross merge + introduce funny file on other side of history' + +. ./test-lib.sh + +# +# Standard setup: +# +# B D +# o---o +# / \ / \ +# A o X ? F +# \ / \ / +# o---o +# C E +# +# Commit A: new files: a, b +# Commit B: rename a->c +# Commit C: rename b->c +# Commit D: merge B&C, keeping c1 (a) & c2 (b) +# Commit E: merge B&C, keeping c1 (a) & c2 (b), and introducing c~HEAD, c~C +# +# Now, when we merge commits D & E, there should be no conflict... + +test_expect_success 'setup rename/rename + criss-cross + new funny files' ' + echo content >a && + echo other >b && + git add a b && + git commit -m A && + git tag A && + + git checkout -b B A && + git mv a c && + git commit -m B && + + git checkout -b C A && + git mv b c && + git commit -m C && + + git checkout B^0 && + test_must_fail git merge C && + git clean -f && + git rm -rf . && + echo content >c1 && + echo other >c2 && + git add c1 c2 && + git commit -m D && + git tag D && + + git checkout C^0 && + test_must_fail git merge B && + git clean -f && + git rm -rf . && + git checkout D -- . && + git add c1 c2 && + git mv c1 "c~Temporary merge branch 1" && + git mv c2 "c~Temporary merge branch 2" && + git commit -m E && + git tag E +' + +test_expect_success 'differently renamed files conflict detected' ' + git checkout D^0 && + + ( + # Do not want to use test_must_fail here because we do not want + # a premature fatal exit via "BUG: There are unmerged index + # entries" (exit code 128) to count as success. We want + # the code to run to completion, detect the conflict, and + # return an appropriate (not zero and not 128) exit code. + git merge -s recursive E^0; + exit_code=$? && + test $exit_code -gt 0 -a $exit_code -lt 128 + ) + +' + +test_done -- 1.7.4 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html