apply: pass apply state to build_fake_ancestor()
[gitweb.git] / apply.c
diff --git a/apply.c b/apply.c
index a9384390f17f1aaa2a6b635122db9897ef348283..a9a743cf9c7ec869aeb4d8f57b12e7bf638c202c 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -112,6 +112,11 @@ void clear_apply_state(struct apply_state *state)
        /* &state->fn_table is cleared at the end of apply_patch() */
 }
 
+static void mute_routine(const char *msg, va_list params)
+{
+       /* do nothing */
+}
+
 int check_apply_state(struct apply_state *state, int force_apply)
 {
        int is_not_gitdir = !startup_info->have_repository;
@@ -144,6 +149,13 @@ int check_apply_state(struct apply_state *state, int force_apply)
        if (!state->lock_file)
                return error("BUG: state->lock_file should not be NULL");
 
+       if (state->apply_verbosity <= verbosity_silent) {
+               state->saved_error_routine = get_error_routine();
+               state->saved_warn_routine = get_warn_routine();
+               set_error_routine(mute_routine);
+               set_warn_routine(mute_routine);
+       }
+
        return 0;
 }
 
@@ -4030,7 +4042,7 @@ static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20
 }
 
 /* Build an index that contains the just the files needed for a 3way merge */
-static int build_fake_ancestor(struct patch *list, const char *filename)
+static int build_fake_ancestor(struct apply_state *state, struct patch *list)
 {
        struct patch *patch;
        struct index_state result = { NULL };
@@ -4077,12 +4089,13 @@ static int build_fake_ancestor(struct patch *list, const char *filename)
                }
        }
 
-       hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
+       hold_lock_file_for_update(&lock, state->fake_ancestor, LOCK_DIE_ON_ERROR);
        res = write_locked_index(&result, &lock, COMMIT_LOCK);
        discard_index(&result);
 
        if (res)
-               return error("Could not write temporary index to %s", filename);
+               return error("Could not write temporary index to %s",
+                            state->fake_ancestor);
 
        return 0;
 }
@@ -4697,7 +4710,7 @@ static int apply_patch(struct apply_state *state,
        }
 
        if (state->fake_ancestor &&
-           build_fake_ancestor(list, state->fake_ancestor)) {
+           build_fake_ancestor(state, list)) {
                res = -128;
                goto end;
        }
@@ -4718,16 +4731,16 @@ static int apply_patch(struct apply_state *state,
        return res;
 }
 
-int apply_option_parse_exclude(const struct option *opt,
-                              const char *arg, int unset)
+static int apply_option_parse_exclude(const struct option *opt,
+                                     const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
        add_name_limit(state, arg, 1);
        return 0;
 }
 
