* 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;
}
*/
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) {
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;
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)
goto end;
}
- if ((state->check || state->apply) &&
- check_patch_list(state, list) < 0 &&
- !state->apply_with_reject) {
- res = -1;
- goto end;
+ 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)) {
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);
return 0;
}
-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,
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);
res = apply_patch(state, fd, arg, options);
+ close(fd);
if (res < 0)
goto end;
errs |= res;
- close(fd);
}
set_default_whitespace_mode(state);
if (read_stdin) {
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:
- exit(res == -1 ? 1 : 128);
+ 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);