git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Elijah Newren <newren@gmail.com>
To: git@vger.kernel.org
Cc: Elijah Newren <newren@gmail.com>
Subject: [RFC/PATCH 12/18] Add --index-only support for recursive merges
Date: Thu,  7 Apr 2016 23:58:40 -0700	[thread overview]
Message-ID: <1460098726-5958-13-git-send-email-newren@gmail.com> (raw)
In-Reply-To: <1460098726-5958-1-git-send-email-newren@gmail.com>

The merge-recursive logic already had the ability to ignore the working
directory and operate entirely on the index -- it needed to do this when
creating a virtual merge base, i.e. when o->call_depth > 0.

The only trick here is that o->call_depth > 0 was also checked to
determine whether all merges conflicts should be forcibly immediately
resolved (typically by treating a copy of the code with conflict markers
still in it as the resolution) in order to get us some actual base tree
to work with.

Introduce a new merge option o->index_only which is true whenver either
--index-only is passed or o->call_depth > 0, and make the portions of
merge-recursive that are about operating only on the index look at
o->index_only, and the portions that are about forcibly immediately
resolving conflicts check o->call_depth.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-recursive.c           | 37 ++++++++++++++++++++++---------------
 t/t6043-merge-index-only.sh | 12 ++++++------
 2 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index b346ed6..6af37ed 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -406,10 +406,11 @@ static void record_df_conflict_files(struct merge_options *o,
 	int i;
 
 	/*
-	 * If we're merging merge-bases, we don't want to bother with
-	 * any working directory changes.
+	 * If we're doing an index-only merge, we don't need to check for
+	 * which files to remove from the working copy to make room for
+	 * paths below directories of D/F conflicts; we can just exit early.
 	 */
-	if (o->call_depth)
+	if (o->index_only)
 		return;
 
 	/* Ensure D/F conflicts are adjacent in the entries list. */
@@ -581,7 +582,7 @@ static int remove_file(struct merge_options *o, int clean,
 		       const char *path, int no_wd)
 {
 	int update_cache = o->call_depth || clean;
-	int update_working_directory = !o->call_depth && !no_wd;
+	int update_working_directory = !o->index_only && !no_wd;
 
 	if (update_cache) {
 		if (remove_file_from_cache(path))
@@ -622,7 +623,7 @@ static char *unique_path(struct merge_options *o, const char *path, const char *
 	base_len = newpath.len;
 	while (string_list_has_string(&o->current_file_set, newpath.buf) ||
 	       string_list_has_string(&o->current_directory_set, newpath.buf) ||
-	       (!o->call_depth && file_exists(newpath.buf))) {
+	       (!o->index_only && file_exists(newpath.buf))) {
 		strbuf_setlen(&newpath, base_len);
 		strbuf_addf(&newpath, "_%d", suffix++);
 	}
@@ -742,7 +743,7 @@ static void update_file_flags(struct merge_options *o,
 			      int update_cache,
 			      int update_wd)
 {
-	if (o->call_depth)
+	if (o->index_only)
 		update_wd = 0;
 
 	if (update_wd) {
@@ -813,7 +814,7 @@ static void update_file(struct merge_options *o,
 			unsigned mode,
 			const char *path)
 {
-	update_file_flags(o, sha, mode, path, o->call_depth || clean, !o->call_depth);
+	update_file_flags(o, sha, mode, path, o->call_depth || clean, !o->index_only);
 }
 
 /* Low level file merging, update and removal */
@@ -1017,7 +1018,7 @@ static void handle_change_delete(struct merge_options *o,
 				 const char *change, const char *change_past)
 {
 	char *renamed = NULL;
-	if (dir_in_way(path, !o->call_depth)) {
+	if (dir_in_way(path, !o->index_only)) {
 		renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);
 	}
 
@@ -1145,7 +1146,7 @@ static void handle_file(struct merge_options *o,
 		remove_file(o, 0, rename->path, 0);
 		dst_name = unique_path(o, rename->path, cur_branch);
 	} else {
-		if (dir_in_way(rename->path, !o->call_depth)) {
+		if (dir_in_way(rename->path, !o->index_only)) {
 			dst_name = unique_path(o, rename->path, cur_branch);
 			output(o, 1, _("%s is a directory in %s adding as %s instead"),
 			       rename->path, other_branch, dst_name);
@@ -1234,8 +1235,8 @@ static void conflict_rename_rename_2to1(struct merge_options *o,
 	       a->path, c1->path, ci->branch1,
 	       b->path, c2->path, ci->branch2);
 
-	remove_file(o, 1, a->path, o->call_depth || would_lose_untracked(a->path));
-	remove_file(o, 1, b->path, o->call_depth || would_lose_untracked(b->path));
+	remove_file(o, 1, a->path, o->index_only || would_lose_untracked(a->path));
+	remove_file(o, 1, b->path, o->index_only || would_lose_untracked(b->path));
 
 	mfi_c1 = merge_file_special_markers(o, a, c1, &ci->ren1_other,
 					    o->branch1, c1->path,
@@ -1619,7 +1620,7 @@ static int merge_content(struct merge_options *o,
 			 o->branch2 == rename_conflict_info->branch1) ?
 			pair1->two->path : pair1->one->path;
 
-		if (dir_in_way(path, !o->call_depth))
+		if (dir_in_way(path, !o->index_only))
 			df_conflict_remains = 1;
 	}
 	mfi = merge_file_special_markers(o, &one, &a, &b,
@@ -1639,7 +1640,7 @@ static int merge_content(struct merge_options *o,
 		path_renamed_outside_HEAD = !path2 || !strcmp(path, path2);
 		if (!path_renamed_outside_HEAD) {
 			add_cacheinfo(mfi.mode, mfi.sha, path,
-				      0, (!o->call_depth), 0);
+				      0, (!o->index_only), 0);
 			return mfi.clean;
 		}
 	} else
@@ -1767,7 +1768,7 @@ static int process_entry(struct merge_options *o,
 			sha = b_sha;
 			conf = _("directory/file");
 		}
-		if (dir_in_way(path, !o->call_depth)) {
+		if (dir_in_way(path, !o->index_only)) {
 			char *new_path = unique_path(o, path, add_branch);
 			clean_merge = 0;
 			output(o, 1, _("CONFLICT (%s): There is a directory with name %s in %s. "
@@ -1819,7 +1820,7 @@ int merge_trees(struct merge_options *o,
 		return 1;
 	}
 
-	code = git_merge_trees(o->call_depth, common, head, merge);
+	code = git_merge_trees(o->index_only, common, head, merge);
 
 	if (code != 0) {
 		if (show(o, 4) || o->call_depth)
@@ -1899,6 +1900,7 @@ int merge_recursive(struct merge_options *o,
 	struct commit *merged_common_ancestors;
 	struct tree *mrtree = mrtree;
 	int clean;
+	int prev_index_only_setting;
 
 	if (show(o, 4)) {
 		output(o, 4, _("Merging:"));
@@ -1929,9 +1931,12 @@ int merge_recursive(struct merge_options *o,
 		merged_common_ancestors = make_virtual_commit(tree, "ancestor");
 	}
 
+	prev_index_only_setting = o->index_only;
+
 	for (iter = ca; iter; iter = iter->next) {
 		const char *saved_b1, *saved_b2;
 		o->call_depth++;
+		o->index_only = 1;
 		/*
 		 * When the merge fails, the result contains files
 		 * with conflict markers. The cleanness flag is
@@ -1954,6 +1959,8 @@ int merge_recursive(struct merge_options *o,
 			die(_("merge returned no commit"));
 	}
 
+	o->index_only = prev_index_only_setting;
+
 	discard_cache();
 	if (!o->call_depth)
 		read_cache();
diff --git a/t/t6043-merge-index-only.sh b/t/t6043-merge-index-only.sh
index 9bb64d8..2e1d953 100755
--- a/t/t6043-merge-index-only.sh
+++ b/t/t6043-merge-index-only.sh
@@ -28,7 +28,7 @@ test_expect_success 'setup rename/modify merge' '
 	git commit -m C
 '
 
-test_expect_failure '--index-only with rename/modify works in non-bare-clone' '
+test_expect_success '--index-only with rename/modify works in non-bare-clone' '
 	git checkout B^0 &&
 
 	git merge --index-only -s recursive C^0 &&
@@ -43,7 +43,7 @@ test_expect_failure '--index-only with rename/modify works in non-bare-clone' '
 	test $(git rev-parse B:a) = $(git rev-parse :b)
 '
 
-test_expect_failure '--index-only with rename/modify works in a bare clone' '
+test_expect_success '--index-only with rename/modify works in a bare clone' '
 	git clone --bare . bare.clone &&
 	(cd bare.clone &&
 
@@ -136,7 +136,7 @@ test_expect_success 'setup single-file criss-cross resolvable with recursive str
 	rm -f answer
 '
 
-test_expect_failure 'recursive --index-only in non-bare repo' '
+test_expect_success 'recursive --index-only in non-bare repo' '
 	git reset --hard &&
 	git checkout L2^0 &&
 
@@ -150,7 +150,7 @@ test_expect_failure 'recursive --index-only in non-bare repo' '
 	test $(git rev-parse L2:contents) = $(git hash-object contents)
 '
 
-test_expect_failure 'recursive --index-only in bare repo' '
+test_expect_success 'recursive --index-only in bare repo' '
 	git clone --bare . bare.clone &&
 	(cd bare.clone &&
 
@@ -406,7 +406,7 @@ test_expect_success '--index-only ours, bare' '
 	)
 '
 
-test_expect_failure '--index-only subtree, non-bare' '
+test_expect_success '--index-only subtree, non-bare' '
 	git reset --hard &&
 	git checkout B^0 &&
 
@@ -420,7 +420,7 @@ test_expect_failure '--index-only subtree, non-bare' '
 	test ! -f e
 '
 
-test_expect_failure '--index-only subtree, bare' '
+test_expect_success '--index-only subtree, bare' '
 	rm -rf bare.clone &&
 	git clone --bare . bare.clone &&
 	(cd bare.clone &&
-- 
2.8.0.18.gc685494

  parent reply	other threads:[~2016-04-08  7:00 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-08  6:58 [RFC/PATCH 00/18] Add --index-only option to git merge Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 01/18] Remove duplicate code Elijah Newren
2016-04-08 23:34   ` Junio C Hamano
2016-04-08  6:58 ` [RFC/PATCH 02/18] Avoid checking working copy when creating a virtual merge base Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 03/18] Document weird bug in octopus merges via testcases Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 04/18] merge-octopus: Abort if index not clean Elijah Newren
2016-04-08 19:31   ` Junio C Hamano
2016-04-08  6:58 ` [RFC/PATCH 05/18] Add testcase for --index-only merges needing the recursive strategy Elijah Newren
2016-04-08 19:37   ` Junio C Hamano
2016-04-08 20:14     ` Junio C Hamano
2016-04-08  6:58 ` [RFC/PATCH 06/18] Add testcase for --index-only merges needing an ff update Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 07/18] Add testcase for --index-only merges with the resolve strategy Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 08/18] Add testcase for --index-only merges with the octopus strategy Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 09/18] Add testcase for --index-only merges with the ours strategy Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 10/18] Add testcase for --index-only merges with the subtree strategy Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 11/18] merge: Add a new --index-only option, not yet implemented Elijah Newren
2016-04-08 22:33   ` Junio C Hamano
2016-04-08  6:58 ` Elijah Newren [this message]
2016-04-08  6:58 ` [RFC/PATCH 13/18] Add --index-only support with read_tree_trivial merges, kind of Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 14/18] Add --index-only support for ff_only merges Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 15/18] merge: Pass --index-only along to external merge strategy programs Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 16/18] git-merge-one-file.sh: support --index-only option Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 17/18] git-merge-resolve.sh: " Elijah Newren
2016-04-08  6:58 ` [RFC/PATCH 18/18] git-merge-octopus.sh: " Elijah Newren
2016-04-08 13:01 ` [RFC/PATCH 00/18] Add --index-only option to git merge Michael J Gruber
2016-04-09  3:09   ` Elijah Newren
2016-04-08 18:08 ` Junio C Hamano
2016-04-09  2:35   ` Elijah Newren
2016-04-09  4:44     ` Junio C Hamano
2016-04-10  5:33 ` 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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=1460098726-5958-13-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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).