apply: make it possible to silently apply

This changes 'int apply_verbosely' into 'enum apply_verbosity', and
changes the possible values of the variable from a bool to
a tristate.

The previous 'false' state is changed into 'verbosity_normal'.
The previous 'true' state is changed into 'verbosity_verbose'.

The new added state is 'verbosity_silent'. It should prevent
anything to be printed on both stderr and stdout.

This is needed because `git am` wants to first call apply
functionality silently, if it can then fall back on 3-way merge
in case of error.

Printing on stdout, and calls to warning() or error() are not
taken care of in this patch, as that will be done in following
patches.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Christian Couder 2016-09-04 22:18:25 +02:00 committed by Junio C Hamano
parent 90875eca5a
commit a46160d27e
3 changed files with 48 additions and 24 deletions

46
apply.c
View File

@ -125,8 +125,11 @@ int check_apply_state(struct apply_state *state, int force_apply)
return error(_("--3way outside a repository")); return error(_("--3way outside a repository"));
state->check_index = 1; state->check_index = 1;
} }
if (state->apply_with_reject) if (state->apply_with_reject) {
state->apply = state->apply_verbosely = 1; state->apply = 1;
if (state->apply_verbosity == verbosity_normal)
state->apply_verbosity = verbosity_verbose;
}
if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor)) if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor))
state->apply = 0; state->apply = 0;
if (state->check_index && is_not_gitdir) if (state->check_index && is_not_gitdir)
@ -1620,6 +1623,7 @@ static void record_ws_error(struct apply_state *state,
return; return;
err = whitespace_error_string(result); err = whitespace_error_string(result);
if (state->apply_verbosity > verbosity_silent)
fprintf(stderr, "%s:%d: %s.\n%.*s\n", fprintf(stderr, "%s:%d: %s.\n%.*s\n",
state->patch_input_file, linenr, err, len, line); state->patch_input_file, linenr, err, len, line);
free(err); free(err);
@ -1816,7 +1820,7 @@ static int parse_single_patch(struct apply_state *state,
return error(_("new file %s depends on old contents"), patch->new_name); return error(_("new file %s depends on old contents"), patch->new_name);
if (0 < patch->is_delete && newlines) if (0 < patch->is_delete && newlines)
return error(_("deleted file %s still has contents"), patch->old_name); return error(_("deleted file %s still has contents"), patch->old_name);
if (!patch->is_delete && !newlines && context) if (!patch->is_delete && !newlines && context && state->apply_verbosity > verbosity_silent)
fprintf_ln(stderr, fprintf_ln(stderr,
_("** warning: " _("** warning: "
"file %s becomes empty but is not deleted"), "file %s becomes empty but is not deleted"),
@ -2911,7 +2915,7 @@ static int apply_one_fragment(struct apply_state *state,
/* Ignore it, we already handled it */ /* Ignore it, we already handled it */
break; break;
default: default:
if (state->apply_verbosely) if (state->apply_verbosity > verbosity_normal)
error(_("invalid start of line: '%c'"), first); error(_("invalid start of line: '%c'"), first);
applied_pos = -1; applied_pos = -1;
goto out; goto out;
@ -3026,7 +3030,7 @@ static int apply_one_fragment(struct apply_state *state,
state->apply = 0; state->apply = 0;
} }
if (state->apply_verbosely && applied_pos != pos) { if (state->apply_verbosity > verbosity_normal && applied_pos != pos) {
int offset = applied_pos - pos; int offset = applied_pos - pos;
if (state->apply_in_reverse) if (state->apply_in_reverse)
offset = 0 - offset; offset = 0 - offset;
@ -3041,14 +3045,14 @@ static int apply_one_fragment(struct apply_state *state,
* Warn if it was necessary to reduce the number * Warn if it was necessary to reduce the number
* of context lines. * of context lines.
*/ */
if ((leading != frag->leading) || if ((leading != frag->leading ||
(trailing != frag->trailing)) trailing != frag->trailing) && state->apply_verbosity > verbosity_silent)
fprintf_ln(stderr, _("Context reduced to (%ld/%ld)" fprintf_ln(stderr, _("Context reduced to (%ld/%ld)"
" to apply fragment at %d"), " to apply fragment at %d"),
leading, trailing, applied_pos+1); leading, trailing, applied_pos+1);
update_image(state, img, applied_pos, &preimage, &postimage); update_image(state, img, applied_pos, &preimage, &postimage);
} else { } else {
if (state->apply_verbosely) if (state->apply_verbosity > verbosity_normal)
error(_("while searching for:\n%.*s"), error(_("while searching for:\n%.*s"),
(int)(old - oldlines), oldlines); (int)(old - oldlines), oldlines);
} }
@ -3539,6 +3543,7 @@ static int try_threeway(struct apply_state *state,
read_blob_object(&buf, pre_sha1, patch->old_mode)) read_blob_object(&buf, pre_sha1, patch->old_mode))
return error("repository lacks the necessary blob to fall back on 3-way merge."); return error("repository lacks the necessary blob to fall back on 3-way merge.");
if (state->apply_verbosity > verbosity_silent)
fprintf(stderr, "Falling back to three-way merge...\n"); fprintf(stderr, "Falling back to three-way merge...\n");
img = strbuf_detach(&buf, &len); img = strbuf_detach(&buf, &len);
@ -3569,7 +3574,9 @@ static int try_threeway(struct apply_state *state,
status = three_way_merge(image, patch->new_name, status = three_way_merge(image, patch->new_name,
pre_sha1, our_sha1, post_sha1); pre_sha1, our_sha1, post_sha1);
if (status < 0) { if (status < 0) {
fprintf(stderr, "Failed to fall back on three-way merge...\n"); if (state->apply_verbosity > verbosity_silent)
fprintf(stderr,
"Failed to fall back on three-way merge...\n");
return status; return status;
} }
@ -3581,9 +3588,15 @@ static int try_threeway(struct apply_state *state,
hashcpy(patch->threeway_stage[0].hash, pre_sha1); hashcpy(patch->threeway_stage[0].hash, pre_sha1);
hashcpy(patch->threeway_stage[1].hash, our_sha1); hashcpy(patch->threeway_stage[1].hash, our_sha1);
hashcpy(patch->threeway_stage[2].hash, post_sha1); hashcpy(patch->threeway_stage[2].hash, post_sha1);
fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name); if (state->apply_verbosity > verbosity_silent)
fprintf(stderr,
"Applied patch to '%s' with conflicts.\n",
patch->new_name);
} else { } else {
fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name); if (state->apply_verbosity > verbosity_silent)
fprintf(stderr,
"Applied patch to '%s' cleanly.\n",
patch->new_name);
} }
return 0; return 0;
} }
@ -3956,7 +3969,7 @@ static int check_patch_list(struct apply_state *state, struct patch *patch)
prepare_fn_table(state, patch); prepare_fn_table(state, patch);
while (patch) { while (patch) {
int res; int res;
if (state->apply_verbosely) if (state->apply_verbosity > verbosity_normal)
say_patch_name(stderr, say_patch_name(stderr,
_("Checking patch %s..."), patch); _("Checking patch %s..."), patch);
res = check_patch(state, patch); res = check_patch(state, patch);
@ -4472,7 +4485,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
} }
if (!cnt) { if (!cnt) {
if (state->apply_verbosely) if (state->apply_verbosity > verbosity_normal)
say_patch_name(stderr, say_patch_name(stderr,
_("Applied patch %s cleanly."), patch); _("Applied patch %s cleanly."), patch);
return 0; return 0;
@ -4489,6 +4502,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
"Applying patch %%s with %d rejects...", "Applying patch %%s with %d rejects...",
cnt), cnt),
cnt); cnt);
if (state->apply_verbosity > verbosity_silent)
say_patch_name(stderr, sb.buf, patch); say_patch_name(stderr, sb.buf, patch);
strbuf_release(&sb); strbuf_release(&sb);
@ -4516,9 +4530,11 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
frag; frag;
cnt++, frag = frag->next) { cnt++, frag = frag->next) {
if (!frag->rejected) { if (!frag->rejected) {
if (state->apply_verbosity > verbosity_silent)
fprintf_ln(stderr, _("Hunk #%d applied cleanly."), cnt); fprintf_ln(stderr, _("Hunk #%d applied cleanly."), cnt);
continue; continue;
} }
if (state->apply_verbosity > verbosity_silent)
fprintf_ln(stderr, _("Rejected hunk #%d."), cnt); fprintf_ln(stderr, _("Rejected hunk #%d."), cnt);
fprintf(rej, "%.*s", frag->size, frag->patch); fprintf(rej, "%.*s", frag->size, frag->patch);
if (frag->patch[frag->size-1] != '\n') if (frag->patch[frag->size-1] != '\n')
@ -4568,8 +4584,10 @@ static int write_out_results(struct apply_state *state, struct patch *list)
struct string_list_item *item; struct string_list_item *item;
string_list_sort(&cpath); string_list_sort(&cpath);
if (state->apply_verbosity > verbosity_silent) {
for_each_string_list_item(item, &cpath) for_each_string_list_item(item, &cpath)
fprintf(stderr, "U %s\n", item->string); fprintf(stderr, "U %s\n", item->string);
}
string_list_clear(&cpath, 0); string_list_clear(&cpath, 0);
rerere(0); rerere(0);
@ -4626,7 +4644,7 @@ static int apply_patch(struct apply_state *state,
listp = &patch->next; listp = &patch->next;
} }
else { else {
if (state->apply_verbosely) if (state->apply_verbosity > verbosity_normal)
say_patch_name(stderr, _("Skipped patch '%s'."), patch); say_patch_name(stderr, _("Skipped patch '%s'."), patch);
free_patch(patch); free_patch(patch);
skipped_patch++; skipped_patch++;

View File

@ -13,6 +13,12 @@ enum apply_ws_ignore {
ignore_ws_change ignore_ws_change
}; };
enum apply_verbosity {
verbosity_silent = -1,
verbosity_normal = 0,
verbosity_verbose = 1
};
/* /*
* We need to keep track of how symlinks in the preimage are * We need to keep track of how symlinks in the preimage are
* manipulated by the patches. A patch to add a/b/c where a/b * manipulated by the patches. A patch to add a/b/c where a/b
@ -51,13 +57,13 @@ struct apply_state {
int allow_overlap; int allow_overlap;
int apply_in_reverse; int apply_in_reverse;
int apply_with_reject; int apply_with_reject;
int apply_verbosely;
int no_add; int no_add;
int threeway; int threeway;
int unidiff_zero; int unidiff_zero;
int unsafe_paths; int unsafe_paths;
/* Other non boolean parameters */ /* Other non boolean parameters */
enum apply_verbosity apply_verbosity;
const char *fake_ancestor; const char *fake_ancestor;
const char *patch_input_file; const char *patch_input_file;
int line_termination; int line_termination;

View File

@ -74,7 +74,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
N_("leave the rejected hunks in corresponding *.rej files")), N_("leave the rejected hunks in corresponding *.rej files")),
OPT_BOOL(0, "allow-overlap", &state.allow_overlap, OPT_BOOL(0, "allow-overlap", &state.allow_overlap,
N_("allow overlapping hunks")), N_("allow overlapping hunks")),
OPT__VERBOSE(&state.apply_verbosely, N_("be verbose")), OPT__VERBOSE(&state.apply_verbosity, N_("be verbose")),
OPT_BIT(0, "inaccurate-eof", &options, OPT_BIT(0, "inaccurate-eof", &options,
N_("tolerate incorrectly detected missing new-line at the end of file"), N_("tolerate incorrectly detected missing new-line at the end of file"),
APPLY_OPT_INACCURATE_EOF), APPLY_OPT_INACCURATE_EOF),