diff options
Diffstat (limited to 'builtin/am.c')
-rw-r--r-- | builtin/am.c | 93 |
1 files changed, 36 insertions, 57 deletions
diff --git a/builtin/am.c b/builtin/am.c index d5da5fe090..9e2ae5cba4 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -184,22 +184,22 @@ static inline const char *am_path(const struct am_state *state, const char *path /** * For convenience to call write_file() */ -static int write_state_text(const struct am_state *state, - const char *name, const char *string) +static void write_state_text(const struct am_state *state, + const char *name, const char *string) { - return write_file(am_path(state, name), "%s", string); + write_file(am_path(state, name), "%s", string); } -static int write_state_count(const struct am_state *state, - const char *name, int value) +static void write_state_count(const struct am_state *state, + const char *name, int value) { - return write_file(am_path(state, name), "%d", value); + write_file(am_path(state, name), "%d", value); } -static int write_state_bool(const struct am_state *state, - const char *name, int value) +static void write_state_bool(const struct am_state *state, + const char *name, int value) { - return write_state_text(state, name, value ? "t" : "f"); + write_state_text(state, name, value ? "t" : "f"); } /** @@ -403,13 +403,8 @@ static int read_commit_msg(struct am_state *state) */ static void write_commit_msg(const struct am_state *state) { - int fd; const char *filename = am_path(state, "final-commit"); - - fd = xopen(filename, O_WRONLY | O_CREAT, 0666); - if (write_in_full(fd, state->msg, state->msg_len) < 0) - die_errno(_("could not write to %s"), filename); - close(fd); + write_file_buf(filename, state->msg, state->msg_len); } /** @@ -1584,47 +1579,18 @@ static int build_fake_ancestor(const struct am_state *state, const char *index_f } /** - * Do the three-way merge using fake ancestor, his 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 *his_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(his_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(his_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], his_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"); @@ -1632,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...")); @@ -1648,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); } @@ -1657,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(his_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...")); @@ -1667,17 +1633,28 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa /* * This is not so wrong. Depending on which base we picked, orig_tree - * may be wildly different from ours, but his_tree has the same set of + * may be wildly different from ours, but their_tree has the same set of * wildly different changes in parts the patch did not touch, so * recursive ends up canceling them, saying that we reverted all those * changes. */ - if (run_fallback_merge_recursive(state, orig_tree, our_tree, his_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; } @@ -1845,6 +1822,8 @@ static void am_run(struct am_state *state, int resume) const char *mail = am_path(state, msgnum(state)); int apply_status; + reset_ident_date(); + if (!file_exists(mail)) goto next; @@ -2243,7 +2222,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) int in_progress; const char * const usage[] = { - N_("git am [<options>] [(<mbox>|<Maildir>)...]"), + N_("git am [<options>] [(<mbox> | <Maildir>)...]"), N_("git am [<options>] (--continue | --skip | --abort)"), NULL }; |