#include "xdiff-interface.h"
#include "ll-merge.h"
#include "rerere.h"
-
-enum apply_ws_error_action {
- nowarn_ws_error,
- warn_on_ws_error,
- die_on_ws_error,
- correct_ws_error
-};
-
-
-enum apply_ws_ignore {
- ignore_ws_none,
- ignore_ws_change
-};
-
-/*
- * We need to keep track of how symlinks in the preimage are
- * manipulated by the patches. A patch to add a/b/c where a/b
- * is a symlink should not be allowed to affect the directory
- * the symlink points at, but if the same patch removes a/b,
- * it is perfectly fine, as the patch removes a/b to make room
- * to create a directory a/b so that a/b/c can be created.
- *
- * See also "struct string_list symlink_changes" in "struct
- * apply_state".
- */
-#define APPLY_SYMLINK_GOES_AWAY 01
-#define APPLY_SYMLINK_IN_RESULT 02
-
-struct apply_state {
- const char *prefix;
- int prefix_length;
-
- /* These are lock_file related */
- struct lock_file *lock_file;
- int newfd;
-
- /* These control what gets looked at and modified */
- int apply; /* this is not a dry-run */
- int cached; /* apply to the index only */
- int check; /* preimage must match working tree, don't actually apply */
- int check_index; /* preimage must match the indexed version */
- int update_index; /* check_index && apply */
-
- /* These control cosmetic aspect of the output */
- int diffstat; /* just show a diffstat, and don't actually apply */
- int numstat; /* just show a numeric diffstat, and don't actually apply */
- int summary; /* just report creation, deletion, etc, and don't actually apply */
-
- /* These boolean parameters control how the apply is done */
- int allow_overlap;
- int apply_in_reverse;
- int apply_with_reject;
- int apply_verbosely;
- int no_add;
- int threeway;
- int unidiff_zero;
- int unsafe_paths;
-
- /* Other non boolean parameters */
- const char *fake_ancestor;
- const char *patch_input_file;
- int line_termination;
- struct strbuf root;
- int p_value;
- int p_value_known;
- unsigned int p_context;
-
- /* Exclude and include path parameters */
- struct string_list limit_by_name;
- int has_include;
-
- /* Various "current state" */
- int linenr; /* current line number */
- struct string_list symlink_changes; /* we have to track symlinks */
-
- /*
- * For "diff-stat" like behaviour, we keep track of the biggest change
- * we've seen, and the longest filename. That allows us to do simple
- * scaling.
- */
- int max_change;
- int max_len;
-
- /*
- * Records filenames that have been touched, in order to handle
- * the case where more than one patches touch the same file.
- */
- struct string_list fn_table;
-
- /* These control whitespace errors */
- enum apply_ws_error_action ws_error_action;
- enum apply_ws_ignore ws_ignore_action;
- const char *whitespace_option;
- int whitespace_error;
- int squelch_whitespace_errors;
- int applied_after_fixing_ws;
-};
+#include "apply.h"
static const char * const apply_usage[] = {
N_("git apply [<options>] [<patch>...]"),
NULL
};
-static void parse_whitespace_option(struct apply_state *state, const char *option)
-{
- if (!option) {
- state->ws_error_action = warn_on_ws_error;
- return;
- }
- if (!strcmp(option, "warn")) {
- state->ws_error_action = warn_on_ws_error;
- return;
- }
- if (!strcmp(option, "nowarn")) {
- state->ws_error_action = nowarn_ws_error;
- return;
- }
- if (!strcmp(option, "error")) {
- state->ws_error_action = die_on_ws_error;
- return;
- }
- if (!strcmp(option, "error-all")) {
- state->ws_error_action = die_on_ws_error;
- state->squelch_whitespace_errors = 0;
- return;
- }
- if (!strcmp(option, "strip") || !strcmp(option, "fix")) {
- state->ws_error_action = correct_ws_error;
- return;
- }
- die(_("unrecognized whitespace option '%s'"), option);
-}
-
-static void parse_ignorewhitespace_option(struct apply_state *state,
- const char *option)
-{
- if (!option || !strcmp(option, "no") ||
- !strcmp(option, "false") || !strcmp(option, "never") ||
- !strcmp(option, "none")) {
- state->ws_ignore_action = ignore_ws_none;
- return;
- }
- if (!strcmp(option, "change")) {
- state->ws_ignore_action = ignore_ws_change;
- return;
- }
- die(_("unrecognized whitespace ignore option '%s'"), option);
-}
-
static void set_default_whitespace_mode(struct apply_state *state)
{
if (!state->whitespace_option && !apply_default_whitespace)
#define SLOP (16)
-static void read_patch_file(struct strbuf *sb, int fd)
+static int read_patch_file(struct strbuf *sb, int fd)
{
if (strbuf_read(sb, fd, 0) < 0)
- die_errno("git apply: failed to read");
+ return error_errno("git apply: failed to read");
/*
* Make sure that we have some slop in the buffer
*/
strbuf_grow(sb, SLOP);
memset(sb->buf + sb->len, 0, SLOP);
+ return 0;
}
static unsigned long linelen(const char *buffer, unsigned long size)
* files, we can happily check the index for a match, but for creating a
* new file we should try to match whatever "patch" does. I have no idea.
*/
-static void parse_traditional_patch(struct apply_state *state,
- const char *first,
- const char *second,
- struct patch *patch)
+static int parse_traditional_patch(struct apply_state *state,
+ const char *first,
+ const char *second,
+ struct patch *patch)
{
char *name;
}
}
if (!name)
- die(_("unable to find filename in patch at line %d"), state->linenr);
+ return error(_("unable to find filename in patch at line %d"), state->linenr);
+
+ return 0;
}
static int gitdiff_hdrend(struct apply_state *state,
const char *line,
struct patch *patch)
{
- return -1;
+ return 1;
}
/*
#define DIFF_OLD_NAME 0
#define DIFF_NEW_NAME 1
-static void gitdiff_verify_name(struct apply_state *state,
- const char *line,
- int isnull,
- char **name,
- int side)
+static int gitdiff_verify_name(struct apply_state *state,
+ const char *line,
+ int isnull,
+ char **name,
+ int side)
{
if (!*name && !isnull) {
*name = find_name(state, line, NULL, state->p_value, TERM_TAB);
- return;
+ return 0;
}
if (*name) {
int len = strlen(*name);
char *another;
if (isnull)
- die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"),
- *name, state->linenr);
+ return error(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"),
+ *name, state->linenr);
another = find_name(state, line, NULL, state->p_value, TERM_TAB);
- if (!another || memcmp(another, *name, len + 1))
- die((side == DIFF_NEW_NAME) ?
+ if (!another || memcmp(another, *name, len + 1)) {
+ free(another);
+ return error((side == DIFF_NEW_NAME) ?
_("git apply: bad git-diff - inconsistent new filename on line %d") :
_("git apply: bad git-diff - inconsistent old filename on line %d"), state->linenr);
+ }
free(another);
} else {
/* expect "/dev/null" */
if (memcmp("/dev/null", line, 9) || line[9] != '\n')
- die(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
+ return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr);
}
+
+ return 0;
}
static int gitdiff_oldname(struct apply_state *state,
const char *line,
struct patch *patch)
{
- gitdiff_verify_name(state, line,
- patch->is_new, &patch->old_name,
- DIFF_OLD_NAME);
- return 0;
+ return gitdiff_verify_name(state, line,
+ patch->is_new, &patch->old_name,
+ DIFF_OLD_NAME);
}
static int gitdiff_newname(struct apply_state *state,
const char *line,
struct patch *patch)
{
- gitdiff_verify_name(state, line,
- patch->is_delete, &patch->new_name,
- DIFF_NEW_NAME);
- return 0;
+ return gitdiff_verify_name(state, line,
+ patch->is_delete, &patch->new_name,
+ DIFF_NEW_NAME);
}
static int gitdiff_oldmode(struct apply_state *state,
const char *line,
struct patch *patch)
{
- return -1;
+ return 1;
}
/*
for (i = 0; i < ARRAY_SIZE(optable); i++) {
const struct opentry *p = optable + i;
int oplen = strlen(p->str);
+ int res;
if (len < oplen || memcmp(p->str, line, oplen))
continue;
- if (p->fn(state, line + oplen, patch) < 0)
+ res = p->fn(state, line + oplen, patch);
+ if (res < 0)
+ return -1;
+ if (res > 0)
return offset;
break;
}
return offset;
}
+/*
+ * Find file diff header
+ *
+ * Returns:
+ * -1 if no header was found
+ * -128 in case of error
+ * the size of the header in bytes (called "offset") otherwise
+ */
static int find_header(struct apply_state *state,
const char *line,
unsigned long size,
struct fragment dummy;
if (parse_fragment_header(line, len, &dummy) < 0)
continue;
- die(_("patch fragment without header at line %d: %.*s"),
- state->linenr, (int)len-1, line);
+ error(_("patch fragment without header at line %d: %.*s"),
+ state->linenr, (int)len-1, line);
+ return -128;
}
if (size < len + 6)
*/
if (!memcmp("diff --git ", line, 11)) {
int git_hdr_len = parse_git_header(state, line, len, size, patch);
+ if (git_hdr_len < 0)
+ return -128;
if (git_hdr_len <= len)
continue;
if (!patch->old_name && !patch->new_name) {
- if (!patch->def_name)
- die(Q_("git diff header lacks filename information when removing "
- "%d leading pathname component (line %d)",
- "git diff header lacks filename information when removing "
- "%d leading pathname components (line %d)",
- state->p_value),
- state->p_value, state->linenr);
+ if (!patch->def_name) {
+ error(Q_("git diff header lacks filename information when removing "
+ "%d leading pathname component (line %d)",
+ "git diff header lacks filename information when removing "
+ "%d leading pathname components (line %d)",
+ state->p_value),
+ state->p_value, state->linenr);
+ return -128;
+ }
patch->old_name = xstrdup(patch->def_name);
patch->new_name = xstrdup(patch->def_name);
}
- if (!patch->is_delete && !patch->new_name)
- die("git diff header lacks filename information "
- "(line %d)", state->linenr);
+ if (!patch->is_delete && !patch->new_name) {
+ error("git diff header lacks filename information "
+ "(line %d)", state->linenr);
+ return -128;
+ }
patch->is_toplevel_relative = 1;
*hdrsize = git_hdr_len;
return offset;
continue;
/* Ok, we'll consider it a patch */
- parse_traditional_patch(state, line, line+len, patch);
+ if (parse_traditional_patch(state, line, line+len, patch))
+ return -128;
*hdrsize = len + nextlen;
state->linenr += 2;
return offset;
*
* The (fragment->patch, fragment->size) pair points into the memory given
* by the caller, not a copy, when we return.
+ *
+ * Returns:
+ * -1 in case of error,
+ * the number of bytes in the patch otherwise.
*/
static int parse_single_patch(struct apply_state *state,
const char *line,
fragment = xcalloc(1, sizeof(*fragment));
fragment->linenr = state->linenr;
len = parse_fragment(state, line, size, patch, fragment);
- if (len <= 0)
- die(_("corrupt patch at line %d"), state->linenr);
+ if (len <= 0) {
+ free(fragment);
+ return error(_("corrupt patch at line %d"), state->linenr);
+ }
fragment->patch = line;
fragment->size = len;
oldlines += fragment->oldlines;
patch->is_delete = 0;
if (0 < patch->is_new && oldlines)
- die(_("new file %s depends on old contents"), patch->new_name);
+ return error(_("new file %s depends on old contents"), patch->new_name);
if (0 < patch->is_delete && newlines)
- die(_("deleted file %s still has contents"), patch->old_name);
+ return error(_("deleted file %s still has contents"), patch->old_name);
if (!patch->is_delete && !newlines && context)
fprintf_ln(stderr,
_("** warning: "
return !state->has_include;
}
-
/*
* Read the patch text in "buffer" that extends for "size" bytes; stop
* reading after seeing a single patch (i.e. changes to a single file).
* Create fragments (i.e. patch hunks) and hang them to the given patch.
- * Return the number of bytes consumed, so that the caller can call us
- * again for the next patch.
+ *
+ * Returns:
+ * -1 if no header was found or parse_binary() failed,
+ * -128 on another error,
+ * the number of bytes consumed otherwise,
+ * so that the caller can call us again for the next patch.
*/
static int parse_chunk(struct apply_state *state, char *buffer, unsigned long size, struct patch *patch)
{
size - offset - hdrsize,
patch);
+ if (patchsize < 0)
+ return -128;
+
if (!patchsize) {
static const char git_binary[] = "GIT binary patch\n";
int hd = hdrsize + offset;
* empty to us here.
*/
if ((state->apply || state->check) &&
- (!patch->is_binary && !metadata_changes(patch)))
- die(_("patch with only garbage at line %d"), state->linenr);
+ (!patch->is_binary && !metadata_changes(patch))) {
+ error(_("patch with only garbage at line %d"), state->linenr);
+ return -128;
+ }
}
return offset + hdrsize + patchsize;
return ret;
}
-static void die_on_unsafe_path(struct patch *patch)
+static int check_unsafe_path(struct patch *patch)
{
const char *old_name = NULL;
const char *new_name = NULL;
new_name = patch->new_name;
if (old_name && !verify_path(old_name))
- die(_("invalid path '%s'"), old_name);
+ return error(_("invalid path '%s'"), old_name);
if (new_name && !verify_path(new_name))
- die(_("invalid path '%s'"), new_name);
+ return error(_("invalid path '%s'"), new_name);
+ return 0;
}
/*
}
}
- if (!state->unsafe_paths)
- die_on_unsafe_path(patch);
+ if (!state->unsafe_paths && check_unsafe_path(patch))
+ return -128;
/*
* An attempt to read from or delete a path that is beyond a
prepare_symlink_changes(state, patch);
prepare_fn_table(state, patch);
while (patch) {
+ int res;
if (state->apply_verbosely)
say_patch_name(stderr,
_("Checking patch %s..."), patch);
- err |= check_patch(state, patch);
+ res = check_patch(state, patch);
+ if (res == -128)
+ return -128;
+ err |= res;
patch = patch->next;
}
return err;
}
/* Build an index that contains the just the files needed for a 3way merge */
-static void build_fake_ancestor(struct patch *list, const char *filename)
+static int build_fake_ancestor(struct patch *list, const char *filename)
{
struct patch *patch;
struct index_state result = { NULL };
static struct lock_file lock;
+ int res;
/* Once we start supporting the reverse patch, it may be
* worth showing the new sha1 prefix, but until then...
if (!preimage_sha1_in_gitlink_patch(patch, sha1))
; /* ok, the textual part looks sane */
else
- die("sha1 information is lacking or useless for submodule %s",
- name);
+ return error("sha1 information is lacking or "
+ "useless for submodule %s", name);
} else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
; /* ok */
} else if (!patch->lines_added && !patch->lines_deleted) {
/* mode-only change: update the current */
if (get_current_sha1(patch->old_name, sha1))
- die("mode change for %s, which is not "
- "in current HEAD", name);
+ return error("mode change for %s, which is not "
+ "in current HEAD", name);
} else
- die("sha1 information is lacking or useless "
- "(%s).", name);
+ return error("sha1 information is lacking or useless "
+ "(%s).", name);
ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0);
if (!ce)
- die(_("make_cache_entry failed for path '%s'"), name);
- if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
- die ("Could not add %s to temporary index", name);
+ return error(_("make_cache_entry failed for path '%s'"),
+ name);
+ if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD)) {
+ free(ce);
+ return error("Could not add %s to temporary index",
+ name);
+ }
}
hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
- if (write_locked_index(&result, &lock, COMMIT_LOCK))
- die ("Could not write temporary index to %s", filename);
-
+ res = write_locked_index(&result, &lock, COMMIT_LOCK);
discard_index(&result);
+
+ if (res)
+ return error("Could not write temporary index to %s", filename);
+
+ return 0;
}
static void stat_patch_list(struct apply_state *state, struct patch *patch)
#define INACCURATE_EOF (1<<0)
#define RECOUNT (1<<1)
+/*
+ * Try to apply a patch.
+ *
+ * Returns:
+ * -128 if a bad error happened (like patch unreadable)
+ * -1 if patch did not apply and user cannot deal with it
+ * 0 if the patch applied
+ * 1 if the patch did not apply but user might fix it
+ */
static int apply_patch(struct apply_state *state,
int fd,
const char *filename,
struct strbuf buf = STRBUF_INIT; /* owns the patch text */
struct patch *list = NULL, **listp = &list;
int skipped_patch = 0;
+ int res = 0;
state->patch_input_file = filename;
- read_patch_file(&buf, fd);
+ if (read_patch_file(&buf, fd) < 0)
+ return -128;
offset = 0;
while (offset < buf.len) {
struct patch *patch;
nr = parse_chunk(state, buf.buf + offset, buf.len - offset, patch);
if (nr < 0) {
free_patch(patch);
+ if (nr == -128) {
+ res = -128;
+ goto end;
+ }
break;
}
if (state->apply_in_reverse)
offset += nr;
}
- if (!list && !skipped_patch)
- die(_("unrecognized input"));
+ if (!list && !skipped_patch) {
+ error(_("unrecognized input"));
+ res = -128;
+ goto end;
+ }
if (state->whitespace_error && (state->ws_error_action == die_on_ws_error))
state->apply = 0;
if (state->update_index && state->newfd < 0)
state->newfd = hold_locked_index(state->lock_file, 1);
- if (state->check_index) {
- if (read_cache() < 0)
- die(_("unable to read index file"));
+ if (state->check_index && read_cache() < 0) {
+ error(_("unable to read index file"));
+ res = -128;
+ goto end;
}
- if ((state->check || state->apply) &&
- check_patch_list(state, list) < 0 &&
- !state->apply_with_reject)
- exit(1);
+ if (state->check || state->apply) {
+ int r = check_patch_list(state, list);
+ if (r == -128) {
+ res = -128;
+ goto end;
+ }
+ if (r < 0 && !state->apply_with_reject) {
+ res = -1;
+ goto end;
+ }
+ }
if (state->apply && write_out_results(state, list)) {
- if (state->apply_with_reject)
- exit(1);
/* with --3way, we still need to write the index out */
- return 1;
+ res = state->apply_with_reject ? -1 : 1;
+ goto end;
}
- if (state->fake_ancestor)
- build_fake_ancestor(list, state->fake_ancestor);
+ if (state->fake_ancestor &&
+ build_fake_ancestor(list, state->fake_ancestor)) {
+ res = -128;
+ goto end;
+ }
if (state->diffstat)
stat_patch_list(state, list);
if (state->summary)
summary_patch_list(list);
+end:
free_patch_list(list);
strbuf_release(&buf);
string_list_clear(&state->fn_table, 0);
- return 0;
-}
-
-static void git_apply_config(void)
-{
- git_config_get_string_const("apply.whitespace", &apply_default_whitespace);
- git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace);
- git_config(git_default_config, NULL);
+ return res;
}
static int option_parse_exclude(const struct option *opt,
{
struct apply_state *state = opt->value;
state->whitespace_option = arg;
- parse_whitespace_option(state, arg);
+ if (parse_whitespace_option(state, arg))
+ exit(1);
return 0;
}
return 0;
}
-static void init_apply_state(struct apply_state *state,
- const char *prefix,
- struct lock_file *lock_file)
-{
- memset(state, 0, sizeof(*state));
- state->prefix = prefix;
- state->prefix_length = state->prefix ? strlen(state->prefix) : 0;
- state->lock_file = lock_file;
- state->newfd = -1;
- state->apply = 1;
- state->line_termination = '\n';
- state->p_value = 1;
- state->p_context = UINT_MAX;
- state->squelch_whitespace_errors = 5;
- state->ws_error_action = warn_on_ws_error;
- state->ws_ignore_action = ignore_ws_none;
- state->linenr = 1;
- string_list_init(&state->fn_table, 0);
- string_list_init(&state->limit_by_name, 0);
- string_list_init(&state->symlink_changes, 0);
- strbuf_init(&state->root, 0);
-
- git_apply_config();
- if (apply_default_whitespace)
- parse_whitespace_option(state, apply_default_whitespace);
- if (apply_default_ignorewhitespace)
- parse_ignorewhitespace_option(state, apply_default_ignorewhitespace);
-}
-
-static void clear_apply_state(struct apply_state *state)
-{
- string_list_clear(&state->limit_by_name, 0);
- string_list_clear(&state->symlink_changes, 0);
- strbuf_release(&state->root);
-
- /* &state->fn_table is cleared at the end of apply_patch() */
-}
-
-static void check_apply_state(struct apply_state *state, int force_apply)
-{
- int is_not_gitdir = !startup_info->have_repository;
-
- if (state->apply_with_reject && state->threeway)
- die("--reject and --3way cannot be used together.");
- if (state->cached && state->threeway)
- die("--cached and --3way cannot be used together.");
- if (state->threeway) {
- if (is_not_gitdir)
- die(_("--3way outside a repository"));
- state->check_index = 1;
- }
- if (state->apply_with_reject)
- state->apply = state->apply_verbosely = 1;
- if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor))
- state->apply = 0;
- if (state->check_index && is_not_gitdir)
- die(_("--index outside a repository"));
- if (state->cached) {
- if (is_not_gitdir)
- die(_("--cached outside a repository"));
- state->check_index = 1;
- }
- if (state->check_index)
- state->unsafe_paths = 0;
- if (!state->lock_file)
- die("BUG: state->lock_file should not be NULL");
-}
-
static int apply_all_patches(struct apply_state *state,
int argc,
const char **argv,
int options)
{
int i;
+ int res;
int errs = 0;
int read_stdin = 1;
int fd;
if (!strcmp(arg, "-")) {
- errs |= apply_patch(state, 0, "<stdin>", options);
+ res = apply_patch(state, 0, "<stdin>", options);
+ if (res < 0)
+ goto end;
+ errs |= res;
read_stdin = 0;
continue;
} else if (0 < state->prefix_length)
arg);
fd = open(arg, O_RDONLY);
- if (fd < 0)
- die_errno(_("can't open patch '%s'"), arg);
+ if (fd < 0) {
+ error(_("can't open patch '%s': %s"), arg, strerror(errno));
+ res = -128;
+ goto end;
+ }
read_stdin = 0;
set_default_whitespace_mode(state);
- errs |= apply_patch(state, fd, arg, options);
+ res = apply_patch(state, fd, arg, options);
close(fd);
+ if (res < 0)
+ goto end;
+ errs |= res;
}
set_default_whitespace_mode(state);
- if (read_stdin)
- errs |= apply_patch(state, 0, "<stdin>", options);
+ if (read_stdin) {
+ res = apply_patch(state, 0, "<stdin>", options);
+ if (res < 0)
+ goto end;
+ errs |= res;
+ }
if (state->whitespace_error) {
if (state->squelch_whitespace_errors &&
squelched),
squelched);
}
- if (state->ws_error_action == die_on_ws_error)
- die(Q_("%d line adds whitespace errors.",
- "%d lines add whitespace errors.",
- state->whitespace_error),
- state->whitespace_error);
+ if (state->ws_error_action == die_on_ws_error) {
+ error(Q_("%d line adds whitespace errors.",
+ "%d lines add whitespace errors.",
+ state->whitespace_error),
+ state->whitespace_error);
+ res = -128;
+ goto end;
+ }
if (state->applied_after_fixing_ws && state->apply)
warning("%d line%s applied after"
" fixing whitespace errors.",
}
if (state->update_index) {
- if (write_locked_index(&the_index, state->lock_file, COMMIT_LOCK))
- die(_("Unable to write new index file"));
+ res = write_locked_index(&the_index, state->lock_file, COMMIT_LOCK);
+ if (res) {
+ error(_("Unable to write new index file"));
+ res = -128;
+ goto end;
+ }
state->newfd = -1;
}
return !!errs;
+
+end:
+ if (state->newfd >= 0) {
+ rollback_lock_file(state->lock_file);
+ state->newfd = -1;
+ }
+
+ return (res == -1 ? 1 : 128);
}
int cmd_apply(int argc, const char **argv, const char *prefix)
OPT_END()
};
- init_apply_state(&state, prefix, &lock_file);
+ if (init_apply_state(&state, prefix, &lock_file))
+ exit(128);
argc = parse_options(argc, argv, state.prefix, builtin_apply_options,
apply_usage, 0);
- check_apply_state(&state, force_apply);
+ if (check_apply_state(&state, force_apply))
+ exit(128);
ret = apply_all_patches(&state, argc, argv, options);