merge-recursive: track information associated with directory renames

Directory rename detection previously silently applied. In order to allow printing information about paths that changed or printing a conflict notification (and only doing so near other potential conflict messages associated with the paths), save this information inside the rename struct for later use. A subsequent patch will make use of the additional information. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Apr 5, 2019 at 08:00 UTC 6d169fd321c0da4b20c13d08bbe19d55cab12e11
1 file changed +23 -14
merge-recursive.c
+23 -14
@@ -207,8 +207,16 @@ struct stage_data {
207 };
208
209 struct rename {
210 + unsigned processed:1;
211 struct diff_filepair *pair;
212 const char *branch; /* branch that the rename occurred on */
213 + /*
214 + * If directory rename detection affected this rename, what was its
215 + * original type ('A' or 'R') and it's original destination before
216 + * the directory rename (otherwise, '\0' and NULL for these two vars).
217 + */
218 + char dir_rename_original_type;
219 + char *dir_rename_original_dest;
220 /*
221 * Purpose of src_entry and dst_entry:
222 *
@@ -230,8 +238,6 @@ struct rename {
238 */
239 struct stage_data *src_entry;
240 struct stage_data *dst_entry;
233 - unsigned add_turned_into_rename:1;
234 - unsigned processed:1;
241 };
242
243 struct rename_conflict_info {
@@ -2484,16 +2490,18 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
2490 &re->dst_entry->stages[stage].oid,
2491 &re->dst_entry->stages[stage].mode);
2492
2487 - /* Update pair status */
2488 - if (pair->status == 'A') {
2489 - /*
2490 - * Recording rename information for this add makes it look
2491 - * like a rename/delete conflict. Make sure we can
2492 - * correctly handle this as an add that was moved to a new
2493 - * directory instead of reporting a rename/delete conflict.
2494 - */
2495 - re->add_turned_into_rename = 1;
2496 - }
2493 + /*
2494 + * Record the original change status (or 'type' of change). If it
2495 + * was originally an add ('A'), this lets us differentiate later
2496 + * between a RENAME_DELETE conflict and RENAME_VIA_DIR (they
2497 + * otherwise look the same). If it was originally a rename ('R'),
2498 + * this lets us remember and report accurately about the transitive
2499 + * renaming that occurred via the directory rename detection. Also,
2500 + * record the original destination name.
2501 + */
2502 + re->dir_rename_original_type = pair->status;
2503 + re->dir_rename_original_dest = pair->two->path;
2504 +
2505 /*
2506 * We don't actually look at pair->status again, but it seems
2507 * pedagogically correct to adjust it.
@@ -2556,9 +2564,10 @@ static struct string_list *get_renames(struct merge_options *opt,
2564
2565 re = xmalloc(sizeof(*re));
2566 re->processed = 0;
2559 - re->add_turned_into_rename = 0;
2567 re->pair = pair;
2568 re->branch = branch;
2569 + re->dir_rename_original_type = '\0';
2570 + re->dir_rename_original_dest = NULL;
2571 item = string_list_lookup(entries, re->pair->one->path);
2572 if (!item)
2573 re->src_entry = insert_stage_data(re->pair->one->path,
@@ -2726,7 +2735,7 @@ static int process_renames(struct merge_options *opt,
2735 try_merge = 0;
2736
2737 if (oid_eq(&src_other.oid, &null_oid) &&
2729 - ren1->add_turned_into_rename) {
2738 + ren1->dir_rename_original_type == 'A') {
2739 setup_rename_conflict_info(RENAME_VIA_DIR,
2740 opt, ren1, NULL);
2741 } else if (oid_eq(&src_other.oid, &null_oid)) {