merge-recursive: Allow make_room_for_path() to remove D/F entries

If there were several files conflicting below a directory corresponding to a D/F conflict, and the file of that D/F conflict is in the way, we want it to be removed. Since files of D/F conflicts are handled last, they can be reinstated later and possibly with a new unique name. 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 ed0148a520ec2ec88f0574c2e107aba0a46936e1
2 files changed +23 -5
merge-recursive.c
+22 -4
@@ -410,7 +410,6 @@ static void record_df_conflict_files(struct merge_options *o,
410 len > last_len &&
411 memcmp(path, last_file, last_len) == 0 &&
412 path[last_len] == '/') {
413 - output(o, 3, "Removing %s to make room for subdirectory; may re-add later.", last_file);
413 string_list_insert(&o->df_conflict_file_set, last_file);
414 }
415
@@ -650,11 +649,30 @@ static int would_lose_untracked(const char *path)
649 return !was_tracked(path) && file_exists(path);
650 }
651
653 -static int make_room_for_path(const char *path)
652 +static int make_room_for_path(struct merge_options *o, const char *path)
653 {
655 - int status;
654 + int status, i;
655 const char *msg = "failed to create path '%s'%s";
656
657 + /* Unlink any D/F conflict files that are in the way */
658 + for (i = 0; i < o->df_conflict_file_set.nr; i++) {
659 + const char *df_path = o->df_conflict_file_set.items[i].string;
660 + size_t pathlen = strlen(path);
661 + size_t df_pathlen = strlen(df_path);
662 + if (df_pathlen < pathlen &&
663 + path[df_pathlen] == '/' &&
664 + strncmp(path, df_path, df_pathlen) == 0) {
665 + output(o, 3,
666 + "Removing %s to make room for subdirectory\n",
667 + df_path);
668 + unlink(df_path);
669 + unsorted_string_list_delete_item(&o->df_conflict_file_set,
670 + i, 0);
671 + break;
672 + }
673 + }
674 +
675 + /* Make sure leading directories are created */
676 status = safe_create_leading_directories_const(path);
677 if (status) {
678 if (status == -3) {
@@ -722,7 +740,7 @@ static void update_file_flags(struct merge_options *o,
740 }
741 }
742
725 - if (make_room_for_path(path) < 0) {
743 + if (make_room_for_path(o, path) < 0) {
744 update_wd = 0;
745 free(buf);
746 goto update_index;
t/t6036-recursive-corner-cases.sh
+1 -1
@@ -496,7 +496,7 @@ test_expect_success 'setup differently handled merges of directory/file conflict
496 git tag E2
497 '
498
499 -test_expect_failure 'merge of D & E1 fails but has appropriate contents' '
499 +test_expect_success 'merge of D & E1 fails but has appropriate contents' '
500 get_clean_checkout D^0 &&
501
502 test_must_fail git merge -s recursive E1^0 &&