[PATCH 4/6] builtin-checkout.c: refactor merge_working_tree()

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

 



The logic to bring the index and the working tree from one commit to
another is a nontrivial amount of code in this function.  Separate it out
into its own function, so that other callers can call it.

Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx>
---
 builtin-checkout.c |  172 +++++++++++++++++++++++++++-------------------------
 1 files changed, 89 insertions(+), 83 deletions(-)

diff --git a/builtin-checkout.c b/builtin-checkout.c
index d88fce2..9c45c49 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -352,6 +352,87 @@ static int reset_tree(struct tree *tree, int quiet, int worktree, int *wt_error)
 	}
 }
 
+static int switch_trees(int merge, int quiet, int *wt_error,
+			struct commit *old_commit, const char *old_label,
+			struct commit *new_commit, const char *new_label)
+{
+	int ret;
+	struct tree_desc trees[2];
+	struct tree *tree;
+	struct unpack_trees_options topts;
+
+	memset(&topts, 0, sizeof(topts));
+	topts.head_idx = -1;
+	topts.src_index = &the_index;
+	topts.dst_index = &the_index;
+
+	topts.msgs.not_uptodate_file = "You have local changes to '%s'; cannot switch branches.";
+
+	refresh_cache(REFRESH_QUIET);
+
+	if (unmerged_cache()) {
+		error("you need to resolve your current index first");
+		return 1;
+	}
+
+	/* 2-way merge to the new branch */
+	topts.initial_checkout = is_cache_unborn();
+	topts.update = 1;
+	topts.merge = 1;
+	topts.gently = merge;
+	topts.verbose_update = !quiet;
+	topts.fn = twoway_merge;
+	topts.dir = xcalloc(1, sizeof(*topts.dir));
+	topts.dir->show_ignored = 1;
+	topts.dir->exclude_per_dir = ".gitignore";
+	tree = parse_tree_indirect(old_commit->object.sha1);
+	init_tree_desc(&trees[0], tree->buffer, tree->size);
+	tree = parse_tree_indirect(new_commit->object.sha1);
+	init_tree_desc(&trees[1], tree->buffer, tree->size);
+
+	ret = unpack_trees(2, trees, &topts);
+	if (ret == -1) {
+		/*
+		 * Unpack couldn't do a trivial merge; either give up
+		 * or do a real merge, depending on whether the merge
+		 * flag was used.
+		 */
+		struct tree *result;
+		struct tree *work;
+		struct merge_options o;
+		if (!merge)
+			return 1;
+		parse_commit(old_commit);
+
+		/* Do more real merge */
+
+		/*
+		 * We update the index fully, then write the tree from
+		 * the index, then merge the new branch with the
+		 * current tree, with the old branch as the base. Then
+		 * we reset the index (but not the working tree) to
+		 * the new branch, leaving the working tree as the
+		 * merged version, but skipping unmerged entries in
+		 * the index.
+		 */
+
+		add_files_to_cache(NULL, NULL, 0);
+		init_merge_options(&o);
+		o.verbosity = 0;
+		work = write_tree_from_memory(&o);
+
+		ret = reset_tree(new_commit->tree, quiet, 1, wt_error);
+		if (ret)
+			return ret;
+		o.branch1 = new_label;
+		o.branch2 = old_label;
+		merge_trees(&o, new_commit->tree, work,
+			    old_commit->tree, &result);
+		ret = reset_tree(new_commit->tree, quiet, 0, wt_error);
+	}
+	return ret;
+}
+
 struct branch_info {
 	const char *name; /* The short name used */
 	const char *path; /* The full name of a real branch */
@@ -376,91 +457,16 @@ static int merge_working_tree(struct checkout_opts *opts,
 	if (read_cache() < 0)
 		return error("corrupt index file");
 
-	if (opts->force) {
+	if (opts->force)
 		ret = reset_tree(new->commit->tree, opts->quiet, 1,
 				 &opts->writeout_error);
-		if (ret)
-			return ret;
-	} else {
-		struct tree_desc trees[2];
-		struct tree *tree;
-		struct unpack_trees_options topts;
-
-		memset(&topts, 0, sizeof(topts));
-		topts.head_idx = -1;
-		topts.src_index = &the_index;
-		topts.dst_index = &the_index;
-
-		topts.msgs.not_uptodate_file = "You have local changes to '%s'; cannot switch branches.";
-
-		refresh_cache(REFRESH_QUIET);
-
-		if (unmerged_cache()) {
-			error("you need to resolve your current index first");
-			return 1;
-		}
-
-		/* 2-way merge to the new branch */
-		topts.initial_checkout = is_cache_unborn();
-		topts.update = 1;
-		topts.merge = 1;
-		topts.gently = opts->merge;
-		topts.verbose_update = !opts->quiet;
-		topts.fn = twoway_merge;
-		topts.dir = xcalloc(1, sizeof(*topts.dir));
-		topts.dir->show_ignored = 1;
-		topts.dir->exclude_per_dir = ".gitignore";
-		tree = parse_tree_indirect(old->commit->object.sha1);
-		init_tree_desc(&trees[0], tree->buffer, tree->size);
-		tree = parse_tree_indirect(new->commit->object.sha1);
-		init_tree_desc(&trees[1], tree->buffer, tree->size);
-
-		ret = unpack_trees(2, trees, &topts);
-		if (ret == -1) {
-			/*
-			 * Unpack couldn't do a trivial merge; either
-			 * give up or do a real merge, depending on
-			 * whether the merge flag was used.
-			 */
-			struct tree *result;
-			struct tree *work;
-			struct merge_options o;
-			if (!opts->merge)
-				return 1;
-			parse_commit(old->commit);
-
-			/* Do more real merge */
-
-			/*
-			 * We update the index fully, then write the
-			 * tree from the index, then merge the new
-			 * branch with the current tree, with the old
-			 * branch as the base. Then we reset the index
-			 * (but not the working tree) to the new
-			 * branch, leaving the working tree as the
-			 * merged version, but skipping unmerged
-			 * entries in the index.
-			 */
-
-			add_files_to_cache(NULL, NULL, 0);
-			init_merge_options(&o);
-			o.verbosity = 0;
-			work = write_tree_from_memory(&o);
-
-			ret = reset_tree(new->commit->tree, opts->quiet, 1,
-					 &opts->writeout_error);
-			if (ret)
-				return ret;
-			o.branch1 = new->name;
-			o.branch2 = "local";
-			merge_trees(&o, new->commit->tree, work,
-				old->commit->tree, &result);
-			ret = reset_tree(new->commit->tree, opts->quiet, 0,
-					 &opts->writeout_error);
-			if (ret)
-				return ret;
-		}
-	}
+	else
+		ret = switch_trees(opts->merge, opts->quiet,
+				   &opts->writeout_error,
+				   old->commit, "local",
+				   new->commit, new->name);
+	if (ret)
+		return ret;
 
 	if (write_cache(newfd, active_cache, active_nr) ||
 	    commit_locked_index(lock_file))
-- 
1.6.1.rc1.72.ga5ce6

--
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]

  Powered by Linux