From: Junio C Hamano Date: Wed, 26 Aug 2015 22:45:33 +0000 (-0700) Subject: Merge branch 'pt/am-builtin' X-Git-Tag: v2.6.0-rc0~37 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/74702c382597ce34e7ce884e29d23e1eedb52196?ds=inline;hp=-c Merge branch 'pt/am-builtin' Rewrite "am" in "C". * pt/am-builtin: i18n: am: fix typo in description of -b option --- 74702c382597ce34e7ce884e29d23e1eedb52196 diff --combined builtin/am.c index 5d34696097,473d794fc5..142f8840bd --- a/builtin/am.c +++ b/builtin/am.c @@@ -10,7 -10,6 +10,7 @@@ #include "dir.h" #include "run-command.h" #include "quote.h" +#include "tempfile.h" #include "lockfile.h" #include "cache-tree.h" #include "refs.h" @@@ -99,12 -98,6 +99,12 @@@ enum scissors_type SCISSORS_TRUE /* pass --scissors to git-mailinfo */ }; +enum signoff_type { + SIGNOFF_FALSE = 0, + SIGNOFF_TRUE = 1, + SIGNOFF_EXPLICIT /* --signoff was set on the command-line */ +}; + struct am_state { /* state directory path */ char *dir; @@@ -130,7 -123,7 +130,7 @@@ int interactive; int threeway; int quiet; - int signoff; + int signoff; /* enum signoff_type */ int utf8; int keep; /* enum keep_type */ int message_id; @@@ -1192,18 -1185,6 +1192,18 @@@ static void NORETURN die_user_resolve(c exit(128); } +/** + * Appends signoff to the "msg" field of the am_state. + */ +static void am_append_signoff(struct am_state *state) +{ + struct strbuf sb = STRBUF_INIT; + + strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len); + append_signoff(&sb, 0, 0); + state->msg = strbuf_detach(&sb, &state->msg_len); +} + /** * Parses `mail` using git-mailinfo, extracting its patch and authorship info. * state->msg will be set to the patch message. state->author_name, @@@ -1798,6 -1779,7 +1798,6 @@@ static void am_run(struct am_state *sta if (resume) { validate_resume_state(state); - resume = 0; } else { int skip; @@@ -1859,10 -1841,6 +1859,10 @@@ next: am_next(state); + + if (resume) + am_load(state); + resume = 0; } if (!is_empty_file(am_path(state, "rewritten"))) { @@@ -1917,7 -1895,6 +1917,7 @@@ static void am_resolve(struct am_state next: am_next(state); + am_load(state); am_run(state, 0); } @@@ -1962,49 -1939,16 +1962,49 @@@ static int fast_forward_to(struct tree return 0; } +/** + * Merges a tree into the index. The index's stat info will take precedence + * over the merged tree's. Returns 0 on success, -1 on failure. + */ +static int merge_tree(struct tree *tree) +{ + struct lock_file *lock_file; + struct unpack_trees_options opts; + struct tree_desc t[1]; + + if (parse_tree(tree)) + return -1; + + lock_file = xcalloc(1, sizeof(struct lock_file)); + hold_locked_index(lock_file, 1); + + memset(&opts, 0, sizeof(opts)); + opts.head_idx = 1; + opts.src_index = &the_index; + opts.dst_index = &the_index; + opts.merge = 1; + opts.fn = oneway_merge; + init_tree_desc(&t[0], tree->buffer, tree->size); + + if (unpack_trees(1, t, &opts)) { + rollback_lock_file(lock_file); + return -1; + } + + if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) + die(_("unable to write new index file")); + + return 0; +} + /** * 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) { - struct lock_file *lock_file; struct tree *head_tree, *remote_tree, *index_tree; unsigned char index[GIT_SHA1_RAWSZ]; - struct pathspec pathspec; head_tree = parse_tree_indirect(head); if (!head_tree) @@@ -2029,8 -1973,18 +2029,8 @@@ if (fast_forward_to(index_tree, remote_tree, 0)) return -1; - memset(&pathspec, 0, sizeof(pathspec)); - - lock_file = xcalloc(1, sizeof(struct lock_file)); - hold_locked_index(lock_file, 1); - - if (read_tree(remote_tree, 0, &pathspec)) { - rollback_lock_file(lock_file); + if (merge_tree(remote_tree)) return -1; - } - - if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) - die(_("unable to write new index file")); remove_branch_state(); @@@ -2068,7 -2022,6 +2068,7 @@@ static void am_skip(struct am_state *st die(_("failed to clean index")); am_next(state); + am_load(state); am_run(state, 0); } @@@ -2179,7 -2132,6 +2179,7 @@@ int cmd_am(int argc, const char **argv int keep_cr = -1; int patch_format = PATCH_FORMAT_UNKNOWN; enum resume_mode resume = RESUME_FALSE; + int in_progress; const char * const usage[] = { N_("git am [options] [(|)...]"), @@@ -2191,13 -2143,12 +2191,13 @@@ OPT_BOOL('i', "interactive", &state.interactive, N_("run interactively")), OPT_HIDDEN_BOOL('b', "binary", &binary, - N_("(historical option -- no-op")), + N_("historical option -- no-op")), OPT_BOOL('3', "3way", &state.threeway, N_("allow fall back on 3way merging if needed")), OPT__QUIET(&state.quiet, N_("be quiet")), - OPT_BOOL('s', "signoff", &state.signoff, - N_("add a Signed-off-by line to the commit message")), + OPT_SET_INT('s', "signoff", &state.signoff, + N_("add a Signed-off-by line to the commit message"), + SIGNOFF_EXPLICIT), OPT_BOOL('u', "utf8", &state.utf8, N_("recode into utf8 (default)")), OPT_SET_INT('k', "keep", &state.keep, @@@ -2276,10 -2227,6 +2276,10 @@@ am_state_init(&state, git_path("rebase-apply")); + in_progress = am_in_progress(&state); + if (in_progress) + am_load(&state); + argc = parse_options(argc, argv, prefix, options, usage, 0); if (binary >= 0) @@@ -2292,7 -2239,7 +2292,7 @@@ if (read_index_preload(&the_index, NULL) < 0) die(_("failed to read the index")); - if (am_in_progress(&state)) { + if (in_progress) { /* * Catch user error to feed us patches when there is a session * in progress: @@@ -2311,8 -2258,7 +2311,8 @@@ if (resume == RESUME_FALSE) resume = RESUME_APPLY; - am_load(&state); + if (state.signoff == SIGNOFF_EXPLICIT) + am_append_signoff(&state); } else { struct argv_array paths = ARGV_ARRAY_INIT; int i;