[PATCHv2 28/56] merge-recursive: Allow make_room_for_path() to remove D/F entries

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
Changes since v1:
  (1) Made use of Johannes' new string-list API to remove items we
      have already checked in order to avoid trying to unlink a path
      more than once
  (2) Moved the comment about removing paths to make room to the
      location where we actually remove the path.
  (3) Fixed a bug with accidentally removing wrong paths (by adding the
        path[df_pathlen] == '/'
      check)

 merge-recursive.c                 |   26 ++++++++++++++++++++++----
 t/t6036-recursive-corner-cases.sh |    2 +-
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index c12e4d5..1547691 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -412,7 +412,6 @@ static void record_df_conflict_files(struct merge_options *o,
 		    len > last_len &&
 		    memcmp(path, last_file, last_len) == 0 &&
 		    path[last_len] == '/') {
-			output(o, 3, "Removing %s to make room for subdirectory; may re-add later.", last_file);
 			string_list_insert(&o->df_conflict_file_set, last_file);
 		}
 
@@ -652,11 +651,30 @@ static int would_lose_untracked(const char *path)
 	return !was_tracked(path) && file_exists(path);
 }
 
-static int make_room_for_path(const char *path)
+static int make_room_for_path(struct merge_options *o, const char *path)
 {
-	int status;
+	int status, i;
 	const char *msg = "failed to create path '%s'%s";
 
+	/* Unlink any D/F conflict files that are in the way */
+	for (i = 0; i < o->df_conflict_file_set.nr; i++) {
+		const char *df_path = o->df_conflict_file_set.items[i].string;
+		size_t pathlen = strlen(path);
+		size_t df_pathlen = strlen(df_path);
+		if (df_pathlen < pathlen &&
+		    path[df_pathlen] == '/' &&
+		    strncmp(path, df_path, df_pathlen) == 0) {
+			output(o, 3,
+			       "Removing %s to make room for subdirectory\n",
+			       df_path);
+			unlink(df_path);
+			unsorted_string_list_delete_item(&o->df_conflict_file_set,
+							 i, 0);
+			break;
+		}
+	}
+
+	/* Make sure leading directories are created */
 	status = safe_create_leading_directories_const(path);
 	if (status) {
 		if (status == -3) {
@@ -724,7 +742,7 @@ static void update_file_flags(struct merge_options *o,
 			}
 		}
 
-		if (make_room_for_path(path) < 0) {
+		if (make_room_for_path(o, path) < 0) {
 			update_wd = 0;
 			free(buf);
 			goto update_index;
diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh
index ed6c6f4..279f33c 100755
--- a/t/t6036-recursive-corner-cases.sh
+++ b/t/t6036-recursive-corner-cases.sh
@@ -496,7 +496,7 @@ test_expect_success 'setup differently handled merges of directory/file conflict
 	git tag E2
 '
 
-test_expect_failure 'merge of D & E1 fails but has appropriate contents' '
+test_expect_success 'merge of D & E1 fails but has appropriate contents' '
 	get_clean_checkout D^0 &&
 
 	test_must_fail git merge -s recursive E1^0 &&
-- 
1.7.6.100.gac5c1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]