On Tue, Aug 19, 2008 at 03:00:27PM -0700, Junio C Hamano [off-list ref] wrote:
and the call chain would become:
(...)
cmd_revert(), cmd_am(), cmd_checkout(), cmd_stash(), ...
-> merge_trees()
I tried to let cmd_revert() use merge_trees() only and not
merge_recursive_generic(), but something is fishy with it.
t3501-revert-cherry-pick passes fine, but t3404-rebase-interactive fail,
becase once we have a conflict, git diff --name-status says 'M' for the
given file and not 'U', which is obviously wrong.
I'm sending both patches: the one that works properly using
merge_recursive_generic() - and which one passes the testsuite here, and
the one that is elegant as it uses merge_trees(), but actually not
complete, at least regarding not adding the unmerged entries to the
index.
So, first here is my failed attempt to use merge_trees() inside
builtin-revert:
diff --git a/builtin-revert.c b/builtin-revert.c
index 3667705..3071518 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -12,6 +12,7 @@
#include "diff.h"
#include "revision.h"
#include "rerere.h"
+#include "merge-recursive.h"
/*
* This implements the builtins revert and cherry-pick.
@@ -201,36 +202,6 @@ static void set_author_ident_env(const char *message)
sha1_to_hex(commit->object.sha1));
}
-static int merge_recursive(const char *base_sha1,
- const char *head_sha1, const char *head_name,
- const char *next_sha1, const char *next_name)
-{
- char buffer[256];
- const char *argv[6];
- int i = 0;
-
- sprintf(buffer, "GITHEAD_%s", head_sha1);
- setenv(buffer, head_name, 1);
- sprintf(buffer, "GITHEAD_%s", next_sha1);
- setenv(buffer, next_name, 1);
-
- /*
- * This three way merge is an interesting one. We are at
- * $head, and would want to apply the change between $commit
- * and $prev on top of us (when reverting), or the change between
- * $prev and $commit on top of us (when cherry-picking or replaying).
- */
- argv[i++] = "merge-recursive";
- if (base_sha1)
- argv[i++] = base_sha1;
- argv[i++] = "--";
- argv[i++] = head_sha1;
- argv[i++] = next_sha1;
- argv[i++] = NULL;
-
- return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
-}
-
static char *help_msg(const unsigned char *sha1)
{
static char helpbuf[1024];@@ -271,6 +242,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
char *oneline, *reencoded_message = NULL;
const char *message, *encoding;
const char *defmsg = xstrdup(git_path("MERGE_MSG"));
+ struct merge_options o;
+ struct tree *result;
git_config(git_default_config, NULL);
me = action == REVERT ? "revert" : "cherry-pick";@@ -374,13 +347,16 @@ static int revert_or_cherry_pick(int argc, const char **argv)
}
}
- if (merge_recursive(base == NULL ?
- NULL : sha1_to_hex(base->object.sha1),
- sha1_to_hex(head), "HEAD",
- sha1_to_hex(next->object.sha1), oneline) ||
- write_cache_as_tree(head, 0, NULL)) {
+ read_cache();
+ init_merge_options(&o);
+ o.branch1 = "HEAD";
+ o.branch2 = oneline;
+ parse_commit(next);
+ parse_commit(base);
+ if (!merge_trees(&o, lookup_commit_reference_gently(head, 0)->tree,
+ next->tree, base->tree, &result) ||
+ write_cache_as_tree(head, 0, NULL)) {
add_to_msg("\nConflicts:\n\n");
- read_cache();
for (i = 0; i < active_nr;) {
struct cache_entry *ce = active_cache[i++];
if (ce_stage(ce)) {