diff options
Diffstat (limited to 'builtin/am.c')
-rw-r--r-- | builtin/am.c | 207 |
1 files changed, 114 insertions, 93 deletions
diff --git a/builtin/am.c b/builtin/am.c index b36d1f047d..6981f42ce9 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -28,6 +28,7 @@ #include "rerere.h" #include "prompt.h" #include "mailinfo.h" +#include "apply.h" #include "string-list.h" /** @@ -109,7 +110,7 @@ struct am_state { size_t msg_len; /* when --rebasing, records the original commit the patch came from */ - unsigned char orig_commit[GIT_SHA1_RAWSZ]; + struct object_id orig_commit; /* number of digits in patch filename */ int prec; @@ -415,8 +416,8 @@ static void am_load(struct am_state *state) read_commit_msg(state); if (read_state_file(&sb, state, "original-commit", 1) < 0) - hashclr(state->orig_commit); - else if (get_sha1_hex(sb.buf, state->orig_commit) < 0) + oidclr(&state->orig_commit); + else if (get_oid_hex(sb.buf, &state->orig_commit) < 0) die(_("could not parse %s"), am_path(state, "original-commit")); read_state_file(&sb, state, "threeway", 1); @@ -542,14 +543,14 @@ static int copy_notes_for_rebase(const struct am_state *state) fp = xfopen(am_path(state, "rewritten"), "r"); while (!strbuf_getline_lf(&sb, fp)) { - unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ]; + struct object_id from_obj, to_obj; if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) { ret = error(invalid_line, sb.buf); goto finish; } - if (get_sha1_hex(sb.buf, from_obj)) { + if (get_oid_hex(sb.buf, &from_obj)) { ret = error(invalid_line, sb.buf); goto finish; } @@ -559,14 +560,14 @@ static int copy_notes_for_rebase(const struct am_state *state) goto finish; } - if (get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ + 1, to_obj)) { + if (get_oid_hex(sb.buf + GIT_SHA1_HEXSZ + 1, &to_obj)) { ret = error(invalid_line, sb.buf); goto finish; } - if (copy_note_for_rewrite(c, from_obj, to_obj)) + if (copy_note_for_rewrite(c, from_obj.hash, to_obj.hash)) ret = error(_("Failed to copy notes from '%s' to '%s'"), - sha1_to_hex(from_obj), sha1_to_hex(to_obj)); + oid_to_hex(&from_obj), oid_to_hex(&to_obj)); } finish: @@ -972,7 +973,7 @@ static int split_mail(struct am_state *state, enum patch_format patch_format, static void am_setup(struct am_state *state, enum patch_format patch_format, const char **paths, int keep_cr) { - unsigned char curr_head[GIT_SHA1_RAWSZ]; + struct object_id curr_head; const char *str; struct strbuf sb = STRBUF_INIT; @@ -1040,10 +1041,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format, else write_state_text(state, "applying", ""); - if (!get_sha1("HEAD", curr_head)) { - write_state_text(state, "abort-safety", sha1_to_hex(curr_head)); + if (!get_oid("HEAD", &curr_head)) { + write_state_text(state, "abort-safety", oid_to_hex(&curr_head)); if (!state->rebasing) - update_ref("am", "ORIG_HEAD", curr_head, NULL, 0, + update_ref_oid("am", "ORIG_HEAD", &curr_head, NULL, 0, UPDATE_REFS_DIE_ON_ERR); } else { write_state_text(state, "abort-safety", ""); @@ -1068,7 +1069,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format, */ static void am_next(struct am_state *state) { - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; free(state->author_name); state->author_name = NULL; @@ -1086,11 +1087,11 @@ static void am_next(struct am_state *state) unlink(am_path(state, "author-script")); unlink(am_path(state, "final-commit")); - hashclr(state->orig_commit); + oidclr(&state->orig_commit); unlink(am_path(state, "original-commit")); - if (!get_sha1("HEAD", head)) - write_state_text(state, "abort-safety", sha1_to_hex(head)); + if (!get_oid("HEAD", &head)) + write_state_text(state, "abort-safety", oid_to_hex(&head)); else write_state_text(state, "abort-safety", ""); @@ -1132,17 +1133,17 @@ static void refresh_and_write_cache(void) */ static int index_has_changes(struct strbuf *sb) { - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; int i; - if (!get_sha1_tree("HEAD", head)) { + if (!get_sha1_tree("HEAD", head.hash)) { struct diff_options opt; diff_setup(&opt); DIFF_OPT_SET(&opt, EXIT_WITH_STATUS); if (!sb) DIFF_OPT_SET(&opt, QUICK); - do_diff_cache(head, &opt); + do_diff_cache(head.hash, &opt); diffcore_std(&opt); for (i = 0; sb && i < diff_queued_diff.nr; i++) { if (i) @@ -1349,7 +1350,7 @@ finish: * Sets commit_id to the commit hash where the mail was generated from. * Returns 0 on success, -1 on failure. */ -static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail) +static int get_mail_commit_oid(struct object_id *commit_id, const char *mail) { struct strbuf sb = STRBUF_INIT; FILE *fp = xfopen(mail, "r"); @@ -1361,7 +1362,7 @@ static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail) if (!skip_prefix(sb.buf, "From ", &x)) return -1; - if (get_sha1_hex(x, commit_id) < 0) + if (get_oid_hex(x, commit_id) < 0) return -1; strbuf_release(&sb); @@ -1451,12 +1452,12 @@ static void write_commit_patch(const struct am_state *state, struct commit *comm static void write_index_patch(const struct am_state *state) { struct tree *tree; - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; struct rev_info rev_info; FILE *fp; - if (!get_sha1_tree("HEAD", head)) - tree = lookup_tree(head); + if (!get_sha1_tree("HEAD", head.hash)) + tree = lookup_tree(head.hash); else tree = lookup_tree(EMPTY_TREE_SHA1_BIN); @@ -1486,19 +1487,19 @@ static void write_index_patch(const struct am_state *state) static int parse_mail_rebase(struct am_state *state, const char *mail) { struct commit *commit; - unsigned char commit_sha1[GIT_SHA1_RAWSZ]; + struct object_id commit_oid; - if (get_mail_commit_sha1(commit_sha1, mail) < 0) + if (get_mail_commit_oid(&commit_oid, mail) < 0) die(_("could not parse %s"), mail); - commit = lookup_commit_or_die(commit_sha1, mail); + commit = lookup_commit_or_die(commit_oid.hash, mail); get_commit_info(state, commit); write_commit_patch(state, commit); - hashcpy(state->orig_commit, commit_sha1); - write_state_text(state, "original-commit", sha1_to_hex(commit_sha1)); + oidcpy(&state->orig_commit, &commit_oid); + write_state_text(state, "original-commit", oid_to_hex(&commit_oid)); return 0; } @@ -1509,39 +1510,59 @@ static int parse_mail_rebase(struct am_state *state, const char *mail) */ static int run_apply(const struct am_state *state, const char *index_file) { - struct child_process cp = CHILD_PROCESS_INIT; - - cp.git_cmd = 1; - - if (index_file) - argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", index_file); + struct argv_array apply_paths = ARGV_ARRAY_INIT; + struct argv_array apply_opts = ARGV_ARRAY_INIT; + struct apply_state apply_state; + int res, opts_left; + static struct lock_file lock_file; + int force_apply = 0; + int options = 0; + + if (init_apply_state(&apply_state, NULL, &lock_file)) + die("BUG: init_apply_state() failed"); + + argv_array_push(&apply_opts, "apply"); + argv_array_pushv(&apply_opts, state->git_apply_opts.argv); + + opts_left = apply_parse_options(apply_opts.argc, apply_opts.argv, + &apply_state, &force_apply, &options, + NULL); + + if (opts_left != 0) + die("unknown option passed through to git apply"); + + if (index_file) { + apply_state.index_file = index_file; + apply_state.cached = 1; + } else + apply_state.check_index = 1; /* * If we are allowed to fall back on 3-way merge, don't give false * errors during the initial attempt. */ - if (state->threeway && !index_file) { - cp.no_stdout = 1; - cp.no_stderr = 1; - } + if (state->threeway && !index_file) + apply_state.apply_verbosity = verbosity_silent; - argv_array_push(&cp.args, "apply"); + if (check_apply_state(&apply_state, force_apply)) + die("BUG: check_apply_state() failed"); - argv_array_pushv(&cp.args, state->git_apply_opts.argv); + argv_array_push(&apply_paths, am_path(state, "patch")); - if (index_file) - argv_array_push(&cp.args, "--cached"); - else - argv_array_push(&cp.args, "--index"); + res = apply_all_patches(&apply_state, apply_paths.argc, apply_paths.argv, options); - argv_array_push(&cp.args, am_path(state, "patch")); + argv_array_clear(&apply_paths); + argv_array_clear(&apply_opts); + clear_apply_state(&apply_state); - if (run_command(&cp)) - return -1; + if (res) + return res; - /* Reload index as git-apply will have modified it. */ - discard_cache(); - read_cache_from(index_file ? index_file : get_index_file()); + if (index_file) { + /* Reload index as apply_all_patches() will have modified it. */ + discard_cache(); + read_cache_from(index_file); + } return 0; } @@ -1652,9 +1673,8 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa */ static void do_commit(const struct am_state *state) { - unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ], - commit[GIT_SHA1_RAWSZ]; - unsigned char *ptr; + struct object_id tree, parent, commit; + const struct object_id *old_oid; struct commit_list *parents = NULL; const char *reflog_msg, *author; struct strbuf sb = STRBUF_INIT; @@ -1662,14 +1682,14 @@ static void do_commit(const struct am_state *state) if (run_hook_le(NULL, "pre-applypatch", NULL)) exit(1); - if (write_cache_as_tree(tree, 0, NULL)) + if (write_cache_as_tree(tree.hash, 0, NULL)) die(_("git write-tree failed to write a tree")); - if (!get_sha1_commit("HEAD", parent)) { - ptr = parent; - commit_list_insert(lookup_commit(parent), &parents); + if (!get_sha1_commit("HEAD", parent.hash)) { + old_oid = &parent; + commit_list_insert(lookup_commit(parent.hash), &parents); } else { - ptr = NULL; + old_oid = NULL; say(state, stderr, _("applying to an empty history")); } @@ -1681,7 +1701,7 @@ static void do_commit(const struct am_state *state) setenv("GIT_COMMITTER_DATE", state->ignore_date ? "" : state->author_date, 1); - if (commit_tree(state->msg, state->msg_len, tree, parents, commit, + if (commit_tree(state->msg, state->msg_len, tree.hash, parents, commit.hash, author, state->sign_commit)) die(_("failed to write commit object")); @@ -1692,14 +1712,15 @@ static void do_commit(const struct am_state *state) strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg), state->msg); - update_ref(sb.buf, "HEAD", commit, ptr, 0, UPDATE_REFS_DIE_ON_ERR); + update_ref_oid(sb.buf, "HEAD", &commit, old_oid, 0, + UPDATE_REFS_DIE_ON_ERR); if (state->rebasing) { FILE *fp = xfopen(am_path(state, "rewritten"), "a"); - assert(!is_null_sha1(state->orig_commit)); - fprintf(fp, "%s ", sha1_to_hex(state->orig_commit)); - fprintf(fp, "%s\n", sha1_to_hex(commit)); + assert(!is_null_oid(&state->orig_commit)); + fprintf(fp, "%s ", oid_to_hex(&state->orig_commit)); + fprintf(fp, "%s\n", oid_to_hex(&commit)); fclose(fp); } @@ -2020,30 +2041,30 @@ static int merge_tree(struct tree *tree) * Clean the index without touching entries that are not modified between * `head` and `remote`. */ -static int clean_index(const unsigned char *head, const unsigned char *remote) +static int clean_index(const struct object_id *head, const struct object_id *remote) { struct tree *head_tree, *remote_tree, *index_tree; - unsigned char index[GIT_SHA1_RAWSZ]; + struct object_id index; - head_tree = parse_tree_indirect(head); + head_tree = parse_tree_indirect(head->hash); if (!head_tree) - return error(_("Could not parse object '%s'."), sha1_to_hex(head)); + return error(_("Could not parse object '%s'."), oid_to_hex(head)); - remote_tree = parse_tree_indirect(remote); + remote_tree = parse_tree_indirect(remote->hash); if (!remote_tree) - return error(_("Could not parse object '%s'."), sha1_to_hex(remote)); + return error(_("Could not parse object '%s'."), oid_to_hex(remote)); read_cache_unmerged(); if (fast_forward_to(head_tree, head_tree, 1)) return -1; - if (write_cache_as_tree(index, 0, NULL)) + if (write_cache_as_tree(index.hash, 0, NULL)) return -1; - index_tree = parse_tree_indirect(index); + index_tree = parse_tree_indirect(index.hash); if (!index_tree) - return error(_("Could not parse object '%s'."), sha1_to_hex(index)); + return error(_("Could not parse object '%s'."), oid_to_hex(&index)); if (fast_forward_to(index_tree, remote_tree, 0)) return -1; @@ -2071,14 +2092,14 @@ static void am_rerere_clear(void) */ static void am_skip(struct am_state *state) { - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; am_rerere_clear(); - if (get_sha1("HEAD", head)) - hashcpy(head, EMPTY_TREE_SHA1_BIN); + if (get_oid("HEAD", &head)) + hashcpy(head.hash, EMPTY_TREE_SHA1_BIN); - if (clean_index(head, head)) + if (clean_index(&head, &head)) die(_("failed to clean index")); am_next(state); @@ -2096,21 +2117,21 @@ static void am_skip(struct am_state *state) static int safe_to_abort(const struct am_state *state) { struct strbuf sb = STRBUF_INIT; - unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ]; + struct object_id abort_safety, head; if (file_exists(am_path(state, "dirtyindex"))) return 0; if (read_state_file(&sb, state, "abort-safety", 1) > 0) { - if (get_sha1_hex(sb.buf, abort_safety)) + if (get_oid_hex(sb.buf, &abort_safety)) die(_("could not parse %s"), am_path(state, "abort_safety")); } else - hashclr(abort_safety); + oidclr(&abort_safety); - if (get_sha1("HEAD", head)) - hashclr(head); + if (get_oid("HEAD", &head)) + oidclr(&head); - if (!hashcmp(head, abort_safety)) + if (!oidcmp(&head, &abort_safety)) return 1; error(_("You seem to have moved HEAD since the last 'am' failure.\n" @@ -2124,7 +2145,7 @@ static int safe_to_abort(const struct am_state *state) */ static void am_abort(struct am_state *state) { - unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ]; + struct object_id curr_head, orig_head; int has_curr_head, has_orig_head; char *curr_branch; @@ -2135,20 +2156,20 @@ static void am_abort(struct am_state *state) am_rerere_clear(); - curr_branch = resolve_refdup("HEAD", 0, curr_head, NULL); - has_curr_head = !is_null_sha1(curr_head); + curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL); + has_curr_head = !is_null_oid(&curr_head); if (!has_curr_head) - hashcpy(curr_head, EMPTY_TREE_SHA1_BIN); + hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN); - has_orig_head = !get_sha1("ORIG_HEAD", orig_head); + has_orig_head = !get_oid("ORIG_HEAD", &orig_head); if (!has_orig_head) - hashcpy(orig_head, EMPTY_TREE_SHA1_BIN); + hashcpy(orig_head.hash, EMPTY_TREE_SHA1_BIN); - clean_index(curr_head, orig_head); + clean_index(&curr_head, &orig_head); if (has_orig_head) - update_ref("am --abort", "HEAD", orig_head, - has_curr_head ? curr_head : NULL, 0, + update_ref_oid("am --abort", "HEAD", &orig_head, + has_curr_head ? &curr_head : NULL, 0, UPDATE_REFS_DIE_ON_ERR); else if (curr_branch) delete_ref(curr_branch, NULL, REF_NODEREF); @@ -2209,7 +2230,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 }; |