diff options
Diffstat (limited to 'builtin/am.c')
-rw-r--r-- | builtin/am.c | 88 |
1 files changed, 45 insertions, 43 deletions
diff --git a/builtin/am.c b/builtin/am.c index 8f27f3375b..78389d08b6 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -3,6 +3,7 @@ * * Based on git-am.sh by Junio C Hamano. */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "builtin.h" @@ -35,22 +36,6 @@ #include "repository.h" /** - * Returns 1 if the file is empty or does not exist, 0 otherwise. - */ -static int is_empty_file(const char *filename) -{ - struct stat st; - - if (stat(filename, &st) < 0) { - if (errno == ENOENT) - return 1; - die_errno(_("could not stat %s"), filename); - } - - return !st.st_size; -} - -/** * Returns the length of the first line of msg. */ static int linelen(const char *msg) @@ -468,6 +453,7 @@ static int run_post_rewrite_hook(const struct am_state *state) cp.in = xopen(am_path(state, "rewritten"), O_RDONLY); cp.stdout_to_stderr = 1; + cp.trace2_hook_name = "post-rewrite"; ret = run_command(&cp); @@ -500,23 +486,24 @@ static int copy_notes_for_rebase(const struct am_state *state) while (!strbuf_getline_lf(&sb, fp)) { struct object_id from_obj, to_obj; + const char *p; - if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) { + if (sb.len != the_hash_algo->hexsz * 2 + 1) { ret = error(invalid_line, sb.buf); goto finish; } - if (get_oid_hex(sb.buf, &from_obj)) { + if (parse_oid_hex(sb.buf, &from_obj, &p)) { ret = error(invalid_line, sb.buf); goto finish; } - if (sb.buf[GIT_SHA1_HEXSZ] != ' ') { + if (*p != ' ') { ret = error(invalid_line, sb.buf); goto finish; } - if (get_oid_hex(sb.buf + GIT_SHA1_HEXSZ + 1, &to_obj)) { + if (get_oid_hex(p + 1, &to_obj)) { ret = error(invalid_line, sb.buf); goto finish; } @@ -527,7 +514,7 @@ static int copy_notes_for_rebase(const struct am_state *state) } finish: - finish_copy_notes_for_rewrite(c, msg); + finish_copy_notes_for_rewrite(the_repository, c, msg); fclose(fp); strbuf_release(&sb); return ret; @@ -1220,7 +1207,7 @@ static int parse_mail(struct am_state *state, const char *mail) goto finish; } - if (is_empty_file(am_path(state, "patch"))) { + if (is_empty_or_missing_file(am_path(state, "patch"))) { printf_ln(_("Patch is empty.")); die_user_resolve(state); } @@ -1352,9 +1339,10 @@ static void write_index_patch(const struct am_state *state) struct rev_info rev_info; FILE *fp; - if (!get_oid_tree("HEAD", &head)) - tree = lookup_tree(the_repository, &head); - else + if (!get_oid("HEAD", &head)) { + struct commit *commit = lookup_commit_or_die(&head, "HEAD"); + tree = get_commit_tree(commit); + } else tree = lookup_tree(the_repository, the_repository->hash_algo->empty_tree); @@ -1515,11 +1503,11 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa * review them with extra care to spot mismerges. */ struct rev_info rev_info; - const char *diff_filter_str = "--diff-filter=AM"; repo_init_revisions(the_repository, &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); + rev_info.diffopt.filter |= diff_filter_bit('A'); + rev_info.diffopt.filter |= diff_filter_bit('M'); add_pending_oid(&rev_info, "HEAD", &our_tree, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); @@ -1545,7 +1533,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa * changes. */ - init_merge_options(&o); + init_merge_options(&o, the_repository); o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); @@ -1594,6 +1582,7 @@ static void do_commit(const struct am_state *state) } author = fmt_ident(state->author_name, state->author_email, + WANT_AUTHOR_IDENT, state->ignore_date ? NULL : state->author_date, IDENT_STRICT); @@ -1655,11 +1644,8 @@ static int do_interactive(struct am_state *state) { assert(state->msg); - if (!isatty(0)) - die(_("cannot be interactive without stdin connected to a terminal.")); - for (;;) { - const char *reply; + char reply[64]; puts(_("Commit Body is:")); puts("--------------------------"); @@ -1671,11 +1657,11 @@ static int do_interactive(struct am_state *state) * in your translation. The program will only accept English * input at this point. */ - reply = git_prompt(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "), PROMPT_ECHO); + printf(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: ")); + if (!fgets(reply, sizeof(reply), stdin)) + die("unable to read from stdin; aborting"); - if (!reply) { - continue; - } else if (*reply == 'y' || *reply == 'Y') { + if (*reply == 'y' || *reply == 'Y') { return 0; } else if (*reply == 'a' || *reply == 'A') { state->interactive = 0; @@ -1719,7 +1705,7 @@ static void am_run(struct am_state *state, int resume) refresh_and_write_cache(); - if (index_has_changes(&the_index, NULL, &sb)) { + if (repo_index_has_changes(the_repository, NULL, &sb)) { write_state_bool(state, "dirtyindex", 1); die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf); } @@ -1777,7 +1763,7 @@ static void am_run(struct am_state *state, int resume) * the result may have produced the same tree as ours. */ if (!apply_status && - !index_has_changes(&the_index, NULL, NULL)) { + !repo_index_has_changes(the_repository, NULL, NULL)) { say(state, stdout, _("No changes -- Patch already applied.")); goto next; } @@ -1803,7 +1789,7 @@ next: resume = 0; } - if (!is_empty_file(am_path(state, "rewritten"))) { + if (!is_empty_or_missing_file(am_path(state, "rewritten"))) { assert(state->rebasing); copy_notes_for_rebase(state); run_post_rewrite_hook(state); @@ -1831,7 +1817,7 @@ static void am_resolve(struct am_state *state) say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg); - if (!index_has_changes(&the_index, NULL, NULL)) { + if (!repo_index_has_changes(the_repository, NULL, NULL)) { printf_ln(_("No changes - did you forget to use 'git add'?\n" "If there is nothing left to stage, chances are that something else\n" "already introduced the same changes; you might want to skip this patch.")); @@ -1970,7 +1956,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem if (merge_tree(remote_tree)) return -1; - remove_branch_state(); + remove_branch_state(the_repository); return 0; } @@ -1981,7 +1967,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem static void am_rerere_clear(void) { struct string_list merge_rr = STRING_LIST_INIT_DUP; - rerere_clear(&merge_rr); + rerere_clear(the_repository, &merge_rr); string_list_clear(&merge_rr, 1); } @@ -2000,6 +1986,15 @@ static void am_skip(struct am_state *state) if (clean_index(&head, &head)) die(_("failed to clean index")); + if (state->rebasing) { + FILE *fp = xfopen(am_path(state, "rewritten"), "a"); + + assert(!is_null_oid(&state->orig_commit)); + fprintf(fp, "%s ", oid_to_hex(&state->orig_commit)); + fprintf(fp, "%s\n", oid_to_hex(&head)); + fclose(fp); + } + am_next(state); am_load(state); am_run(state, 0); @@ -2125,6 +2120,10 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int *opt_value = PATCH_FORMAT_HG; else if (!strcmp(arg, "mboxrd")) *opt_value = PATCH_FORMAT_MBOXRD; + /* + * Please update $__git_patchformat in git-completion.bash + * when you add new options + */ else return error(_("Invalid value for --patch-format: %s"), arg); return 0; @@ -2278,7 +2277,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) /* Ensure a valid committer ident can be constructed */ git_committer_info(IDENT_STRICT); - if (read_index_preload(&the_index, NULL, 0) < 0) + if (repo_read_index_preload(the_repository, NULL, 0) < 0) die(_("failed to read the index")); if (in_progress) { @@ -2333,6 +2332,9 @@ int cmd_am(int argc, const char **argv, const char *prefix) argv_array_push(&paths, mkpath("%s/%s", prefix, argv[i])); } + if (state.interactive && !paths.argc) + die(_("interactive mode requires patches on the command line")); + am_setup(&state, patch_format, paths.argv, keep_cr); argv_array_clear(&paths); |