#include "cache.h"
#include "config.h"
#include "builtin.h"
-#include "exec_cmd.h"
+#include "exec-cmd.h"
#include "parse-options.h"
#include "dir.h"
#include "run-command.h"
#include "mailinfo.h"
#include "apply.h"
#include "string-list.h"
+#include "packfile.h"
+#include "repository.h"
/**
* Returns 1 if the file is empty or does not exist, 0 otherwise.
die_errno(_("could not read '%s'"), am_path(state, file));
}
-/**
- * Take a series of KEY='VALUE' lines where VALUE part is
- * sq-quoted, and append <KEY, VALUE> at the end of the string list
- */
-static int parse_key_value_squoted(char *buf, struct string_list *list)
-{
- while (*buf) {
- struct string_list_item *item;
- char *np;
- char *cp = strchr(buf, '=');
- if (!cp)
- return -1;
- np = strchrnul(cp, '\n');
- *cp++ = '\0';
- item = string_list_append(list, buf);
-
- buf = np + (*np == '\n');
- *np = '\0';
- cp = sq_dequote(cp);
- if (!cp)
- return -1;
- item->util = xstrdup(cp);
- }
- return 0;
-}
-
/**
* Reads and parses the state directory's "author-script" file, and sets
* state->author_name, state->author_email and state->author_date accordingly.
* script, and thus if the file differs from what this function expects, it is
* better to bail out than to do something that the user does not expect.
*/
-static int read_author_script(struct am_state *state)
+static int read_am_author_script(struct am_state *state)
{
const char *filename = am_path(state, "author-script");
- struct strbuf buf = STRBUF_INIT;
- struct string_list kv = STRING_LIST_INIT_DUP;
- int retval = -1; /* assume failure */
- int fd;
assert(!state->author_name);
assert(!state->author_email);
assert(!state->author_date);
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- if (errno == ENOENT)
- return 0;
- die_errno(_("could not open '%s' for reading"), filename);
- }
- strbuf_read(&buf, fd, 0);
- close(fd);
- if (parse_key_value_squoted(buf.buf, &kv))
- goto finish;
-
- if (kv.nr != 3 ||
- strcmp(kv.items[0].string, "GIT_AUTHOR_NAME") ||
- strcmp(kv.items[1].string, "GIT_AUTHOR_EMAIL") ||
- strcmp(kv.items[2].string, "GIT_AUTHOR_DATE"))
- goto finish;
- state->author_name = kv.items[0].util;
- state->author_email = kv.items[1].util;
- state->author_date = kv.items[2].util;
- retval = 0;
-finish:
- string_list_clear(&kv, !!retval);
- strbuf_release(&buf);
- return retval;
+ return read_author_script(filename, &state->author_name,
+ &state->author_email, &state->author_date, 1);
}
/**
struct strbuf sb = STRBUF_INIT;
if (read_state_file(&sb, state, "next", 1) < 0)
- die("BUG: state file 'next' does not exist");
+ BUG("state file 'next' does not exist");
state->cur = strtol(sb.buf, NULL, 10);
if (read_state_file(&sb, state, "last", 1) < 0)
- die("BUG: state file 'last' does not exist");
+ BUG("state file 'last' does not exist");
state->last = strtol(sb.buf, NULL, 10);
- if (read_author_script(state) < 0)
+ if (read_am_author_script(state) < 0)
die(_("could not parse author script"));
read_commit_msg(state);
goto done;
}
- strbuf_reset(&l2);
strbuf_getline(&l2, fp);
- strbuf_reset(&l3);
strbuf_getline(&l3, fp);
/*
done:
fclose(fp);
strbuf_release(&l1);
+ strbuf_release(&l2);
+ strbuf_release(&l3);
return ret;
}
{
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf last = STRBUF_INIT;
+ int ret;
cp.git_cmd = 1;
argv_array_push(&cp.args, "mailsplit");
argv_array_push(&cp.args, "--");
argv_array_pushv(&cp.args, paths);
- if (capture_command(&cp, &last, 8))
- return -1;
+ ret = capture_command(&cp, &last, 8);
+ if (ret)
+ goto exit;
state->cur = 1;
state->last = strtol(last.buf, NULL, 10);
- return 0;
+exit:
+ strbuf_release(&last);
+ return ret ? -1 : 0;
}
/**
static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
{
struct strbuf sb = STRBUF_INIT;
+ int rc = 0;
while (!strbuf_getline_lf(&sb, in)) {
const char *str;
errno = 0;
timestamp = parse_timestamp(str, &end, 10);
- if (errno)
- return error(_("invalid timestamp"));
+ if (errno) {
+ rc = error(_("invalid timestamp"));
+ goto exit;
+ }
- if (!skip_prefix(end, " ", &str))
- return error(_("invalid Date line"));
+ if (!skip_prefix(end, " ", &str)) {
+ rc = error(_("invalid Date line"));
+ goto exit;
+ }
errno = 0;
tz = strtol(str, &end, 10);
- if (errno)
- return error(_("invalid timezone offset"));
+ if (errno) {
+ rc = error(_("invalid timezone offset"));
+ goto exit;
+ }
- if (*end)
- return error(_("invalid Date line"));
+ if (*end) {
+ rc = error(_("invalid Date line"));
+ goto exit;
+ }
/*
* mercurial's timezone is in seconds west of UTC,
fwrite(sb.buf, 1, sb.len, out);
strbuf_reset(&sb);
}
-
+exit:
strbuf_release(&sb);
- return 0;
+ return rc;
}
/**
case PATCH_FORMAT_MBOXRD:
return split_mail_mbox(state, paths, keep_cr, 1);
default:
- die("BUG: invalid patch_format");
+ BUG("invalid patch_format");
}
return -1;
}
if (mkdir(state->dir, 0777) < 0 && errno != EEXIST)
die_errno(_("failed to create directory '%s'"), state->dir);
+ delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
if (split_mail(state, patch_format, paths, keep_cr) < 0) {
am_destroy(state);
str = "b";
break;
default:
- die("BUG: invalid value for state->keep");
+ BUG("invalid value for state->keep");
}
write_state_text(state, "keep", str);
str = "t";
break;
default:
- die("BUG: invalid value for state->scissors");
+ BUG("invalid value for state->scissors");
}
write_state_text(state, "scissors", str);
- sq_quote_argv(&sb, state->git_apply_opts.argv, 0);
+ sq_quote_argv(&sb, state->git_apply_opts.argv);
write_state_text(state, "apply-opt", sb.buf);
if (state->rebasing)
if (!get_oid("HEAD", &curr_head)) {
write_state_text(state, "abort-safety", oid_to_hex(&curr_head));
if (!state->rebasing)
- update_ref_oid("am", "ORIG_HEAD", &curr_head, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref("am", "ORIG_HEAD", &curr_head, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
} else {
write_state_text(state, "abort-safety", "");
if (!state->rebasing)
oidclr(&state->orig_commit);
unlink(am_path(state, "original-commit"));
+ delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
if (!get_oid("HEAD", &head))
write_state_text(state, "abort-safety", oid_to_hex(&head));
*/
static void refresh_and_write_cache(void)
{
- struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+ struct lock_file lock_file = LOCK_INIT;
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
refresh_cache(REFRESH_QUIET);
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write index file"));
}
-/**
- * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn
- * branch, returns 1 if there are entries in the index, 0 otherwise. If an
- * strbuf is provided, the space-separated list of files that differ will be
- * appended to it.
- */
-static int index_has_changes(struct strbuf *sb)
-{
- struct object_id head;
- int i;
-
- 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);
- diffcore_std(&opt);
- for (i = 0; sb && i < diff_queued_diff.nr; i++) {
- if (i)
- strbuf_addch(sb, ' ');
- strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);
- }
- diff_flush(&opt);
- return DIFF_OPT_TST(&opt, HAS_CHANGES) != 0;
- } else {
- for (i = 0; sb && i < active_nr; i++) {
- if (i)
- strbuf_addch(sb, ' ');
- strbuf_addstr(sb, active_cache[i]->name);
- }
- return !!active_nr;
- }
-}
-
/**
* Dies with a user-friendly message on how to proceed after resolving the
* problem. This message can be overridden with state->resolvemsg.
mi.keep_non_patch_brackets_in_subject = 1;
break;
default:
- die("BUG: invalid value for state->keep");
+ BUG("invalid value for state->keep");
}
if (state->message_id)
mi.use_scissors = 1;
break;
default:
- die("BUG: invalid value for state->scissors");
+ BUG("invalid value for state->scissors");
}
mi.input = xfopen(mail, "r");
fclose(mi.input);
fclose(mi.output);
+ if (mi.format_flowed)
+ warning(_("Patch sent with format=flowed; "
+ "space at the end of lines might be lost."));
+
/* Extract message and author information */
fp = xfopen(am_path(state, "info"), "r");
while (!strbuf_getline_lf(&sb, fp)) {
FILE *fp;
fp = xfopen(am_path(state, "patch"), "w");
- init_revisions(&rev_info, NULL);
+ repo_init_revisions(the_repository, &rev_info, NULL);
rev_info.diff = 1;
rev_info.abbrev = 0;
rev_info.disable_stdin = 1;
rev_info.show_root_diff = 1;
rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
rev_info.no_commit_id = 1;
- DIFF_OPT_SET(&rev_info.diffopt, BINARY);
- DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);
+ rev_info.diffopt.flags.binary = 1;
+ rev_info.diffopt.flags.full_index = 1;
rev_info.diffopt.use_color = 0;
rev_info.diffopt.file = fp;
rev_info.diffopt.close_file = 1;
struct rev_info rev_info;
FILE *fp;
- if (!get_sha1_tree("HEAD", head.hash))
- tree = lookup_tree(&head);
+ if (!get_oid_tree("HEAD", &head))
+ tree = lookup_tree(the_repository, &head);
else
- tree = lookup_tree(&empty_tree_oid);
+ tree = lookup_tree(the_repository,
+ the_repository->hash_algo->empty_tree);
fp = xfopen(am_path(state, "patch"), "w");
- init_revisions(&rev_info, NULL);
+ repo_init_revisions(the_repository, &rev_info, NULL);
rev_info.diff = 1;
rev_info.disable_stdin = 1;
rev_info.no_commit_id = 1;
oidcpy(&state->orig_commit, &commit_oid);
write_state_text(state, "original-commit", oid_to_hex(&commit_oid));
+ update_ref("am", "REBASE_HEAD", &commit_oid,
+ NULL, REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
return 0;
}
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");
+ if (init_apply_state(&apply_state, the_repository, NULL))
+ BUG("init_apply_state() failed");
argv_array_push(&apply_opts, "apply");
argv_array_pushv(&apply_opts, state->git_apply_opts.argv);
apply_state.apply_verbosity = verbosity_silent;
if (check_apply_state(&apply_state, force_apply))
- die("BUG: check_apply_state() failed");
+ BUG("check_apply_state() failed");
argv_array_push(&apply_paths, am_path(state, "patch"));
char *their_tree_name;
if (get_oid("HEAD", &our_tree) < 0)
- hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN);
+ oidcpy(&our_tree, the_hash_algo->empty_tree);
if (build_fake_ancestor(state, index_path))
return error("could not build fake ancestor");
discard_cache();
read_cache_from(index_path);
- if (write_index_as_tree(orig_tree.hash, &the_index, index_path, 0, NULL))
+ if (write_index_as_tree(&orig_tree, &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..."));
struct rev_info rev_info;
const char *diff_filter_str = "--diff-filter=AM";
- init_revisions(&rev_info, NULL);
+ 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);
add_pending_oid(&rev_info, "HEAD", &our_tree, 0);
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.hash, &the_index, index_path, 0, NULL))
+ if (write_index_as_tree(&their_tree, &the_index, index_path, 0, NULL))
return error("could not write tree");
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
o.branch1 = "HEAD";
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
o.branch2 = their_tree_name;
+ o.detect_directory_renames = 0;
if (state->quiet)
o.verbosity = 0;
if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) {
- rerere(state->allow_rerere_autoupdate);
+ repo_rerere(the_repository, state->allow_rerere_autoupdate);
free(their_tree_name);
return error(_("Failed to merge in the changes."));
}
if (run_hook_le(NULL, "pre-applypatch", NULL))
exit(1);
- if (write_cache_as_tree(tree.hash, 0, NULL))
+ if (write_cache_as_tree(&tree, 0, NULL))
die(_("git write-tree failed to write a tree"));
- if (!get_sha1_commit("HEAD", parent.hash)) {
+ if (!get_oid_commit("HEAD", &parent)) {
old_oid = &parent;
- commit_list_insert(lookup_commit(&parent), &parents);
+ commit_list_insert(lookup_commit(the_repository, &parent),
+ &parents);
} else {
old_oid = NULL;
say(state, stderr, _("applying to an empty history"));
setenv("GIT_COMMITTER_DATE",
state->ignore_date ? "" : state->author_date, 1);
- if (commit_tree(state->msg, state->msg_len, tree.hash, parents, commit.hash,
- author, state->sign_commit))
+ if (commit_tree(state->msg, state->msg_len, &tree, parents, &commit,
+ author, state->sign_commit))
die(_("failed to write commit object"));
reflog_msg = getenv("GIT_REFLOG_ACTION");
strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg),
state->msg);
- update_ref_oid(sb.buf, "HEAD", &commit, old_oid, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref(sb.buf, "HEAD", &commit, old_oid, 0,
+ UPDATE_REFS_DIE_ON_ERR);
if (state->rebasing) {
FILE *fp = xfopen(am_path(state, "rewritten"), "a");
refresh_and_write_cache();
- if (index_has_changes(&sb)) {
+ if (index_has_changes(&the_index, NULL, &sb)) {
write_state_bool(state, "dirtyindex", 1);
die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf);
}
* Applying the patch to an earlier tree and merging
* the result may have produced the same tree as ours.
*/
- if (!apply_status && !index_has_changes(NULL)) {
+ if (!apply_status &&
+ !index_has_changes(&the_index, NULL, NULL)) {
say(state, stdout, _("No changes -- Patch already applied."));
goto next;
}
}
if (apply_status) {
- int advice_amworkdir = 1;
-
printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
linelen(state->msg), state->msg);
- git_config_get_bool("advice.amworkdir", &advice_amworkdir);
-
if (advice_amworkdir)
- printf_ln(_("The copy of the patch that failed is found in: %s"),
- am_path(state, "patch"));
+ advise(_("Use 'git am --show-current-patch' to see the failed patch"));
die_user_resolve(state);
}
*/
if (!state->rebasing) {
am_destroy(state);
- close_all_packs();
+ close_all_packs(the_repository->objects);
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
}
}
say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
- if (!index_has_changes(NULL)) {
+ if (!index_has_changes(&the_index, 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."));
goto next;
}
- rerere(0);
+ repo_rerere(the_repository, 0);
do_commit(state);
*/
static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
{
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
struct unpack_trees_options opts;
struct tree_desc t[2];
if (parse_tree(head) || parse_tree(remote))
return -1;
- lock_file = xcalloc(1, sizeof(struct lock_file));
- hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
refresh_cache(REFRESH_QUIET);
init_tree_desc(&t[1], remote->buffer, remote->size);
if (unpack_trees(2, t, &opts)) {
- rollback_lock_file(lock_file);
+ rollback_lock_file(&lock_file);
return -1;
}
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
*/
static int merge_tree(struct tree *tree)
{
- struct lock_file *lock_file;
+ struct lock_file lock_file = LOCK_INIT;
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, LOCK_DIE_ON_ERROR);
+ hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
init_tree_desc(&t[0], tree->buffer, tree->size);
if (unpack_trees(1, t, &opts)) {
- rollback_lock_file(lock_file);
+ rollback_lock_file(&lock_file);
return -1;
}
- if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
if (fast_forward_to(head_tree, head_tree, 1))
return -1;
- if (write_cache_as_tree(index.hash, 0, NULL))
+ if (write_cache_as_tree(&index, 0, NULL))
return -1;
index_tree = parse_tree_indirect(&index);
am_rerere_clear();
if (get_oid("HEAD", &head))
- hashcpy(head.hash, EMPTY_TREE_SHA1_BIN);
+ oidcpy(&head, the_hash_algo->empty_tree);
if (clean_index(&head, &head))
die(_("failed to clean index"));
die(_("could not parse %s"), am_path(state, "abort-safety"));
} else
oidclr(&abort_safety);
+ strbuf_release(&sb);
if (get_oid("HEAD", &head))
oidclr(&head);
- if (!oidcmp(&head, &abort_safety))
+ if (oideq(&head, &abort_safety))
return 1;
warning(_("You seem to have moved HEAD since the last 'am' failure.\n"
am_rerere_clear();
- curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL);
+ curr_branch = resolve_refdup("HEAD", 0, &curr_head, NULL);
has_curr_head = curr_branch && !is_null_oid(&curr_head);
if (!has_curr_head)
- hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN);
+ oidcpy(&curr_head, the_hash_algo->empty_tree);
has_orig_head = !get_oid("ORIG_HEAD", &orig_head);
if (!has_orig_head)
- hashcpy(orig_head.hash, EMPTY_TREE_SHA1_BIN);
+ oidcpy(&orig_head, the_hash_algo->empty_tree);
clean_index(&curr_head, &orig_head);
if (has_orig_head)
- update_ref_oid("am --abort", "HEAD", &orig_head,
- has_curr_head ? &curr_head : NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ update_ref("am --abort", "HEAD", &orig_head,
+ has_curr_head ? &curr_head : NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
else if (curr_branch)
- delete_ref(NULL, curr_branch, NULL, REF_NODEREF);
+ delete_ref(NULL, curr_branch, NULL, REF_NO_DEREF);
free(curr_branch);
am_destroy(state);
}
+static int show_patch(struct am_state *state)
+{
+ struct strbuf sb = STRBUF_INIT;
+ const char *patch_path;
+ int len;
+
+ if (!is_null_oid(&state->orig_commit)) {
+ const char *av[4] = { "show", NULL, "--", NULL };
+ char *new_oid_str;
+ int ret;
+
+ av[1] = new_oid_str = xstrdup(oid_to_hex(&state->orig_commit));
+ ret = run_command_v_opt(av, RUN_GIT_CMD);
+ free(new_oid_str);
+ return ret;
+ }
+
+ patch_path = am_path(state, msgnum(state));
+ len = strbuf_read_file(&sb, patch_path, 0);
+ if (len < 0)
+ die_errno(_("failed to read '%s'"), patch_path);
+
+ setup_pager();
+ write_in_full(1, sb.buf, sb.len);
+ strbuf_release(&sb);
+ return 0;
+}
+
/**
* parse_options() callback that validates and sets opt->value to the
* PATCH_FORMAT_* enum value corresponding to `arg`.
{
int *opt_value = opt->value;
- if (!strcmp(arg, "mbox"))
+ if (unset)
+ *opt_value = PATCH_FORMAT_UNKNOWN;
+ else if (!strcmp(arg, "mbox"))
*opt_value = PATCH_FORMAT_MBOX;
else if (!strcmp(arg, "stgit"))
*opt_value = PATCH_FORMAT_STGIT;
RESUME_APPLY,
RESUME_RESOLVED,
RESUME_SKIP,
- RESUME_ABORT
+ RESUME_ABORT,
+ RESUME_QUIT,
+ RESUME_SHOW_PATCH
};
static int git_am_config(const char *k, const char *v, void *cb)
int patch_format = PATCH_FORMAT_UNKNOWN;
enum resume_mode resume = RESUME_FALSE;
int in_progress;
+ int ret = 0;
const char * const usage[] = {
N_("git am [<options>] [(<mbox> | <Maildir>)...]"),
N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),
OPT_BOOL('m', "message-id", &state.message_id,
N_("pass -m flag to git-mailinfo")),
- { OPTION_SET_INT, 0, "keep-cr", &keep_cr, NULL,
- N_("pass --keep-cr flag to git-mailsplit for mbox format"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1},
- { OPTION_SET_INT, 0, "no-keep-cr", &keep_cr, NULL,
- N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
+ OPT_SET_INT_F(0, "keep-cr", &keep_cr,
+ N_("pass --keep-cr flag to git-mailsplit for mbox format"),
+ 1, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "no-keep-cr", &keep_cr,
+ N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),
+ 0, PARSE_OPT_NONEG),
OPT_BOOL('c', "scissors", &state.scissors,
N_("strip everything before a scissors line")),
OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
OPT_CMDMODE(0, "abort", &resume,
N_("restore the original branch and abort the patching operation."),
RESUME_ABORT),
+ OPT_CMDMODE(0, "quit", &resume,
+ N_("abort the patching operation but keep HEAD where it is."),
+ RESUME_QUIT),
+ OPT_CMDMODE(0, "show-current-patch", &resume,
+ N_("show the patch being applied."),
+ RESUME_SHOW_PATCH),
OPT_BOOL(0, "committer-date-is-author-date",
&state.committer_date_is_author_date,
N_("lie about committer date")),
/* Ensure a valid committer ident can be constructed */
git_committer_info(IDENT_STRICT);
- if (read_index_preload(&the_index, NULL) < 0)
+ if (read_index_preload(&the_index, NULL, 0) < 0)
die(_("failed to read the index"));
if (in_progress) {
* stray directories.
*/
if (file_exists(state.dir) && !state.rebasing) {
- if (resume == RESUME_ABORT) {
+ if (resume == RESUME_ABORT || resume == RESUME_QUIT) {
am_destroy(&state);
am_state_release(&state);
return 0;
case RESUME_ABORT:
am_abort(&state);
break;
+ case RESUME_QUIT:
+ am_rerere_clear();
+ am_destroy(&state);
+ break;
+ case RESUME_SHOW_PATCH:
+ ret = show_patch(&state);
+ break;
default:
- die("BUG: invalid resume value");
+ BUG("invalid resume value");
}
am_state_release(&state);
- return 0;
+ return ret;
}