-int apply_option_parse_include(const struct option *opt,
-                              const char *arg, int unset)
+static int apply_option_parse_include(const struct option *opt,
+                                     const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
        add_name_limit(state, arg, 0);
@@ -4735,9 +4748,9 @@ int apply_option_parse_include(const struct option *opt,
        return 0;
 }
 
-int apply_option_parse_p(const struct option *opt,
-                        const char *arg,
-                        int unset)
+static int apply_option_parse_p(const struct option *opt,
+                               const char *arg,
+                               int unset)
 {
        struct apply_state *state = opt->value;
        state->p_value = atoi(arg);
@@ -4745,8 +4758,8 @@ int apply_option_parse_p(const struct option *opt,
        return 0;
 }
 
-int apply_option_parse_space_change(const struct option *opt,
-                                   const char *arg, int unset)
+static int apply_option_parse_space_change(const struct option *opt,
+                                          const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
        if (unset)
@@ -4756,8 +4769,8 @@ int apply_option_parse_space_change(const struct option *opt,
        return 0;
 }
 
-int apply_option_parse_whitespace(const struct option *opt,
-                                 const char *arg, int unset)
+static int apply_option_parse_whitespace(const struct option *opt,
+                                        const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
        state->whitespace_option = arg;
@@ -4766,8 +4779,8 @@ int apply_option_parse_whitespace(const struct option *opt,
        return 0;
 }
 
-int apply_option_parse_directory(const struct option *opt,
-                                const char *arg, int unset)
+static int apply_option_parse_directory(const struct option *opt,
+                                       const char *arg, int unset)
 {
        struct apply_state *state = opt->value;
        strbuf_reset(&state->root);
@@ -4864,7 +4877,7 @@ int apply_all_patches(struct apply_state *state,
                state->newfd = -1;
        }
 
-       return !!errs;
+       res = !!errs;
 
 end:
        if (state->newfd >= 0) {
@@ -4872,5 +4885,89 @@ int apply_all_patches(struct apply_state *state,
                state->newfd = -1;
        }
 
+       if (state->apply_verbosity <= verbosity_silent) {
+               set_error_routine(state->saved_error_routine);
+               set_warn_routine(state->saved_warn_routine);
+       }
+
+       if (res > -1)
+               return res;
        return (res == -1 ? 1 : 128);
 }
+
+int apply_parse_options(int argc, const char **argv,
+                       struct apply_state *state,
+                       int *force_apply, int *options,
+                       const char * const *apply_usage)
+{
+       struct option builtin_apply_options[] = {
+               { OPTION_CALLBACK, 0, "exclude", state, N_("path"),
+                       N_("don't apply changes matching the given path"),
+                       0, apply_option_parse_exclude },
+               { OPTION_CALLBACK, 0, "include", state, N_("path"),
+                       N_("apply changes matching the given path"),
+                       0, apply_option_parse_include },
+               { OPTION_CALLBACK, 'p', NULL, state, N_("num"),
+                       N_("remove <num> leading slashes from traditional diff paths"),
+                       0, apply_option_parse_p },
+               OPT_BOOL(0, "no-add", &state->no_add,
+                       N_("ignore additions made by the patch")),
+               OPT_BOOL(0, "stat", &state->diffstat,
+                       N_("instead of applying the patch, output diffstat for the input")),
+               OPT_NOOP_NOARG(0, "allow-binary-replacement"),
+               OPT_NOOP_NOARG(0, "binary"),
+               OPT_BOOL(0, "numstat", &state->numstat,
+                       N_("show number of added and deleted lines in decimal notation")),
+               OPT_BOOL(0, "summary", &state->summary,
+                       N_("instead of applying the patch, output a summary for the input")),
+               OPT_BOOL(0, "check", &state->check,
+                       N_("instead of applying the patch, see if the patch is applicable")),
+               OPT_BOOL(0, "index", &state->check_index,
+                       N_("make sure the patch is applicable to the current index")),
+               OPT_BOOL(0, "cached", &state->cached,
+                       N_("apply a patch without touching the working tree")),
+               OPT_BOOL(0, "unsafe-paths", &state->unsafe_paths,
+                       N_("accept a patch that touches outside the working area")),
+               OPT_BOOL(0, "apply", force_apply,
+                       N_("also apply the patch (use with --stat/--summary/--check)")),
+               OPT_BOOL('3', "3way", &state->threeway,
+                        N_( "attempt three-way merge if a patch does not apply")),
+               OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor,
+                       N_("build a temporary index based on embedded index information")),
+               /* Think twice before adding "--nul" synonym to this */
+               OPT_SET_INT('z', NULL, &state->line_termination,
+                       N_("paths are separated with NUL character"), '\0'),
+               OPT_INTEGER('C', NULL, &state->p_context,
+                               N_("ensure at least <n> lines of context match")),
+               { OPTION_CALLBACK, 0, "whitespace", state, N_("action"),
+                       N_("detect new or modified lines that have whitespace errors"),
+                       0, apply_option_parse_whitespace },
+               { OPTION_CALLBACK, 0, "ignore-space-change", state, NULL,
+                       N_("ignore changes in whitespace when finding context"),
+                       PARSE_OPT_NOARG, apply_option_parse_space_change },
+               { OPTION_CALLBACK, 0, "ignore-whitespace", state, NULL,
+                       N_("ignore changes in whitespace when finding context"),
+                       PARSE_OPT_NOARG, apply_option_parse_space_change },
+               OPT_BOOL('R', "reverse", &state->apply_in_reverse,
+                       N_("apply the patch in reverse")),
+               OPT_BOOL(0, "unidiff-zero", &state->unidiff_zero,
+                       N_("don't expect at least one line of context")),
+               OPT_BOOL(0, "reject", &state->apply_with_reject,
+                       N_("leave the rejected hunks in corresponding *.rej files")),
+               OPT_BOOL(0, "allow-overlap", &state->allow_overlap,
+                       N_("allow overlapping hunks")),
+               OPT__VERBOSE(&state->apply_verbosity, N_("be verbose")),
+               OPT_BIT(0, "inaccurate-eof", options,
+                       N_("tolerate incorrectly detected missing new-line at the end of file"),
+                       APPLY_OPT_INACCURATE_EOF),
+               OPT_BIT(0, "recount", options,
+                       N_("do not trust the line counts in the hunk headers"),
+                       APPLY_OPT_RECOUNT),
+               { OPTION_CALLBACK, 0, "directory", state, N_("root"),
+                       N_("prepend <root> to all filenames"),
+                       0, apply_option_parse_directory },
+               OPT_END()
+       };
+
+       return parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0);
+}