From: Elijah Newren Date: Fri, 12 Aug 2011 05:20:15 +0000 (-0600) Subject: merge-recursive: Defer rename/rename(2to1) handling until process_entry X-Git-Tag: v1.7.7-rc1~28^2~15 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=461f5041178c02f3360920f42b542df7add0033f;p=git.git merge-recursive: Defer rename/rename(2to1) handling until process_entry This puts the code for the different types of double rename conflicts closer together (fewer lines of other code separating the two paths) and increases similarity between how they are handled. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- diff --git a/merge-recursive.c b/merge-recursive.c index 8020d4b51..ccb934356 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -67,7 +67,8 @@ enum rename_type { RENAME_NORMAL = 0, RENAME_DELETE, RENAME_ONE_FILE_TO_ONE, - RENAME_ONE_FILE_TO_TWO + RENAME_ONE_FILE_TO_TWO, + RENAME_TWO_FILES_TO_ONE }; struct rename_conflict_info { @@ -1019,32 +1020,40 @@ static void conflict_rename_rename_1to2(struct merge_options *o, } static void conflict_rename_rename_2to1(struct merge_options *o, - struct rename *ren1, - const char *branch1, - struct rename *ren2, - const char *branch2) + struct rename_conflict_info *ci) { - char *path = ren1->pair->two->path; /* same as ren2->pair->two->path */ - /* Two files were renamed to the same thing. */ + /* Two files, a & b, were renamed to the same thing, c. */ + struct diff_filespec *a = ci->pair1->one; + struct diff_filespec *b = ci->pair2->one; + struct diff_filespec *c1 = ci->pair1->two; + struct diff_filespec *c2 = ci->pair2->two; + char *path = c1->path; /* == c2->path */ + + output(o, 1, "CONFLICT (rename/rename): " + "Rename %s->%s in %s. " + "Rename %s->%s in %s", + a->path, c1->path, ci->branch1, + b->path, c2->path, ci->branch2); + + remove_file(o, 1, a->path, would_lose_untracked(a->path)); + remove_file(o, 1, b->path, would_lose_untracked(b->path)); + if (o->call_depth) { struct merge_file_info mfi; mfi = merge_file(o, path, null_sha1, 0, - ren1->pair->two->sha1, ren1->pair->two->mode, - ren2->pair->two->sha1, ren2->pair->two->mode, - branch1, branch2); + c1->sha1, c1->mode, + c2->sha1, c2->mode, + ci->branch1, ci->branch2); output(o, 1, "Adding merged %s", path); update_file(o, 0, mfi.sha, mfi.mode, path); } else { - char *new_path1 = unique_path(o, path, branch1); - char *new_path2 = unique_path(o, path, branch2); + char *new_path1 = unique_path(o, path, ci->branch1); + char *new_path2 = unique_path(o, path, ci->branch2); output(o, 1, "Renaming %s to %s and %s to %s instead", - ren1->pair->one->path, new_path1, - ren2->pair->one->path, new_path2); + a->path, new_path1, b->path, new_path2); remove_file(o, 0, path, 0); - update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, - new_path1); - update_file(o, 0, ren2->pair->two->sha1, ren2->pair->two->mode, - new_path2); + update_file(o, 0, c1->sha1, c1->mode, new_path1); + update_file(o, 0, c2->sha1, c2->mode, new_path2); free(new_path2); free(new_path1); } @@ -1075,6 +1084,7 @@ static int process_renames(struct merge_options *o, struct rename *ren1 = NULL, *ren2 = NULL; const char *branch1, *branch2; const char *ren1_src, *ren1_dst; + struct string_list_item *lookup; if (i >= a_renames->nr) { ren2 = b_renames->items[j++].util; @@ -1106,30 +1116,30 @@ static int process_renames(struct merge_options *o, ren1 = tmp; } + if (ren1->processed) + continue; + ren1->processed = 1; ren1->dst_entry->processed = 1; /* BUG: We should only mark src_entry as processed if we * are not dealing with a rename + add-source case. */ ren1->src_entry->processed = 1; - if (ren1->processed) - continue; - ren1->processed = 1; - ren1_src = ren1->pair->one->path; ren1_dst = ren1->pair->two->path; if (ren2) { + /* One file renamed on both sides */ const char *ren2_src = ren2->pair->one->path; const char *ren2_dst = ren2->pair->two->path; enum rename_type rename_type; - /* Renamed in 1 and renamed in 2 */ if (strcmp(ren1_src, ren2_src) != 0) - die("ren1.src != ren2.src"); + die("ren1_src != ren2_src"); ren2->dst_entry->processed = 1; ren2->processed = 1; if (strcmp(ren1_dst, ren2_dst) != 0) { rename_type = RENAME_ONE_FILE_TO_TWO; + clean_merge = 0; } else { rename_type = RENAME_ONE_FILE_TO_ONE; /* BUG: We should only remove ren1_src in @@ -1149,9 +1159,32 @@ static int process_renames(struct merge_options *o, branch2, ren1->dst_entry, ren2->dst_entry); + } else if ((lookup = string_list_lookup(renames2Dst, ren1_dst))) { + /* Two different files renamed to the same thing */ + char *ren2_dst; + ren2 = lookup->util; + ren2_dst = ren2->pair->two->path; + if (strcmp(ren1_dst, ren2_dst) != 0) + die("ren1_dst != ren2_dst"); + + clean_merge = 0; + ren2->processed = 1; + /* + * BUG: We should only mark src_entry as processed + * if we are not dealing with a rename + add-source + * case. + */ + ren2->src_entry->processed = 1; + + setup_rename_conflict_info(RENAME_TWO_FILES_TO_ONE, + ren1->pair, + ren2->pair, + branch1, + branch2, + ren1->dst_entry, + ren2->dst_entry); } else { /* Renamed in 1, maybe changed in 2 */ - struct string_list_item *item; /* we only use sha1 and mode of these */ struct diff_filespec src_other, dst_other; int try_merge; @@ -1186,23 +1219,6 @@ static int process_renames(struct merge_options *o, branch2, ren1->dst_entry, NULL); - } else if ((item = string_list_lookup(renames2Dst, ren1_dst))) { - char *ren2_src, *ren2_dst; - ren2 = item->util; - ren2_src = ren2->pair->one->path; - ren2_dst = ren2->pair->two->path; - - clean_merge = 0; - ren2->processed = 1; - remove_file(o, 1, ren2_src, - renamed_stage == 3 || would_lose_untracked(ren1_src)); - - output(o, 1, "CONFLICT (rename/rename): " - "Rename %s->%s in %s. " - "Rename %s->%s in %s", - ren1_src, ren1_dst, branch1, - ren2_src, ren2_dst, 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 @@ -1502,6 +1518,10 @@ static int process_entry(struct merge_options *o, clean_merge = 0; conflict_rename_rename_1to2(o, conflict_info); break; + case RENAME_TWO_FILES_TO_ONE: + clean_merge = 0; + conflict_rename_rename_2to1(o, conflict_info); + break; default: entry->processed = 0; break;