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 <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Aug 11, 2011 at 23:20 UTC
461f5041178c02f3360920f42b542df7add0033f
1 file changed
+62
-42
merge-recursive.c
+62
-42
@@ -67,7 +67,8 @@ enum rename_type {
67
RENAME_NORMAL = 0,
68
RENAME_DELETE,
69
RENAME_ONE_FILE_TO_ONE,
70
- RENAME_ONE_FILE_TO_TWO
70
+ RENAME_ONE_FILE_TO_TWO,
71
+ RENAME_TWO_FILES_TO_ONE
72
};
73
74
struct rename_conflict_info {
@@ -1019,32 +1020,40 @@ static void conflict_rename_rename_1to2(struct merge_options *o,
1020
}
1021
1022
static void conflict_rename_rename_2to1(struct merge_options *o,
1022
- struct rename *ren1,
1023
- const char *branch1,
1024
- struct rename *ren2,
1025
- const char *branch2)
1023
+ struct rename_conflict_info *ci)
1024
{
1027
- char *path = ren1->pair->two->path; /* same as ren2->pair->two->path */
1028
- /* Two files were renamed to the same thing. */
1025
+ /* Two files, a & b, were renamed to the same thing, c. */
1026
+ struct diff_filespec *a = ci->pair1->one;
1027
+ struct diff_filespec *b = ci->pair2->one;
1028
+ struct diff_filespec *c1 = ci->pair1->two;
1029
+ struct diff_filespec *c2 = ci->pair2->two;
1030
+ char *path = c1->path; /* == c2->path */
1031
+
1032
+ output(o, 1, "CONFLICT (rename/rename): "
1033
+ "Rename %s->%s in %s. "
1034
+ "Rename %s->%s in %s",
1035
+ a->path, c1->path, ci->branch1,
1036
+ b->path, c2->path, ci->branch2);
1037
+
1038
+ remove_file(o, 1, a->path, would_lose_untracked(a->path));
1039
+ remove_file(o, 1, b->path, would_lose_untracked(b->path));
1040
+
1041
if (o->call_depth) {
1042
struct merge_file_info mfi;
1043
mfi = merge_file(o, path, null_sha1, 0,
1032
- ren1->pair->two->sha1, ren1->pair->two->mode,
1033
- ren2->pair->two->sha1, ren2->pair->two->mode,
1034
- branch1, branch2);
1044
+ c1->sha1, c1->mode,
1045
+ c2->sha1, c2->mode,
1046
+ ci->branch1, ci->branch2);
1047
output(o, 1, "Adding merged %s", path);
1048
update_file(o, 0, mfi.sha, mfi.mode, path);
1049
} else {
1038
- char *new_path1 = unique_path(o, path, branch1);
1039
- char *new_path2 = unique_path(o, path, branch2);
1050
+ char *new_path1 = unique_path(o, path, ci->branch1);
1051
+ char *new_path2 = unique_path(o, path, ci->branch2);
1052
output(o, 1, "Renaming %s to %s and %s to %s instead",
1041
- ren1->pair->one->path, new_path1,
1042
- ren2->pair->one->path, new_path2);
1053
+ a->path, new_path1, b->path, new_path2);
1054
remove_file(o, 0, path, 0);
1044
- update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode,
1045
- new_path1);
1046
- update_file(o, 0, ren2->pair->two->sha1, ren2->pair->two->mode,
1047
- new_path2);
1055
+ update_file(o, 0, c1->sha1, c1->mode, new_path1);
1056
+ update_file(o, 0, c2->sha1, c2->mode, new_path2);
1057
free(new_path2);
1058
free(new_path1);
1059
}
@@ -1075,6 +1084,7 @@ static int process_renames(struct merge_options *o,
1084
struct rename *ren1 = NULL, *ren2 = NULL;
1085
const char *branch1, *branch2;
1086
const char *ren1_src, *ren1_dst;
1087
+ struct string_list_item *lookup;
1088
1089
if (i >= a_renames->nr) {
1090
ren2 = b_renames->items[j++].util;
@@ -1106,30 +1116,30 @@ static int process_renames(struct merge_options *o,
1116
ren1 = tmp;
1117
}
1118
1119
+ if (ren1->processed)
1120
+ continue;
1121
+ ren1->processed = 1;
1122
ren1->dst_entry->processed = 1;
1123
/* BUG: We should only mark src_entry as processed if we
1124
* are not dealing with a rename + add-source case.
1125
*/
1126
ren1->src_entry->processed = 1;
1127
1115
- if (ren1->processed)
1116
- continue;
1117
- ren1->processed = 1;
1118
-
1128
ren1_src = ren1->pair->one->path;
1129
ren1_dst = ren1->pair->two->path;
1130
1131
if (ren2) {
1132
+ /* One file renamed on both sides */
1133
const char *ren2_src = ren2->pair->one->path;
1134
const char *ren2_dst = ren2->pair->two->path;
1135
enum rename_type rename_type;
1126
- /* Renamed in 1 and renamed in 2 */
1136
if (strcmp(ren1_src, ren2_src) != 0)
1128
- die("ren1.src != ren2.src");
1137
+ die("ren1_src != ren2_src");
1138
ren2->dst_entry->processed = 1;
1139
ren2->processed = 1;
1140
if (strcmp(ren1_dst, ren2_dst) != 0) {
1141
rename_type = RENAME_ONE_FILE_TO_TWO;
1142
+ clean_merge = 0;
1143
} else {
1144
rename_type = RENAME_ONE_FILE_TO_ONE;
1145
/* BUG: We should only remove ren1_src in
@@ -1149,9 +1159,32 @@ static int process_renames(struct merge_options *o,
1159
branch2,
1160
ren1->dst_entry,
1161
ren2->dst_entry);
1162
+ } else if ((lookup = string_list_lookup(renames2Dst, ren1_dst))) {
1163
+ /* Two different files renamed to the same thing */
1164
+ char *ren2_dst;
1165
+ ren2 = lookup->util;
1166
+ ren2_dst = ren2->pair->two->path;
1167
+ if (strcmp(ren1_dst, ren2_dst) != 0)
1168
+ die("ren1_dst != ren2_dst");
1169
+
1170
+ clean_merge = 0;
1171
+ ren2->processed = 1;
1172
+ /*
1173
+ * BUG: We should only mark src_entry as processed
1174
+ * if we are not dealing with a rename + add-source
1175
+ * case.
1176
+ */
1177
+ ren2->src_entry->processed = 1;
1178
+
1179
+ setup_rename_conflict_info(RENAME_TWO_FILES_TO_ONE,
1180
+ ren1->pair,
1181
+ ren2->pair,
1182
+ branch1,
1183
+ branch2,
1184
+ ren1->dst_entry,
1185
+ ren2->dst_entry);
1186
} else {
1187
/* Renamed in 1, maybe changed in 2 */
1154
- struct string_list_item *item;
1188
/* we only use sha1 and mode of these */
1189
struct diff_filespec src_other, dst_other;
1190
int try_merge;
@@ -1186,23 +1219,6 @@ static int process_renames(struct merge_options *o,
1219
branch2,
1220
ren1->dst_entry,
1221
NULL);
1189
- } else if ((item = string_list_lookup(renames2Dst, ren1_dst))) {
1190
- char *ren2_src, *ren2_dst;
1191
- ren2 = item->util;
1192
- ren2_src = ren2->pair->one->path;
1193
- ren2_dst = ren2->pair->two->path;
1194
-
1195
- clean_merge = 0;
1196
- ren2->processed = 1;
1197
- remove_file(o, 1, ren2_src,
1198
- renamed_stage == 3 || would_lose_untracked(ren1_src));
1199
-
1200
- output(o, 1, "CONFLICT (rename/rename): "
1201
- "Rename %s->%s in %s. "
1202
- "Rename %s->%s in %s",
1203
- ren1_src, ren1_dst, branch1,
1204
- ren2_src, ren2_dst, branch2);
1205
- conflict_rename_rename_2to1(o, ren1, branch1, ren2, branch2);
1222
} else if ((dst_other.mode == ren1->pair->two->mode) &&
1223
sha_eq(dst_other.sha1, ren1->pair->two->sha1)) {
1224
/* Added file on the other side
@@ -1502,6 +1518,10 @@ static int process_entry(struct merge_options *o,
1518
clean_merge = 0;
1519
conflict_rename_rename_1to2(o, conflict_info);
1520
break;
1521
+ case RENAME_TWO_FILES_TO_ONE:
1522
+ clean_merge = 0;
1523
+ conflict_rename_rename_2to1(o, conflict_info);
1524
+ break;
1525
default:
1526
entry->processed = 0;
1527
break;