Merge branch 'jk/avoid-unbounded-alloca'
[gitweb.git] / builtin / apply.c
index 8095026d33ba3583f428a0008c6c20a30c8e6769..ecb7f1b258cb802c934dc37f8d6af511e7b33ed1 100644 (file)
@@ -52,6 +52,10 @@ 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 */
@@ -114,8 +118,6 @@ struct apply_state {
        int applied_after_fixing_ws;
 };
 
-static int newfd = -1;
-
 static const char * const apply_usage[] = {
        N_("git apply [<options>] [<patch>...]"),
        NULL
@@ -462,7 +464,7 @@ static int is_dev_null(const char *str)
 #define TERM_SPACE     1
 #define TERM_TAB       2
 
-static int name_terminate(const char *name, int namelen, int c, int terminate)
+static int name_terminate(int c, int terminate)
 {
        if (c == ' ' && !(terminate & TERM_SPACE))
                return 0;
@@ -698,7 +700,7 @@ static char *find_name_common(struct apply_state *state,
                if (!end && isspace(c)) {
                        if (c == '\n')
                                break;
-                       if (name_terminate(start, line-start, c, terminate))
+                       if (name_terminate(c, terminate))
                                break;
                }
                line++;
@@ -4546,8 +4548,8 @@ static int apply_patch(struct apply_state *state,
                state->apply = 0;
 
        state->update_index = state->check_index && state->apply;
-       if (state->update_index && newfd < 0)
-               newfd = hold_locked_index(&lock_file, 1);
+       if (state->update_index && state->newfd < 0)
+               state->newfd = hold_locked_index(state->lock_file, 1);
 
        if (state->check_index) {
                if (read_cache() < 0)
@@ -4648,11 +4650,15 @@ static int option_parse_directory(const struct option *opt,
        return 0;
 }
 
-static void init_apply_state(struct apply_state *state, const char *prefix)
+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;
@@ -4705,15 +4711,85 @@ static void check_apply_state(struct apply_state *state, int force_apply)
        }
        if (state->check_index)
                state->unsafe_paths = 0;
+       if (!state->lock_file)
+               die("BUG: state->lock_file should not be NULL");
 }
 
-int cmd_apply(int argc, const char **argv, const char *prefix)
+static int apply_all_patches(struct apply_state *state,
+                            int argc,
+                            const char **argv,
+                            int options)
 {
        int i;
        int errs = 0;
+       int read_stdin = 1;
+
+       for (i = 0; i < argc; i++) {
+               const char *arg = argv[i];
+               int fd;
+
+               if (!strcmp(arg, "-")) {
+                       errs |= apply_patch(state, 0, "<stdin>", options);
+                       read_stdin = 0;
+                       continue;
+               } 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(state);
+               errs |= apply_patch(state, fd, arg, options);
+               close(fd);
+       }
+       set_default_whitespace_mode(state);
+       if (read_stdin)
+               errs |= apply_patch(state, 0, "<stdin>", options);
+
+       if (state->whitespace_error) {
+               if (state->squelch_whitespace_errors &&
+                   state->squelch_whitespace_errors < state->whitespace_error) {
+                       int squelched =
+                               state->whitespace_error - state->squelch_whitespace_errors;
+                       warning(Q_("squelched %d whitespace error",
+                                  "squelched %d 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->applied_after_fixing_ws && state->apply)
+                       warning("%d line%s applied after"
+                               " fixing whitespace errors.",
+                               state->applied_after_fixing_ws,
+                               state->applied_after_fixing_ws == 1 ? "" : "s");
+               else if (state->whitespace_error)
+                       warning(Q_("%d line adds whitespace errors.",
+                                  "%d lines add whitespace errors.",
+                                  state->whitespace_error),
+                               state->whitespace_error);
+       }
+
+       if (state->update_index) {
+               if (write_locked_index(&the_index, state->lock_file, COMMIT_LOCK))
+                       die(_("Unable to write new index file"));
+               state->newfd = -1;
+       }
+
+       return !!errs;
+}
+
+int cmd_apply(int argc, const char **argv, const char *prefix)
+{
        int force_apply = 0;
        int options = 0;
-       int read_stdin = 1;
+       int ret;
        struct apply_state state;
 
        struct option builtin_apply_options[] = {
@@ -4785,70 +4861,16 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
-       init_apply_state(&state, prefix);
+       init_apply_state(&state, prefix, &lock_file);
 
        argc = parse_options(argc, argv, state.prefix, builtin_apply_options,
                        apply_usage, 0);
 
        check_apply_state(&state, force_apply);
 
-       for (i = 0; i < argc; i++) {
-               const char *arg = argv[i];
-               int fd;
-
-               if (!strcmp(arg, "-")) {
-                       errs |= apply_patch(&state, 0, "<stdin>", options);
-                       read_stdin = 0;
-                       continue;
-               } 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(&state);
-               errs |= apply_patch(&state, fd, arg, options);
-               close(fd);
-       }
-       set_default_whitespace_mode(&state);
-       if (read_stdin)
-               errs |= apply_patch(&state, 0, "<stdin>", options);
-       if (state.whitespace_error) {
-               if (state.squelch_whitespace_errors &&
-                   state.squelch_whitespace_errors < state.whitespace_error) {
-                       int squelched =
-                               state.whitespace_error - state.squelch_whitespace_errors;
-                       warning(Q_("squelched %d whitespace error",
-                                  "squelched %d 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.applied_after_fixing_ws && state.apply)
-                       warning("%d line%s applied after"
-                               " fixing whitespace errors.",
-                               state.applied_after_fixing_ws,
-                               state.applied_after_fixing_ws == 1 ? "" : "s");
-               else if (state.whitespace_error)
-                       warning(Q_("%d line adds whitespace errors.",
-                                  "%d lines add whitespace errors.",
-                                  state.whitespace_error),
-                               state.whitespace_error);
-       }
-
-       if (state.update_index) {
-               if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-                       die(_("Unable to write new index file"));
-       }
+       ret = apply_all_patches(&state, argc, argv, options);
 
        clear_apply_state(&state);
 
-       return !!errs;
+       return ret;
 }