From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 4/6] builtin-checkout.c: refactor merge_working_tree()
Date: Fri, 5 Dec 2008 17:54:13 -0800 [thread overview]
Message-ID: <1228528455-3089-5-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1228528455-3089-4-git-send-email-gitster@pobox.com>
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@pobox.com>
---
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
next prev parent reply other threads:[~2008-12-06 1:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-06 1:54 [PATCH 0/6] Reusing "checkout [-m]" logic for "reset --merge" Junio C Hamano
2008-12-06 1:54 ` [PATCH 1/6] builtin-checkout.c: check error return from read_cache() Junio C Hamano
2008-12-06 1:54 ` [PATCH 2/6] read-cache.c: typofix in comment Junio C Hamano
2008-12-06 1:54 ` [PATCH 3/6] Make reset_tree() in builtin-checkout.c a bit more library-ish Junio C Hamano
2008-12-06 1:54 ` Junio C Hamano [this message]
2008-12-06 1:54 ` [PATCH 5/6] builtin-commit.c: further refactor branch switching Junio C Hamano
2008-12-06 1:54 ` [PATCH 6/6] builtin-reset.c: use reset_index_and_worktree() Junio C Hamano
2008-12-06 2:08 ` [PATCH 5/6] builtin-commit.c: further refactor branch switching Linus Torvalds
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=1228528455-3089-5-git-send-email-gitster@pobox.com \
--to=gitster@pobox.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.