Signed-off-by: Christian Couder <chrisc...@tuxfamily.org>
---
 builtin/apply.c | 94 ++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 56 insertions(+), 38 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 838e46a..462e28f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -21,6 +21,11 @@
 #include "ll-merge.h"
 #include "rerere.h"
 
+struct apply_state {
+       const char *prefix;
+       int prefix_length;
+};
+
 /*
  *  --check turns on checking that the working tree matches the
  *    files that are being modified, but doesn't apply the patch
@@ -30,8 +35,6 @@
  *  --index updates the cache as well.
  *  --cached updates only the cache without ever touching the working tree.
  */
-static const char *prefix;
-static int prefix_length = -1;
 static int newfd = -1;
 
 static int unidiff_zero;
@@ -749,7 +752,7 @@ static int count_slashes(const char *cp)
  * Given the string after "--- " or "+++ ", guess the appropriate
  * p_value for the given patch.
  */
-static int guess_p_value(const char *nameline)
+static int guess_p_value(struct apply_state *state, const char *nameline)
 {
        char *name, *cp;
        int val = -1;
@@ -762,17 +765,17 @@ static int guess_p_value(const char *nameline)
        cp = strchr(name, '/');
        if (!cp)
                val = 0;
-       else if (prefix) {
+       else if (state->prefix) {
                /*
                 * Does it begin with "a/$our-prefix" and such?  Then this is
                 * very likely to apply to our directory.
                 */
-               if (!strncmp(name, prefix, prefix_length))
-                       val = count_slashes(prefix);
+               if (!strncmp(name, state->prefix, state->prefix_length))
+                       val = count_slashes(state->prefix);
                else {
                        cp++;
-                       if (!strncmp(cp, prefix, prefix_length))
-                               val = count_slashes(prefix) + 1;
+                       if (!strncmp(cp, state->prefix, state->prefix_length))
+                               val = count_slashes(state->prefix) + 1;
                }
        }
        free(name);
@@ -859,7 +862,10 @@ static int has_epoch_timestamp(const char *nameline)
  * 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(const char *first, const char *second, 
struct patch *patch)
+static void parse_traditional_patch(struct apply_state *state,
+                                   const char *first,
+                                   const char *second,
+                                   struct patch *patch)
 {
        char *name;
 
@@ -867,8 +873,8 @@ static void parse_traditional_patch(const char *first, 
const char *second, struc
        second += 4;    /* skip "+++ " */
        if (!p_value_known) {
                int p, q;
-               p = guess_p_value(first);
-               q = guess_p_value(second);
+               p = guess_p_value(state, first);
+               q = guess_p_value(state, second);
                if (p < 0) p = q;
                if (0 <= p && p == q) {
                        p_value = p;
@@ -1439,7 +1445,11 @@ static int parse_fragment_header(const char *line, int 
len, struct fragment *fra
        return offset;
 }
 
-static int find_header(const char *line, unsigned long size, int *hdrsize, 
struct patch *patch)
+static int find_header(struct apply_state *state,
+                      const char *line,
+                      unsigned long size,
+                      int *hdrsize,
+                      struct patch *patch)
 {
        unsigned long offset, len;
 
@@ -1516,7 +1526,7 @@ static int find_header(const char *line, unsigned long 
size, int *hdrsize, struc
                        continue;
 
                /* Ok, we'll consider it a patch */
-               parse_traditional_patch(line, line+len, patch);
+               parse_traditional_patch(state, line, line+len, patch);
                *hdrsize = len + nextlen;
                linenr += 2;
                return offset;
@@ -1918,21 +1928,21 @@ static int parse_binary(char *buffer, unsigned long 
size, struct patch *patch)
        return used;
 }
 
-static void prefix_one(char **name)
+static void prefix_one(struct apply_state *state, char **name)
 {
        char *old_name = *name;
        if (!old_name)
                return;
-       *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
+       *name = xstrdup(prefix_filename(state->prefix, state->prefix_length, 
*name));
        free(old_name);
 }
 
-static void prefix_patch(struct patch *p)
+static void prefix_patch(struct apply_state *state, struct patch *p)
 {
-       if (!prefix || p->is_toplevel_relative)
+       if (!state->prefix || p->is_toplevel_relative)
                return;
-       prefix_one(&p->new_name);
-       prefix_one(&p->old_name);
+       prefix_one(state, &p->new_name);
+       prefix_one(state, &p->old_name);
 }
 
 /*
@@ -1949,16 +1959,16 @@ static void add_name_limit(const char *name, int 
exclude)
        it->util = exclude ? NULL : (void *) 1;
 }
 
-static int use_patch(struct patch *p)
+static int use_patch(struct apply_state *state, struct patch *p)
 {
        const char *pathname = p->new_name ? p->new_name : p->old_name;
        int i;
 
        /* Paths outside are not touched regardless of "--include" */
-       if (0 < prefix_length) {
+       if (0 < state->prefix_length) {
                int pathlen = strlen(pathname);
-               if (pathlen <= prefix_length ||
-                   memcmp(prefix, pathname, prefix_length))
+               if (pathlen <= state->prefix_length ||
+                   memcmp(state->prefix, pathname, state->prefix_length))
                        return 0;
        }
 
@@ -1985,17 +1995,17 @@ static int use_patch(struct patch *p)
  * Return the number of bytes consumed, so that the caller can call us
  * again for the next patch.
  */
-static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
+static int parse_chunk(struct apply_state *state, char *buffer, unsigned long 
size, struct patch *patch)
 {
        int hdrsize, patchsize;
-       int offset = find_header(buffer, size, &hdrsize, patch);
+       int offset = find_header(state, buffer, size, &hdrsize, patch);
 
        if (offset < 0)
                return offset;
 
-       prefix_patch(patch);
+       prefix_patch(state, patch);
 
-       if (!use_patch(patch))
+       if (!use_patch(state, patch))
                patch->ws_rule = 0;
        else
                patch->ws_rule = whitespace_rule(patch->new_name
@@ -4371,7 +4381,10 @@ static struct lock_file lock_file;
 #define INACCURATE_EOF (1<<0)
 #define RECOUNT                (1<<1)
 
-static int apply_patch(int fd, const char *filename, int options)
+static int apply_patch(struct apply_state *state,
+                      int fd,
+                      const char *filename,
+                      int options)
 {
        size_t offset;
        struct strbuf buf = STRBUF_INIT; /* owns the patch text */
@@ -4388,12 +4401,12 @@ static int apply_patch(int fd, const char *filename, 
int options)
                patch = xcalloc(1, sizeof(*patch));
                patch->inaccurate_eof = !!(options & INACCURATE_EOF);
                patch->recount =  !!(options & RECOUNT);
-               nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
+               nr = parse_chunk(state, buf.buf + offset, buf.len - offset, 
patch);
                if (nr < 0)
                        break;
                if (apply_in_reverse)
                        reverse_patches(patch);
-               if (use_patch(patch)) {
+               if (use_patch(state, patch)) {
                        patch_stats(patch);
                        *listp = patch;
                        listp = &patch->next;
@@ -4516,6 +4529,7 @@ int cmd_apply(int argc, const char **argv, const char 
*prefix_)
        int is_not_gitdir = !startup_info->have_repository;
        int force_apply = 0;
        int options = 0;
+       struct apply_state state;
 
        const char *whitespace_option = NULL;
 
@@ -4588,15 +4602,17 @@ int cmd_apply(int argc, const char **argv, const char 
*prefix_)
                OPT_END()
        };
 
-       prefix = prefix_;
-       prefix_length = prefix ? strlen(prefix) : 0;
+       memset(&state, 0, sizeof(state));
+       state.prefix = prefix_;
+       state.prefix_length = state.prefix ? strlen(state.prefix) : 0;
+
        git_apply_config();
        if (apply_default_whitespace)
                parse_whitespace_option(apply_default_whitespace);
        if (apply_default_ignorewhitespace)
                parse_ignorewhitespace_option(apply_default_ignorewhitespace);
 
-       argc = parse_options(argc, argv, prefix, builtin_apply_options,
+       argc = parse_options(argc, argv, state.prefix, builtin_apply_options,
                        apply_usage, 0);
 
        if (apply_with_reject && threeway)
@@ -4627,23 +4643,25 @@ int cmd_apply(int argc, const char **argv, const char 
*prefix_)
                int fd;
 
                if (!strcmp(arg, "-")) {
-                       errs |= apply_patch(0, "<stdin>", options);
+                       errs |= apply_patch(&state, 0, "<stdin>", options);
                        read_stdin = 0;
                        continue;
-               } else if (0 < prefix_length)
-                       arg = prefix_filename(prefix, prefix_length, arg);
+               } else if (0 < state.prefix_length)
+                       arg = prefix_filename(state.prefix,
+                                             state.prefix_length,
+                                             arg);
 
                fd = open(arg, O_RDONLY);
                if (fd < 0)
                        die_errno(_("can't open patch '%s'"), arg);
                read_stdin = 0;
                set_default_whitespace_mode(whitespace_option);
-               errs |= apply_patch(fd, arg, options);
+               errs |= apply_patch(&state, fd, arg, options);
                close(fd);
        }
        set_default_whitespace_mode(whitespace_option);
        if (read_stdin)
-               errs |= apply_patch(0, "<stdin>", options);
+               errs |= apply_patch(&state, 0, "<stdin>", options);
        if (whitespace_error) {
                if (squelch_whitespace_errors &&
                    squelch_whitespace_errors < whitespace_error) {
-- 
2.8.0.rc1.49.gca61272

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to