From b70332520d2ba0f32b5006feff86d71242061011 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Thu, 11 Aug 2011 23:20:19 -0600 Subject: [PATCH] merge-recursive: Make modify/delete handling code reusable modify/delete and rename/delete share a lot of similarities; we'd like all the criss-cross and D/F conflict handling specializations to be shared between the two. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- merge-recursive.c | 82 +++++++++++++++++++++++++++++-------------------- t/t6022-merge-rename.sh | 4 +-- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/merge-recursive.c b/merge-recursive.c index 312414401..500efffb3 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -992,6 +992,46 @@ static struct merge_file_info merge_file(struct merge_options *o, return merge_file_1(o, &one, &a, &b, branch1, branch2); } +static void handle_change_delete(struct merge_options *o, + const char *path, + const unsigned char *o_sha, int o_mode, + const unsigned char *a_sha, int a_mode, + const unsigned char *b_sha, int b_mode, + const char *change, const char *change_past) +{ + char *renamed = NULL; + if (dir_in_way(path, !o->call_depth)) { + renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2); + } + + if (o->call_depth) { + /* + * We cannot arbitrarily accept either a_sha or b_sha as + * correct; since there is no true "middle point" between + * them, simply reuse the base version for virtual merge base. + */ + remove_file_from_cache(path); + update_file(o, 0, o_sha, o_mode, renamed ? renamed : path); + } else if (!a_sha) { + output(o, 1, "CONFLICT (%s/delete): %s deleted in %s " + "and %s in %s. Version %s of %s left in tree%s%s.", + change, path, o->branch1, + change_past, o->branch2, o->branch2, path, + NULL == renamed ? "" : " at ", + NULL == renamed ? "" : renamed); + update_file(o, 0, b_sha, b_mode, renamed ? renamed : path); + } else { + output(o, 1, "CONFLICT (%s/delete): %s deleted in %s " + "and %s in %s. Version %s of %s left in tree%s%s.", + change, path, o->branch2, + change_past, o->branch1, o->branch1, path, + NULL == renamed ? "" : " at ", + NULL == renamed ? "" : renamed); + update_file(o, 0, a_sha, a_mode, renamed ? renamed : path); + } + free(renamed); +} + static void conflict_rename_delete(struct merge_options *o, struct diff_filepair *pair, const char *rename_branch, @@ -1409,44 +1449,18 @@ error_return: return ret; } -static void handle_delete_modify(struct merge_options *o, +static void handle_modify_delete(struct merge_options *o, const char *path, unsigned char *o_sha, int o_mode, unsigned char *a_sha, int a_mode, unsigned char *b_sha, int b_mode) { - char *renamed = NULL; - if (dir_in_way(path, !o->call_depth)) { - renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2); - } - - if (o->call_depth) { - /* - * We cannot arbitrarily accept either a_sha or b_sha as - * correct; since there is no true "middle point" between - * them, simply reuse the base version for virtual merge base. - */ - remove_file_from_cache(path); - update_file(o, 0, o_sha, o_mode, renamed ? renamed : path); - } else if (!a_sha) { - output(o, 1, "CONFLICT (delete/modify): %s deleted in %s " - "and modified in %s. Version %s of %s left in tree%s%s.", - path, o->branch1, - o->branch2, o->branch2, path, - NULL == renamed ? "" : " at ", - NULL == renamed ? "" : renamed); - update_file(o, 0, b_sha, b_mode, renamed ? renamed : path); - } else { - output(o, 1, "CONFLICT (delete/modify): %s deleted in %s " - "and modified in %s. Version %s of %s left in tree%s%s.", - path, o->branch2, - o->branch1, o->branch1, path, - NULL == renamed ? "" : " at ", - NULL == renamed ? "" : renamed); - update_file(o, 0, a_sha, a_mode, renamed ? renamed : path); - } - free(renamed); - + handle_change_delete(o, + path, + o_sha, o_mode, + a_sha, a_mode, + b_sha, b_mode, + "modify", "modified"); } static int merge_content(struct merge_options *o, @@ -1612,7 +1626,7 @@ static int process_entry(struct merge_options *o, } else { /* Modify/delete; deleted side may have put a directory in the way */ clean_merge = 0; - handle_delete_modify(o, path, o_sha, o_mode, + handle_modify_delete(o, path, o_sha, o_mode, a_sha, a_mode, b_sha, b_mode); } } else if ((!o_sha && a_sha && !b_sha) || diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index d96d3c597..74dcf20b8 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -303,7 +303,7 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' git checkout -q renamed-file-has-no-conflicts^0 && test_must_fail git merge --strategy=recursive dir-in-way >output && - grep "CONFLICT (delete/modify): dir/file-in-the-way" output && + grep "CONFLICT (modify/delete): dir/file-in-the-way" output && grep "Auto-merging dir" output && grep "Adding as dir~HEAD instead" output && @@ -325,7 +325,7 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors && ! grep "error: refusing to lose untracked file at" errors && - grep "CONFLICT (delete/modify): dir/file-in-the-way" output && + grep "CONFLICT (modify/delete): dir/file-in-the-way" output && grep "Auto-merging dir" output && grep "Adding as dir~renamed-file-has-no-conflicts instead" output && -- 2.11.0