builtin/apply: move 'allow_overlap' global into 'struct apply_state'
[gitweb.git] / builtin / apply.c
index 52b5d3ed8e0313f4016f0084ea6e964c8bf8cdb0..ad3bec443124e303035cd516415b1b58d8fe7bbb 100644 (file)
 struct apply_state {
        const char *prefix;
        int prefix_length;
+
+       /* These control what gets looked at and modified */
+       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 boolean parameters control how the apply is done */
+       int allow_overlap;
+       int apply_in_reverse;
+       int apply_with_reject;
+       int apply_verbosely;
+       int unidiff_zero;
 };
 
 /*
- *  --check turns on checking that the working tree matches the
- *    files that are being modified, but doesn't apply the patch
  *  --stat does just a diffstat, and doesn't actually apply
  *  --numstat does numeric diffstat, and doesn't actually apply
  *  --index-info shows the old and new index info for paths if available.
- *  --index updates the cache as well.
  *  --cached updates only the cache without ever touching the working tree.
  */
 static int newfd = -1;
 
-static int unidiff_zero;
 static int state_p_value = 1;
 static int p_value_known;
-static int check_index;
-static int update_index;
 static int cached;
 static int diffstat;
 static int numstat;
 static int summary;
-static int check;
 static int apply = 1;
-static int apply_in_reverse;
-static int apply_with_reject;
-static int apply_verbosely;
-static int allow_overlap;
 static int no_add;
 static int threeway;
 static int unsafe_paths;
@@ -1555,8 +1556,11 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule)
  * between a "---" that is part of a patch, and a "---" that starts
  * the next patch is to look at the line counts..
  */
