git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Elijah Newren <newren@gmail.com>
To: git@vger.kernel.org
Cc: Elijah Newren <newren@gmail.com>
Subject: [PATCH 36/37] merge-recursive: Make room for directories in D/F conflicts
Date: Mon, 20 Sep 2010 02:29:09 -0600	[thread overview]
Message-ID: <1284971350-30590-37-git-send-email-newren@gmail.com> (raw)
In-Reply-To: <1284971350-30590-1-git-send-email-newren@gmail.com>

When there are unmerged entries present, make sure to check for D/F
conflicts first and remove any files present in HEAD that would be in the
way of creating files below the correspondingly named directory.  Such
files will be processed again at the end of the merge in
process_df_entry(); at that time we will be able to tell if we need to
and can reinstate the file, whether we need to place its contents in a
different file due to the directory still being present, etc.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-recursive.c   |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++
 t/t6020-merge-df.sh |    2 +-
 2 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index 05da47c..821bed8 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -347,6 +347,63 @@ static struct string_list *get_unmerged(void)
 	return unmerged;
 }
 
+static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
+						      struct string_list *entries)
+{
+	/* If there are D/F conflicts, and the paths currently exist
+	 * in the working copy as a file, we want to remove them to
+	 * make room for the corresponding directory.  Such paths will
+	 * later be processed in process_df_entry() at the end.  If
+	 * the corresponding directory ends up being removed by the
+	 * merge, then the file will be reinstated at that time;
+	 * otherwise, if the file is not supposed to be removed by the
+	 * merge, the contents of the file will be placed in another
+	 * unique filename.
+	 *
+	 * NOTE: This function relies on the fact that entries for a
+	 * D/F conflict will appear adjacent in the index, with the
+	 * entries for the file appearing before entries for paths
+	 * below the corresponding directory.
+	 */
+	const char *last_file = NULL;
+	int last_len;
+	struct stage_data *last_e;
+	int i;
+
+	for (i = 0; i < entries->nr; i++) {
+		const char *path = entries->items[i].string;
+		int len = strlen(path);
+		struct stage_data *e = entries->items[i].util;
+
+		/*
+		 * Check if last_file & path correspond to a D/F conflict;
+		 * i.e. whether path is last_file+'/'+<something>.
+		 * If so, remove last_file to make room for path and friends.
+		 */
+		if (last_file &&
+		    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);
+			unlink(last_file);
+		}
+
+		/*
+		 * Determine whether path could exist as a file in the
+		 * working directory as a possible D/F conflict.  This
+		 * will only occur when it exists in stage 2 as a
+		 * file.
+		 */
+		if (S_ISREG(e->stages[2].mode) || S_ISLNK(e->stages[2].mode)) {
+			last_file = path;
+			last_len = len;
+			last_e = e;
+		} else {
+			last_file = NULL;
+		}
+	}
+}
+
 struct rename
 {
 	struct diff_filepair *pair;
@@ -1488,6 +1545,7 @@ int merge_trees(struct merge_options *o,
 		get_files_dirs(o, merge);
 
 		entries = get_unmerged();
+		make_room_for_directories_of_df_conflicts(o, entries);
 		re_head  = get_renames(o, head, common, head, merge, entries);
 		re_merge = get_renames(o, merge, common, head, merge, entries);
 		clean = process_renames(o, re_head, re_merge);
diff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh
index 7b1ce82..b129f1d 100755
--- a/t/t6020-merge-df.sh
+++ b/t/t6020-merge-df.sh
@@ -83,7 +83,7 @@ test_expect_success 'modify/delete + directory/file conflict' '
 	test -f letters~modify
 '
 
-test_expect_failure 'modify/delete + directory/file conflict; other way' '
+test_expect_success 'modify/delete + directory/file conflict; other way' '
 	git reset --hard &&
 	git clean -f &&
 	git checkout modify^0 &&
-- 
1.7.3.271.g16009

  parent reply	other threads:[~2010-09-20  8:30 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-20  8:28 [PATCH 00/37] Audit and fix corner case bugs in recursive merge Elijah Newren
2010-09-20  8:28 ` [PATCH 01/37] t3030: Add a testcase for resolvable rename/add conflict with symlinks Elijah Newren
2010-09-20  9:15   ` Johannes Sixt
2010-09-20  9:34   ` Jakub Narebski
2010-09-20  8:28 ` [PATCH 02/37] merge-recursive: Restructure showing how to chain more process_* functions Elijah Newren
2010-09-20  8:28 ` [PATCH 03/37] t6032: Add a test checking for excessive output from merge Elijah Newren
2010-09-20  8:28 ` [PATCH 04/37] t6022: Add test combinations of {content conflict?, D/F conflict remains?} Elijah Newren
2010-09-20  8:28 ` [PATCH 05/37] t6022: Add tests for reversing order of merges when D/F conflicts present Elijah Newren
2010-09-20  8:28 ` [PATCH 06/37] t6022: Add tests with both rename source & dest involved in D/F conflicts Elijah Newren
2010-09-20  8:28 ` [PATCH 07/37] t6022: Add paired rename+D/F conflict: (two/file, one/file) -> (one, two) Elijah Newren
2010-09-20  8:28 ` [PATCH 08/37] t6022: Add tests for rename/rename combined with D/F conflicts Elijah Newren
2010-09-20  8:28 ` [PATCH 09/37] t6020: Modernize style a bit Elijah Newren
2010-09-20  9:24   ` Johannes Sixt
2010-09-20 16:03     ` Elijah Newren
2010-09-22  1:44       ` Junio C Hamano
2010-09-22  4:41         ` Elijah Newren
2010-09-20  8:28 ` [PATCH 10/37] t6020: Add a testcase for modify/delete + directory/file conflict Elijah Newren
2010-09-20  8:28 ` [PATCH 11/37] t6036: Test index and worktree state, not just that merge fails Elijah Newren
2010-09-20  8:28 ` [PATCH 12/37] t6036: Add a second testcase similar to the first but with content changes Elijah Newren
2010-09-20  8:28 ` [PATCH 13/37] t6036: Add testcase for undetected conflict Elijah Newren
2010-09-20  8:28 ` [PATCH 14/37] merge-recursive: Small code clarification -- variable name and comments Elijah Newren
2010-09-20  8:28 ` [PATCH 15/37] merge-recursive: Rename conflict_rename_rename*() for clarity Elijah Newren
2010-09-20  8:28 ` [PATCH 16/37] merge-recursive: Nuke rename/directory conflict detection Elijah Newren
2010-09-20  8:28 ` [PATCH 17/37] merge-recursive: Move rename/delete handling into dedicated function Elijah Newren
2010-09-20  8:28 ` [PATCH 18/37] merge-recursive: Move delete/modify " Elijah Newren
2010-09-20  8:28 ` [PATCH 19/37] merge-recursive: Move process_entry's content merging into a function Elijah Newren
2010-09-20  8:28 ` [PATCH 20/37] merge-recursive: New data structures for deferring of D/F conflicts Elijah Newren
2010-09-20  8:28 ` [PATCH 21/37] merge-recursive: New function to assist resolving renames in-core only Elijah Newren
2010-09-20  8:28 ` [PATCH 22/37] merge-recursive: Have process_entry() skip D/F or rename entries Elijah Newren
2010-09-20  8:28 ` [PATCH 23/37] merge-recursive: Structure process_df_entry() to handle more cases Elijah Newren
2010-09-20  8:28 ` [PATCH 24/37] merge-recursive: Update conflict_rename_rename_1to2() call signature Elijah Newren
2010-09-20  8:28 ` [PATCH 25/37] merge-recursive: Update merge_content() " Elijah Newren
2010-09-20  8:28 ` [PATCH 26/37] merge-recursive: Avoid doubly merging rename/add conflict contents Elijah Newren
2010-09-20  8:29 ` [PATCH 27/37] merge-recursive: Move handling of double rename of one file to two Elijah Newren
2010-09-20  8:29 ` [PATCH 28/37] merge-recursive: Move handling of double rename of one file to other file Elijah Newren
2010-09-20  8:29 ` [PATCH 29/37] merge-recursive: Delay handling of rename/delete conflicts Elijah Newren
2010-09-20  8:29 ` [PATCH 30/37] merge-recursive: Delay content merging for renames Elijah Newren
2010-09-20  8:29 ` [PATCH 31/37] merge-recursive: Delay modify/delete conflicts if D/F conflict present Elijah Newren
2010-09-20  8:29 ` [PATCH 32/37] conflict_rename_delete(): Check whether D/F conflicts are still present Elijah Newren
2010-09-20  8:29 ` [PATCH 33/37] conflict_rename_rename_1to2(): Fix checks for presence of D/F conflicts Elijah Newren
2010-09-20  8:29 ` [PATCH 34/37] merge_content(): Check whether D/F conflicts are still present Elijah Newren
2010-09-20  8:29 ` [PATCH 35/37] handle_delete_modify(): " Elijah Newren
2010-09-20  8:29 ` Elijah Newren [this message]
2010-09-20 11:40   ` [PATCH 36/37] merge-recursive: Make room for directories in D/F conflicts Johannes Sixt
2010-09-20 16:06     ` Elijah Newren
2010-09-20  8:29 ` [PATCH 37/37] merge-recursive: Remove redundant path clearing for " Elijah Newren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1284971350-30590-37-git-send-email-newren@gmail.com \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).