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 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).