mirror of
https://github.com/git/git.git
synced 2024-11-28 04:23:30 +08:00
am -3: use merge_recursive() directly again
Last October, we had to change this code to run `git merge-recursive`
in a child process: git-am wants to print some helpful advice when the
merge failed, but the code in question was not prepared to return, it
die()d instead.
We are finally at a point when the code *is* prepared to return errors,
and can avoid the child process again.
This reverts commit c63d4b2
(am -3: do not let failed merge from
completing the error codepath, 2015-10-09), with the necessary changes
to adjust for the fact that Git's source code changed in the meantime
(such as: using OIDs instead of hashes in the recursive merge, and a
removed gender bias).
Note: the code now calls merge_recursive_generic() again. Unlike
merge_trees() and merge_recursive(), this function returns 0 upon success,
as most of Git's functions. Therefore, the error value -1 naturally is
handled correctly, and we do not have to take care of it specifically.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
6003303a1e
commit
3f338f43b0
62
builtin/am.c
62
builtin/am.c
@ -1578,48 +1578,19 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the three-way merge using fake ancestor, their tree constructed
|
||||
* from the fake ancestor and the postimage of the patch, and our
|
||||
* state.
|
||||
*/
|
||||
static int run_fallback_merge_recursive(const struct am_state *state,
|
||||
unsigned char *orig_tree,
|
||||
unsigned char *our_tree,
|
||||
unsigned char *their_tree)
|
||||
{
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
int status;
|
||||
|
||||
cp.git_cmd = 1;
|
||||
|
||||
argv_array_pushf(&cp.env_array, "GITHEAD_%s=%.*s",
|
||||
sha1_to_hex(their_tree), linelen(state->msg), state->msg);
|
||||
if (state->quiet)
|
||||
argv_array_push(&cp.env_array, "GIT_MERGE_VERBOSITY=0");
|
||||
|
||||
argv_array_push(&cp.args, "merge-recursive");
|
||||
argv_array_push(&cp.args, sha1_to_hex(orig_tree));
|
||||
argv_array_push(&cp.args, "--");
|
||||
argv_array_push(&cp.args, sha1_to_hex(our_tree));
|
||||
argv_array_push(&cp.args, sha1_to_hex(their_tree));
|
||||
|
||||
status = run_command(&cp) ? (-1) : 0;
|
||||
discard_cache();
|
||||
read_cache();
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt a threeway merge, using index_path as the temporary index.
|
||||
*/
|
||||
static int fall_back_threeway(const struct am_state *state, const char *index_path)
|
||||
{
|
||||
unsigned char orig_tree[GIT_SHA1_RAWSZ], their_tree[GIT_SHA1_RAWSZ],
|
||||
our_tree[GIT_SHA1_RAWSZ];
|
||||
struct object_id orig_tree, their_tree, our_tree;
|
||||
const struct object_id *bases[1] = { &orig_tree };
|
||||
struct merge_options o;
|
||||
struct commit *result;
|
||||
char *their_tree_name;
|
||||
|
||||
if (get_sha1("HEAD", our_tree) < 0)
|
||||
hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);
|
||||
if (get_oid("HEAD", &our_tree) < 0)
|
||||
hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN);
|
||||
|
||||
if (build_fake_ancestor(state, index_path))
|
||||
return error("could not build fake ancestor");
|
||||
@ -1627,7 +1598,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
||||
discard_cache();
|
||||
read_cache_from(index_path);
|
||||
|
||||
if (write_index_as_tree(orig_tree, &the_index, index_path, 0, NULL))
|
||||
if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL))
|
||||
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
|
||||
|
||||
say(state, stdout, _("Using index info to reconstruct a base tree..."));
|
||||
@ -1643,7 +1614,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
||||
init_revisions(&rev_info, NULL);
|
||||
rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
|
||||
diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
|
||||
add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
|
||||
add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0);
|
||||
diff_setup_done(&rev_info.diffopt);
|
||||
run_diff_index(&rev_info, 1);
|
||||
}
|
||||
@ -1652,7 +1623,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
||||
return error(_("Did you hand edit your patch?\n"
|
||||
"It does not apply to blobs recorded in its index."));
|
||||
|
||||
if (write_index_as_tree(their_tree, &the_index, index_path, 0, NULL))
|
||||
if (write_index_as_tree(their_tree.hash, &the_index, index_path, 0, NULL))
|
||||
return error("could not write tree");
|
||||
|
||||
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
|
||||
@ -1668,11 +1639,22 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
|
||||
* changes.
|
||||
*/
|
||||
|
||||
if (run_fallback_merge_recursive(state, orig_tree, our_tree, their_tree)) {
|
||||
init_merge_options(&o);
|
||||
|
||||
o.branch1 = "HEAD";
|
||||
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
|
||||
o.branch2 = their_tree_name;
|
||||
|
||||
if (state->quiet)
|
||||
o.verbosity = 0;
|
||||
|
||||
if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) {
|
||||
rerere(state->allow_rerere_autoupdate);
|
||||
free(their_tree_name);
|
||||
return error(_("Failed to merge in the changes."));
|
||||
}
|
||||
|
||||
free(their_tree_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user