-static int parse_fragment(const char *line, unsigned long size,
-                         struct patch *patch, struct fragment *fragment)
+static int parse_fragment(struct apply_state *state,
+                         const char *line,
+                         unsigned long size,
+                         struct patch *patch,
+                         struct fragment *fragment)
 {
        int added, deleted;
        int len = linelen(line, size), offset;
@@ -1596,12 +1600,12 @@ static int parse_fragment(const char *line, unsigned long size,
                        if (!deleted && !added)
                                leading++;
                        trailing++;
-                       if (!apply_in_reverse &&
+                       if (!state->apply_in_reverse &&
                            ws_error_action == correct_ws_error)
                                check_whitespace(line, len, patch->ws_rule);
                        break;
                case '-':
-                       if (apply_in_reverse &&
+                       if (state->apply_in_reverse &&
                            ws_error_action != nowarn_ws_error)
                                check_whitespace(line, len, patch->ws_rule);
                        deleted++;
@@ -1609,7 +1613,7 @@ static int parse_fragment(const char *line, unsigned long size,
                        trailing = 0;
                        break;
                case '+':
-                       if (!apply_in_reverse &&
+                       if (!state->apply_in_reverse &&
                            ws_error_action != nowarn_ws_error)
                                check_whitespace(line, len, patch->ws_rule);
                        added++;
@@ -1665,7 +1669,10 @@ static int parse_fragment(const char *line, unsigned long size,
  * The (fragment->patch, fragment->size) pair points into the memory given
  * by the caller, not a copy, when we return.
  */
-static int parse_single_patch(const char *line, unsigned long size, struct patch *patch)
+static int parse_single_patch(struct apply_state *state,
+                             const char *line,
+                             unsigned long size,
+                             struct patch *patch)
 {
        unsigned long offset = 0;
        unsigned long oldlines = 0, newlines = 0, context = 0;
@@ -1677,7 +1684,7 @@ static int parse_single_patch(const char *line, unsigned long size, struct patch
 
                fragment = xcalloc(1, sizeof(*fragment));
                fragment->linenr = state_linenr;
-               len = parse_fragment(line, size, patch, fragment);
+               len = parse_fragment(state, line, size, patch, fragment);
                if (len <= 0)
                        die(_("corrupt patch at line %d"), state_linenr);
                fragment->patch = line;
@@ -2007,8 +2014,10 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si
                                                 ? patch->new_name
                                                 : patch->old_name);
 
-       patchsize = parse_single_patch(buffer + offset + hdrsize,
-                                      size - offset - hdrsize, patch);
+       patchsize = parse_single_patch(state,
+                                      buffer + offset + hdrsize,
+                                      size - offset - hdrsize,
+                                      patch);
 
        if (!patchsize) {
                static const char git_binary[] = "GIT binary patch\n";
@@ -2051,7 +2060,7 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si
                 * without metadata change.  A binary patch appears
                 * empty to us here.
                 */
-               if ((apply || check) &&
+               if ((apply || state->check) &&
                    (!patch->is_binary && !metadata_changes(patch)))
                        die(_("patch with only garbage at line %d"), state_linenr);
        }
@@ -2618,7 +2627,8 @@ static void remove_last_line(struct image *img)
  * apply at applied_pos (counts in line numbers) in "img".
  * Update "img" to remove "preimage" and replace it with "postimage".
  */
-static void update_image(struct image *img,
+static void update_image(struct apply_state *state,
+                        struct image *img,
                         int applied_pos,
                         struct image *preimage,
                         struct image *postimage)
@@ -2683,7 +2693,7 @@ static void update_image(struct image *img,
        memcpy(img->line + applied_pos,
               postimage->line,
               postimage->nr * sizeof(*img->line));
-       if (!allow_overlap)
+       if (!state->allow_overlap)
                for (i = 0; i < postimage->nr; i++)
                        img->line[applied_pos + i].flag |= LINE_PATCHED;
        img->nr = nr;
@@ -2694,7 +2704,8 @@ static void update_image(struct image *img,
  * postimage) for the hunk.  Find lines that match "preimage" in "img" and
  * replace the part of "img" with "postimage" text.
  */
-static int apply_one_fragment(struct image *img, struct fragment *frag,
+static int apply_one_fragment(struct apply_state *state,
+                             struct image *img, struct fragment *frag,
                              int inaccurate_eof, unsigned ws_rule,
                              int nth_fragment)
 {
@@ -2739,7 +2750,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                if (len < size && patch[len] == '\\')
                        plen--;
                first = *patch;
-               if (apply_in_reverse) {
+               if (state->apply_in_reverse) {
                        if (first == '-')
                                first = '+';
                        else if (first == '+')
@@ -2795,7 +2806,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                        /* Ignore it, we already handled it */
                        break;
                default:
-                       if (apply_verbosely)
+                       if (state->apply_verbosely)
                                error(_("invalid start of line: '%c'"), first);
                        applied_pos = -1;
                        goto out;
@@ -2836,7 +2847,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
         * without leading context must match at the beginning.
         */
        match_beginning = (!frag->oldpos ||
-                          (frag->oldpos == 1 && !unidiff_zero));
+                          (frag->oldpos == 1 && !state->unidiff_zero));
 
        /*
         * A hunk without trailing lines must match at the end.
@@ -2844,7 +2855,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
         * from the lack of trailing lines if the patch was generated
         * with unidiff without any context.
         */
-       match_end = !unidiff_zero && !trailing;
+       match_end = !state->unidiff_zero && !trailing;
 
        pos = frag->newpos ? (frag->newpos - 1) : 0;
        preimage.buf = oldlines;
@@ -2910,9 +2921,9 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                                apply = 0;
                }
 
-               if (apply_verbosely && applied_pos != pos) {
+               if (state->apply_verbosely && applied_pos != pos) {
                        int offset = applied_pos - pos;
-                       if (apply_in_reverse)
+                       if (state->apply_in_reverse)
                                offset = 0 - offset;
                        fprintf_ln(stderr,
                                   Q_("Hunk #%d succeeded at %d (offset %d line).",
@@ -2930,9 +2941,9 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                        fprintf_ln(stderr, _("Context reduced to (%ld/%ld)"
                                             " to apply fragment at %d"),
                                   leading, trailing, applied_pos+1);
-               update_image(img, applied_pos, &preimage, &postimage);
+               update_image(state, img, applied_pos, &preimage, &postimage);
        } else {
-               if (apply_verbosely)
+               if (state->apply_verbosely)
                        error(_("while searching for:\n%.*s"),
                              (int)(old - oldlines), oldlines);
        }
@@ -2946,7 +2957,9 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        return (applied_pos < 0);
 }
 
-static int apply_binary_fragment(struct image *img, struct patch *patch)
+static int apply_binary_fragment(struct apply_state *state,
+                                struct image *img,
+                                struct patch *patch)
 {
        struct fragment *fragment = patch->fragments;
        unsigned long len;
@@ -2959,7 +2972,7 @@ static int apply_binary_fragment(struct image *img, struct patch *patch)
                             patch->old_name);
 
        /* Binary patch is irreversible without the optional second hunk */
-       if (apply_in_reverse) {
+       if (state->apply_in_reverse) {
                if (!fragment->next)
                        return error("cannot reverse-apply a binary patch "
                                     "without the reverse hunk to '%s'",
@@ -2992,7 +3005,9 @@ static int apply_binary_fragment(struct image *img, struct patch *patch)
  * but the preimage prepared by the caller in "img" is freed here
  * or in the helper function apply_binary_fragment() this calls.
  */
-static int apply_binary(struct image *img, struct patch *patch)
+static int apply_binary(struct apply_state *state,
+                       struct image *img,
+                       struct patch *patch)
 {
        const char *name = patch->old_name ? patch->old_name : patch->new_name;
        unsigned char sha1[20];
@@ -3053,7 +3068,7 @@ static int apply_binary(struct image *img, struct patch *patch)
                 * apply the patch data to it, which is stored
                 * in the patch->fragments->{patch,size}.
                 */
-               if (apply_binary_fragment(img, patch))
+               if (apply_binary_fragment(state, img, patch))
                        return error(_("binary patch does not apply to '%s'"),
                                     name);
 
@@ -3067,7 +3082,7 @@ static int apply_binary(struct image *img, struct patch *patch)
        return 0;
 }
 
-static int apply_fragments(struct image *img, struct patch *patch)
+static int apply_fragments(struct apply_state *state, struct image *img, struct patch *patch)
 {
        struct fragment *frag = patch->fragments;
        const char *name = patch->old_name ? patch->old_name : patch->new_name;
@@ -3076,13 +3091,13 @@ static int apply_fragments(struct image *img, struct patch *patch)
        int nth = 0;
 
        if (patch->is_binary)
-               return apply_binary(img, patch);
+               return apply_binary(state, img, patch);
 
        while (frag) {
                nth++;
-               if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
+               if (apply_one_fragment(state, img, frag, inaccurate_eof, ws_rule, nth)) {
                        error(_("patch failed: %s:%ld"), name, frag->oldpos);
-                       if (!apply_with_reject)
+                       if (!state->apply_with_reject)
                                return -1;
                        frag->rejected = 1;
                }
@@ -3242,13 +3257,14 @@ static int verify_index_match(const struct cache_entry *ce, struct stat *st)
 
 #define SUBMODULE_PATCH_WITHOUT_INDEX 1
 
-static int load_patch_target(struct strbuf *buf,
+static int load_patch_target(struct apply_state *state,
+                            struct strbuf *buf,
                             const struct cache_entry *ce,
                             struct stat *st,
                             const char *name,
                             unsigned expected_mode)
 {
-       if (cached || check_index) {
+       if (cached || state->check_index) {
                if (read_file_or_gitlink(ce, buf))
                        return error(_("read of %s failed"), name);
        } else if (name) {
@@ -3274,7 +3290,8 @@ static int load_patch_target(struct strbuf *buf,
  * applying a non-git patch that incrementally updates the tree,
  * we read from the result of a previous diff.
  */
-static int load_preimage(struct image *image,
+static int load_preimage(struct apply_state *state,
+                        struct image *image,
                         struct patch *patch, struct stat *st,
                         const struct cache_entry *ce)
 {
@@ -3292,7 +3309,7 @@ static int load_preimage(struct image *image,
                /* We have a patched copy in memory; use that. */
                strbuf_add(&buf, previous->result, previous->resultsize);
        } else {
-               status = load_patch_target(&buf, ce, st,
+               status = load_patch_target(state, &buf, ce, st,
                                           patch->old_name, patch->old_mode);
                if (status < 0)
                        return status;
@@ -3351,7 +3368,9 @@ static int three_way_merge(struct image *image,
  * the current contents of the new_name.  In no cases other than that
  * this function will be called.
  */
-static int load_current(struct image *image, struct patch *patch)
+static int load_current(struct apply_state *state,
+                       struct image *image,
+                       struct patch *patch)
 {
        struct strbuf buf = STRBUF_INIT;
        int status, pos;
@@ -3378,7 +3397,7 @@ static int load_current(struct image *image, struct patch *patch)
        if (verify_index_match(ce, &st))
                return error(_("%s: does not match index"), name);
 
-       status = load_patch_target(&buf, ce, &st, name, mode);
+       status = load_patch_target(state, &buf, ce, &st, name, mode);
        if (status < 0)
                return status;
        else if (status)
@@ -3388,8 +3407,11 @@ static int load_current(struct image *image, struct patch *patch)
        return 0;
 }
 
-static int try_threeway(struct image *image, struct patch *patch,
-                       struct stat *st, const struct cache_entry *ce)
+static int try_threeway(struct apply_state *state,
+                       struct image *image,
+                       struct patch *patch,
+                       struct stat *st,
+                       const struct cache_entry *ce)
 {
        unsigned char pre_sha1[20], post_sha1[20], our_sha1[20];
        struct strbuf buf = STRBUF_INIT;
@@ -3415,7 +3437,7 @@ static int try_threeway(struct image *image, struct patch *patch,
        img = strbuf_detach(&buf, &len);
        prepare_image(&tmp_image, img, len, 1);
        /* Apply the patch to get the post image */
-       if (apply_fragments(&tmp_image, patch) < 0) {
+       if (apply_fragments(state, &tmp_image, patch) < 0) {
                clear_image(&tmp_image);
                return -1;
        }
@@ -3425,11 +3447,11 @@ static int try_threeway(struct image *image, struct patch *patch,
 
        /* our_sha1[] is ours */
        if (patch->is_new) {
-               if (load_current(&tmp_image, patch))
+               if (load_current(state, &tmp_image, patch))
                        return error("cannot read the current contents of '%s'",
                                     patch->new_name);
        } else {
-               if (load_preimage(&tmp_image, patch, st, ce))
+               if (load_preimage(state, &tmp_image, patch, st, ce))
                        return error("cannot read the current contents of '%s'",
                                     patch->old_name);
        }
@@ -3459,17 +3481,18 @@ static int try_threeway(struct image *image, struct patch *patch,
        return 0;
 }
 
-static int apply_data(struct patch *patch, struct stat *st, const struct cache_entry *ce)
+static int apply_data(struct apply_state *state, struct patch *patch,
+                     struct stat *st, const struct cache_entry *ce)
 {
        struct image image;
 
-       if (load_preimage(&image, patch, st, ce) < 0)
+       if (load_preimage(state, &image, patch, st, ce) < 0)
                return -1;
 
        if (patch->direct_to_threeway ||
-           apply_fragments(&image, patch) < 0) {
+           apply_fragments(state, &image, patch) < 0) {
                /* Note: with --reject, apply_fragments() returns 0 */
-               if (!threeway || try_threeway(&image, patch, st, ce) < 0)
+               if (!threeway || try_threeway(state, &image, patch, st, ce) < 0)
                        return -1;
        }
        patch->result = image.buf;
@@ -3494,7 +3517,10 @@ static int apply_data(struct patch *patch, struct stat *st, const struct cache_e
  * check_patch() separately makes sure (and errors out otherwise) that
  * the path the patch creates does not exist in the current tree.
  */
-static int check_preimage(struct patch *patch, struct cache_entry **ce, struct stat *st)
+static int check_preimage(struct apply_state *state,
+                         struct patch *patch,
+                         struct cache_entry **ce,
+                         struct stat *st)
 {
        const char *old_name = patch->old_name;
        struct patch *previous = NULL;
@@ -3517,7 +3543,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
                        return error(_("%s: %s"), old_name, strerror(errno));
        }
 
-       if (check_index && !previous) {
+       if (state->check_index && !previous) {
                int pos = cache_name_pos(old_name, strlen(old_name));
                if (pos < 0) {
                        if (patch->is_new < 0)
@@ -3567,11 +3593,13 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
 #define EXISTS_IN_INDEX 1
 #define EXISTS_IN_WORKTREE 2
 
-static int check_to_create(const char *new_name, int ok_if_exists)
+static int check_to_create(struct apply_state *state,
+                          const char *new_name,
+                          int ok_if_exists)
 {
        struct stat nst;
 
-       if (check_index &&
+       if (state->check_index &&
            cache_name_pos(new_name, strlen(new_name)) >= 0 &&
            !ok_if_exists)
                return EXISTS_IN_INDEX;
@@ -3647,7 +3675,7 @@ static void prepare_symlink_changes(struct patch *patch)
        }
 }
 
-static int path_is_beyond_symlink_1(struct strbuf *name)
+static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *name)
 {
        do {
                unsigned int change;
@@ -3668,7 +3696,7 @@ static int path_is_beyond_symlink_1(struct strbuf *name)
                        continue;
 
                /* otherwise, check the preimage */
-               if (check_index) {
+               if (state->check_index) {
                        struct cache_entry *ce;
 
                        ce = cache_file_exists(name->buf, name->len, ignore_case);
@@ -3683,14 +3711,14 @@ static int path_is_beyond_symlink_1(struct strbuf *name)
        return 0;
 }
 
-static int path_is_beyond_symlink(const char *name_)
+static int path_is_beyond_symlink(struct apply_state *state, const char *name_)
 {
        int ret;
        struct strbuf name = STRBUF_INIT;
 
        assert(*name_ != '\0');
        strbuf_addstr(&name, name_);
-       ret = path_is_beyond_symlink_1(&name);
+       ret = path_is_beyond_symlink_1(state, &name);
        strbuf_release(&name);
 
        return ret;
@@ -3717,7 +3745,7 @@ static void die_on_unsafe_path(struct patch *patch)
  * Check and apply the patch in-core; leave the result in patch->result
  * for the caller to write it out to the final destination.
  */
-static int check_patch(struct patch *patch)
+static int check_patch(struct apply_state *state, struct patch *patch)
 {
        struct stat st;
        const char *old_name = patch->old_name;
@@ -3730,7 +3758,7 @@ static int check_patch(struct patch *patch)
 
        patch->rejected = 1; /* we will drop this after we succeed */
 
-       status = check_preimage(patch, &ce, &st);
+       status = check_preimage(state, patch, &ce, &st);
        if (status)
                return status;
        old_name = patch->old_name;
@@ -3757,7 +3785,7 @@ static int check_patch(struct patch *patch)
 
        if (new_name &&
            ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) {
-               int err = check_to_create(new_name, ok_if_exists);
+               int err = check_to_create(state, new_name, ok_if_exists);
 
                if (err && threeway) {
                        patch->direct_to_threeway = 1;
@@ -3812,27 +3840,27 @@ static int check_patch(struct patch *patch)
         * is not deposited to a path that is beyond a symbolic link
         * here.
         */
-       if (!patch->is_delete && path_is_beyond_symlink(patch->new_name))
+       if (!patch->is_delete && path_is_beyond_symlink(state, patch->new_name))
                return error(_("affected file '%s' is beyond a symbolic link"),
                             patch->new_name);
 
-       if (apply_data(patch, &st, ce) < 0)
+       if (apply_data(state, patch, &st, ce) < 0)
                return error(_("%s: patch does not apply"), name);
        patch->rejected = 0;
        return 0;
 }
 
-static int check_patch_list(struct patch *patch)
+static int check_patch_list(struct apply_state *state, struct patch *patch)
 {
        int err = 0;
 
        prepare_symlink_changes(patch);
        prepare_fn_table(patch);
        while (patch) {
-               if (apply_verbosely)
+               if (state->apply_verbosely)
                        say_patch_name(stderr,
                                       _("Checking patch %s..."), patch);
-               err |= check_patch(patch);
+               err |= check_patch(state, patch);
                patch = patch->next;
        }
        return err;
@@ -4063,9 +4091,9 @@ static void patch_stats(struct patch *patch)
        }
 }
 
-static void remove_file(struct patch *patch, int rmdir_empty)
+static void remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty)
 {
-       if (update_index) {
+       if (state->update_index) {
                if (remove_file_from_cache(patch->old_name) < 0)
                        die(_("unable to remove %s from index"), patch->old_name);
        }
@@ -4076,14 +4104,18 @@ static void remove_file(struct patch *patch, int rmdir_empty)
        }
 }
 
-static void add_index_file(const char *path, unsigned mode, void *buf, unsigned long size)
+static void add_index_file(struct apply_state *state,
+                          const char *path,
+                          unsigned mode,
+                          void *buf,
+                          unsigned long size)
 {
        struct stat st;
        struct cache_entry *ce;
        int namelen = strlen(path);
        unsigned ce_size = cache_entry_size(namelen);
 
-       if (!update_index)
+       if (!state->update_index)
                return;
 
        ce = xcalloc(1, ce_size);
@@ -4193,13 +4225,14 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
        die_errno(_("unable to write file '%s' mode %o"), path, mode);
 }
 
-static void add_conflicted_stages_file(struct patch *patch)
+static void add_conflicted_stages_file(struct apply_state *state,
+                                      struct patch *patch)
 {
        int stage, namelen;
        unsigned ce_size, mode;
        struct cache_entry *ce;
 
-       if (!update_index)
+       if (!state->update_index)
                return;
        namelen = strlen(patch->new_name);
        ce_size = cache_entry_size(namelen);
@@ -4220,7 +4253,7 @@ static void add_conflicted_stages_file(struct patch *patch)
        }
 }
 
-static void create_file(struct patch *patch)
+static void create_file(struct apply_state *state, struct patch *patch)
 {
        char *path = patch->new_name;
        unsigned mode = patch->new_mode;
@@ -4232,22 +4265,24 @@ static void create_file(struct patch *patch)
        create_one_file(path, mode, buf, size);
 
        if (patch->conflicted_threeway)
-               add_conflicted_stages_file(patch);
+               add_conflicted_stages_file(state, patch);
        else
-               add_index_file(path, mode, buf, size);
+               add_index_file(state, path, mode, buf, size);
 }
 
 /* phase zero is to remove, phase one is to create */
-static void write_out_one_result(struct patch *patch, int phase)
+static void write_out_one_result(struct apply_state *state,
+                                struct patch *patch,
+                                int phase)
 {
        if (patch->is_delete > 0) {
                if (phase == 0)
-                       remove_file(patch, 1);
+                       remove_file(state, patch, 1);
                return;
        }
        if (patch->is_new > 0 || patch->is_copy) {
                if (phase == 1)
-                       create_file(patch);
+                       create_file(state, patch);
                return;
        }
        /*
@@ -4255,12 +4290,12 @@ static void write_out_one_result(struct patch *patch, int phase)
         * thing: remove the old, write the new
         */
        if (phase == 0)
-               remove_file(patch, patch->is_rename);
+               remove_file(state, patch, patch->is_rename);
        if (phase == 1)
-               create_file(patch);
+               create_file(state, patch);
 }
 
-static int write_out_one_reject(struct patch *patch)
+static int write_out_one_reject(struct apply_state *state, struct patch *patch)
 {
        FILE *rej;
        char namebuf[PATH_MAX];
@@ -4275,7 +4310,7 @@ static int write_out_one_reject(struct patch *patch)
        }
 
        if (!cnt) {
-               if (apply_verbosely)
+               if (state->apply_verbosely)
                        say_patch_name(stderr,
                                       _("Applied patch %s cleanly."), patch);
                return 0;
@@ -4331,7 +4366,7 @@ static int write_out_one_reject(struct patch *patch)
        return -1;
 }
 
-static int write_out_results(struct patch *list)
+static int write_out_results(struct apply_state *state, struct patch *list)
 {
        int phase;
        int errs = 0;
@@ -4344,9 +4379,9 @@ static int write_out_results(struct patch *list)
                        if (l->rejected)
                                errs = 1;
                        else {
-                               write_out_one_result(l, phase);
+                               write_out_one_result(state, l, phase);
                                if (phase == 1) {
-                                       if (write_out_one_reject(l))
+                                       if (write_out_one_reject(state, l))
                                                errs = 1;
                                        if (l->conflicted_threeway) {
                                                string_list_append(&cpath, l->new_name);
@@ -4402,7 +4437,7 @@ static int apply_patch(struct apply_state *state,
                        free_patch(patch);
                        break;
                }
-               if (apply_in_reverse)
+               if (state->apply_in_reverse)
                        reverse_patches(patch);
                if (use_patch(state, patch)) {
                        patch_stats(patch);
@@ -4410,7 +4445,7 @@ static int apply_patch(struct apply_state *state,
                        listp = &patch->next;
                }
                else {
-                       if (apply_verbosely)
+                       if (state->apply_verbosely)
                                say_patch_name(stderr, _("Skipped patch '%s'."), patch);
                        free_patch(patch);
                        skipped_patch++;
@@ -4424,22 +4459,22 @@ static int apply_patch(struct apply_state *state,
        if (whitespace_error && (ws_error_action == die_on_ws_error))
                apply = 0;
 
-       update_index = check_index && apply;
-       if (update_index && newfd < 0)
+       state->update_index = state->check_index && apply;
+       if (state->update_index && newfd < 0)
                newfd = hold_locked_index(&lock_file, 1);
 
-       if (check_index) {
+       if (state->check_index) {
                if (read_cache() < 0)
                        die(_("unable to read index file"));
        }
 
-       if ((check || apply) &&
-           check_patch_list(list) < 0 &&
-           !apply_with_reject)
+       if ((state->check || apply) &&
+           check_patch_list(state, list) < 0 &&
+           !state->apply_with_reject)
                exit(1);
 
-       if (apply && write_out_results(list)) {
-               if (apply_with_reject)
+       if (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;
@@ -4572,9 +4607,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
                        N_("show number of added and deleted lines in decimal notation")),
                OPT_BOOL(0, "summary", &summary,
                        N_("instead of applying the patch, output a summary for the input")),
-               OPT_BOOL(0, "check", &check,
+               OPT_BOOL(0, "check", &state.check,
                        N_("instead of applying the patch, see if the patch is applicable")),
-               OPT_BOOL(0, "index", &check_index,
+               OPT_BOOL(0, "index", &state.check_index,
                        N_("make sure the patch is applicable to the current index")),
                OPT_BOOL(0, "cached", &cached,
                        N_("apply a patch without touching the working tree")),
@@ -4600,15 +4635,15 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
                { OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL,
                        N_("ignore changes in whitespace when finding context"),
                        PARSE_OPT_NOARG, option_parse_space_change },
-               OPT_BOOL('R', "reverse", &apply_in_reverse,
+               OPT_BOOL('R', "reverse", &state.apply_in_reverse,
                        N_("apply the patch in reverse")),
-               OPT_BOOL(0, "unidiff-zero", &unidiff_zero,
+               OPT_BOOL(0, "unidiff-zero", &state.unidiff_zero,
                        N_("don't expect at least one line of context")),
-               OPT_BOOL(0, "reject", &apply_with_reject,
+               OPT_BOOL(0, "reject", &state.apply_with_reject,
                        N_("leave the rejected hunks in corresponding *.rej files")),
-               OPT_BOOL(0, "allow-overlap", &allow_overlap,
+               OPT_BOOL(0, "allow-overlap", &state.allow_overlap,
                        N_("allow overlapping hunks")),
-               OPT__VERBOSE(&apply_verbosely, N_("be verbose")),
+               OPT__VERBOSE(&state.apply_verbosely, N_("be verbose")),
                OPT_BIT(0, "inaccurate-eof", &options,
                        N_("tolerate incorrectly detected missing new-line at the end of file"),
                        INACCURATE_EOF),
@@ -4626,27 +4661,27 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, state.prefix, builtin_apply_options,
                        apply_usage, 0);
 
-       if (apply_with_reject && threeway)
+       if (state.apply_with_reject && threeway)
                die("--reject and --3way cannot be used together.");
        if (cached && threeway)
                die("--cached and --3way cannot be used together.");
        if (threeway) {
                if (is_not_gitdir)
                        die(_("--3way outside a repository"));
-               check_index = 1;
+               state.check_index = 1;
        }
-       if (apply_with_reject)
-               apply = apply_verbosely = 1;
-       if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))
+       if (state.apply_with_reject)
+               apply = state.apply_verbosely = 1;
+       if (!force_apply && (diffstat || numstat || summary || state.check || fake_ancestor))
                apply = 0;
-       if (check_index && is_not_gitdir)
+       if (state.check_index && is_not_gitdir)
                die(_("--index outside a repository"));
        if (cached) {
                if (is_not_gitdir)
                        die(_("--cached outside a repository"));
-               check_index = 1;
+               state.check_index = 1;
        }
-       if (check_index)
+       if (state.check_index)
                unsafe_paths = 0;
 
        for (i = 0; i < argc; i++) {
@@ -4700,7 +4735,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
                                whitespace_error);
        }
 
-       if (update_index) {
+       if (state.update_index) {
                if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
                        die(_("Unable to write new index file"));
        }