Subject: [PATCH/WIP 2/8] Move reset_tree from builtin/checkout.c to unpack-trees.c

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Wed, 18 Mar 2015 16:55:41 +0700

---
 builtin/checkout.c | 40 +++-------------------------------------
 builtin/merge.c    | 29 +++++++----------------------
 unpack-trees.c     | 33 +++++++++++++++++++++++++++++++++
 unpack-trees.h     |  4 ++++
 4 files changed, 47 insertions(+), 59 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index a9c1b5a..93b18ad 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -362,40 +362,6 @@ static void describe_detached_head(const char *msg, struct commit *commit)
 	strbuf_release(&sb);
 }
 
-static int reset_tree(struct tree *tree, const struct checkout_opts *o,
-		      int worktree, int *writeout_error)
-{
-	struct unpack_trees_options opts;
-	struct tree_desc tree_desc;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = -1;
-	opts.update = worktree;
-	opts.skip_unmerged = !worktree;
-	opts.reset = 1;
-	opts.merge = 1;
-	opts.fn = oneway_merge;
-	opts.verbose_update = !o->quiet && isatty(2);
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	parse_tree(tree);
-	init_tree_desc(&tree_desc, tree->buffer, tree->size);
-	switch (unpack_trees(1, &tree_desc, &opts)) {
-	case -2:
-		*writeout_error = 1;
-		/*
-		 * We return 0 nevertheless, as the index is all right
-		 * and more importantly we have made best efforts to
-		 * update paths in the work tree, and we cannot revert
-		 * them.
-		 */
-	case 0:
-		return 0;
-	default:
-		return 128;
-	}
-}
-
 struct branch_info {
 	const char *name; /* The short name used */
 	const char *path; /* The full name of a real branch */
@@ -427,7 +393,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
 
 	resolve_undo_clear();
 	if (opts->force) {
-		ret = reset_tree(new->commit->tree, opts, 1, writeout_error);
+		ret = reset_tree(new->commit->tree, opts->quiet, 1, writeout_error);
 		if (ret)
 			return ret;
 	} else {
@@ -513,7 +479,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			o.verbosity = 0;
 			work = write_tree_from_memory(&o);
 
-			ret = reset_tree(new->commit->tree, opts, 1,
+			ret = reset_tree(new->commit->tree, opts->quiet, 1,
 					 writeout_error);
 			if (ret)
 				return ret;
@@ -522,7 +488,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			o.branch2 = "local";
 			merge_trees(&o, new->commit->tree, work,
 				old->commit->tree, &result);
-			ret = reset_tree(new->commit->tree, opts, 0,
+			ret = reset_tree(new->commit->tree, opts->quiet, 0,
 					 writeout_error);
 			if (ret)
 				return ret;
diff --git a/builtin/merge.c b/builtin/merge.c
index 6babf39..c51e4f5 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -269,33 +269,18 @@ static void read_empty(unsigned const char *sha1, int verbose)
 		die(_("read-tree failed"));
 }
 
-static void reset_hard(unsigned const char *sha1, int verbose)
-{
-	int i = 0;
-	const char *args[6];
-
-	args[i++] = "read-tree";
-	if (verbose)
-		args[i++] = "-v";
-	args[i++] = "--reset";
-	args[i++] = "-u";
-	args[i++] = sha1_to_hex(sha1);
-	args[i] = NULL;
-
-	if (run_command_v_opt(args, RUN_GIT_CMD))
-		die(_("read-tree failed"));
-}
-
-static void restore_state(const unsigned char *head,
+static void restore_state(struct commit *head_commit,
 			  const unsigned char *stash)
 {
 	struct strbuf sb = STRBUF_INIT;
 	const char *args[] = { "stash", "apply", NULL, NULL };
+	int error = 0;
 
 	if (is_null_sha1(stash))
 		return;
 
-	reset_hard(head, 1);
+	if (reset_tree(head_commit->tree, 0, 1, &error) || error)
+		die(_("read-tree failed"));
 
 	args[2] = sha1_to_hex(stash);
 
@@ -1409,7 +1394,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		int ret;
 		if (i) {
 			printf(_("Rewinding the tree to pristine...\n"));
-			restore_state(head_commit->object.sha1, stash);
+			restore_state(head_commit, stash);
 		}
 		if (use_strategies_nr != 1)
 			printf(_("Trying merge strategy %s...\n"),
@@ -1475,7 +1460,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	 * it up.
 	 */
 	if (!best_strategy) {
-		restore_state(head_commit->object.sha1, stash);
+		restore_state(head_commit, stash);
 		if (use_strategies_nr > 1)
 			fprintf(stderr,
 				_("No merge strategy handled the merge.\n"));
@@ -1488,7 +1473,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		; /* We already have its result in the working tree. */
 	else {
 		printf(_("Rewinding the tree to pristine...\n"));
-		restore_state(head_commit->object.sha1, stash);
+		restore_state(head_commit, stash);
 		printf(_("Using the %s to prepare resolving by hand.\n"),
 			best_strategy);
 		try_merge_strategy(best_strategy, common, remoteheads,
diff --git a/unpack-trees.c b/unpack-trees.c
index 0e1a196..3c24a4d 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1847,3 +1847,36 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
 	}
 	return merged_entry(a, old, o);
 }
+
+int reset_tree(struct tree *tree, int quiet, int worktree, int *writeout_error)
+{
+	struct unpack_trees_options opts;
+	struct tree_desc tree_desc;
+
+	memset(&opts, 0, sizeof(opts));
+	opts.head_idx = -1;
+	opts.update = worktree;
+	opts.skip_unmerged = !worktree;
+	opts.reset = 1;
+	opts.merge = 1;
+	opts.fn = oneway_merge;
+	opts.verbose_update = !quiet && isatty(2);
+	opts.src_index = &the_index;
+	opts.dst_index = &the_index;
+	parse_tree(tree);
+	init_tree_desc(&tree_desc, tree->buffer, tree->size);
+	switch (unpack_trees(1, &tree_desc, &opts)) {
+	case -2:
+		*writeout_error = 1;
+		/*
+		 * We return 0 nevertheless, as the index is all right
+		 * and more importantly we have made best efforts to
+		 * update paths in the work tree, and we cannot revert
+		 * them.
+		 */
+	case 0:
+		return 0;
+	default:
+		return 128;
+	}
+}
diff --git a/unpack-trees.h b/unpack-trees.h
index ec74a9f..f0850bb 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -83,4 +83,8 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o);
 int bind_merge(struct cache_entry **src, struct unpack_trees_options *o);
 int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o);
 
+
+struct tree;
+extern int reset_tree(struct tree *tree, int quiet,
+		      int worktree, int *writeout_error);
 #endif
-- 
2.3.0.rc1.137.g477eb31