mirror of
https://github.com/git/git.git
synced 2026-03-14 02:43:25 +01:00
Merge branch 'jc/apply' into next
* jc/apply: git-apply --verbose git-apply --reject: send rejects to .rej files.
This commit is contained in:
122
builtin-apply.c
122
builtin-apply.c
@@ -39,12 +39,13 @@ static int check;
|
||||
static int apply = 1;
|
||||
static int apply_in_reverse;
|
||||
static int apply_with_reject;
|
||||
static int apply_verbosely;
|
||||
static int no_add;
|
||||
static int show_index_info;
|
||||
static int line_termination = '\n';
|
||||
static unsigned long p_context = -1;
|
||||
static const char apply_usage[] =
|
||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
|
||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
|
||||
|
||||
static enum whitespace_eol {
|
||||
nowarn_whitespace,
|
||||
@@ -153,6 +154,24 @@ struct patch {
|
||||
struct patch *next;
|
||||
};
|
||||
|
||||
static void say_patch_name(FILE *output, const char *pre, struct patch *patch, const char *post)
|
||||
{
|
||||
fputs(pre, output);
|
||||
if (patch->old_name && patch->new_name &&
|
||||
strcmp(patch->old_name, patch->new_name)) {
|
||||
write_name_quoted(NULL, 0, patch->old_name, 1, output);
|
||||
fputs(" => ", output);
|
||||
write_name_quoted(NULL, 0, patch->new_name, 1, output);
|
||||
}
|
||||
else {
|
||||
const char *n = patch->new_name;
|
||||
if (!n)
|
||||
n = patch->old_name;
|
||||
write_name_quoted(NULL, 0, n, 1, output);
|
||||
}
|
||||
fputs(post, output);
|
||||
}
|
||||
|
||||
#define CHUNKSIZE (8192)
|
||||
#define SLOP (16)
|
||||
|
||||
@@ -1928,6 +1947,9 @@ static int check_patch_list(struct patch *patch)
|
||||
int error = 0;
|
||||
|
||||
for (prev_patch = NULL; patch ; patch = patch->next) {
|
||||
if (apply_verbosely)
|
||||
say_patch_name(stderr,
|
||||
"Checking patch ", patch, "...\n");
|
||||
error |= check_patch(patch, prev_patch);
|
||||
prev_patch = patch;
|
||||
}
|
||||
@@ -2242,36 +2264,69 @@ static void write_out_one_result(struct patch *patch, int phase)
|
||||
|
||||
static int write_out_one_reject(struct patch *patch)
|
||||
{
|
||||
FILE *rej;
|
||||
char namebuf[PATH_MAX];
|
||||
struct fragment *frag;
|
||||
int rejects = 0;
|
||||
int cnt = 0;
|
||||
|
||||
for (rejects = 0, frag = patch->fragments; frag; frag = frag->next) {
|
||||
for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
|
||||
if (!frag->rejected)
|
||||
continue;
|
||||
if (rejects == 0) {
|
||||
rejects = 1;
|
||||
printf("** Rejected hunk(s) for ");
|
||||
if (patch->old_name && patch->new_name &&
|
||||
strcmp(patch->old_name, patch->new_name)) {
|
||||
write_name_quoted(NULL, 0,
|
||||
patch->old_name, 1, stdout);
|
||||
fputs(" => ", stdout);
|
||||
write_name_quoted(NULL, 0,
|
||||
patch->new_name, 1, stdout);
|
||||
}
|
||||
else {
|
||||
const char *n = patch->new_name;
|
||||
if (!n)
|
||||
n = patch->old_name;
|
||||
write_name_quoted(NULL, 0, n, 1, stdout);
|
||||
}
|
||||
printf(" **\n");
|
||||
}
|
||||
printf("%.*s", frag->size, frag->patch);
|
||||
if (frag->patch[frag->size-1] != '\n')
|
||||
putchar('\n');
|
||||
cnt++;
|
||||
}
|
||||
return rejects;
|
||||
|
||||
if (!cnt) {
|
||||
if (apply_verbosely)
|
||||
say_patch_name(stderr,
|
||||
"Applied patch ", patch, " cleanly.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This should not happen, because a removal patch that leaves
|
||||
* contents are marked "rejected" at the patch level.
|
||||
*/
|
||||
if (!patch->new_name)
|
||||
die("internal error");
|
||||
|
||||
/* Say this even without --verbose */
|
||||
say_patch_name(stderr, "Applying patch ", patch, " with");
|
||||
fprintf(stderr, " %d rejects...\n", cnt);
|
||||
|
||||
cnt = strlen(patch->new_name);
|
||||
if (ARRAY_SIZE(namebuf) <= cnt + 5) {
|
||||
cnt = ARRAY_SIZE(namebuf) - 5;
|
||||
fprintf(stderr,
|
||||
"warning: truncating .rej filename to %.*s.rej",
|
||||
cnt - 1, patch->new_name);
|
||||
}
|
||||
memcpy(namebuf, patch->new_name, cnt);
|
||||
memcpy(namebuf + cnt, ".rej", 5);
|
||||
|
||||
rej = fopen(namebuf, "w");
|
||||
if (!rej)
|
||||
return error("cannot open %s: %s", namebuf, strerror(errno));
|
||||
|
||||
/* Normal git tools never deal with .rej, so do not pretend
|
||||
* this is a git patch by saying --git nor give extended
|
||||
* headers. While at it, maybe please "kompare" that wants
|
||||
* the trailing TAB and some garbage at the end of line ;-).
|
||||
*/
|
||||
fprintf(rej, "diff a/%s b/%s\t(rejected hunks)\n",
|
||||
patch->new_name, patch->new_name);
|
||||
for (cnt = 0, frag = patch->fragments;
|
||||
frag;
|
||||
cnt++, frag = frag->next) {
|
||||
if (!frag->rejected) {
|
||||
fprintf(stderr, "Hunk #%d applied cleanly.\n", cnt);
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "Rejected hunk #%d.\n", cnt);
|
||||
fprintf(rej, "%.*s", frag->size, frag->patch);
|
||||
if (frag->patch[frag->size-1] != '\n')
|
||||
fputc('\n', rej);
|
||||
}
|
||||
fclose(rej);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int write_out_results(struct patch *list, int skipped_patch)
|
||||
@@ -2288,16 +2343,9 @@ static int write_out_results(struct patch *list, int skipped_patch)
|
||||
while (l) {
|
||||
if (l->rejected)
|
||||
errs = 1;
|
||||
else
|
||||
else {
|
||||
write_out_one_result(l, phase);
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
if (apply_with_reject) {
|
||||
l = list;
|
||||
while (l) {
|
||||
if (!l->rejected) {
|
||||
if (write_out_one_reject(l))
|
||||
if (phase == 1 && write_out_one_reject(l))
|
||||
errs = 1;
|
||||
}
|
||||
l = l->next;
|
||||
@@ -2512,6 +2560,10 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
|
||||
apply = apply_with_reject = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--verbose")) {
|
||||
apply_verbosely = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--inaccurate-eof")) {
|
||||
inaccurate_eof = 1;
|
||||
continue;
|
||||
|
||||
@@ -23,6 +23,12 @@ test_expect_success setup '
|
||||
echo $i
|
||||
done >file1 &&
|
||||
git diff >patch.1 &&
|
||||
cat file1 >clean &&
|
||||
|
||||
for i in 1 E 2 3 4 5 6 7 8 9 10 11 12 C 13 14 15 16 17 18 19 20 F 21
|
||||
do
|
||||
echo $i
|
||||
done >expected &&
|
||||
|
||||
mv file1 file2 &&
|
||||
git update-index --add --remove file1 file2 &&
|
||||
@@ -51,27 +57,43 @@ test_expect_success 'apply without --reject should fail' '
|
||||
diff -u file1 saved.file1
|
||||
'
|
||||
|
||||
test_expect_success 'apply with --reject should fail but update the file' '
|
||||
test_expect_success 'apply without --reject should fail' '
|
||||
|
||||
cat saved.file1 >file1
|
||||
|
||||
if git apply --reject patch.1 >rejects
|
||||
if git apply --verbose patch.1
|
||||
then
|
||||
echo "succeeds with --reject?"
|
||||
echo "Eh? Why?"
|
||||
exit 1
|
||||
fi
|
||||
cat rejects
|
||||
for i in 1 E 2 3 4 5 6 7 8 9 10 11 12 C 13 14 15 16 17 18 19 20 F 21
|
||||
do
|
||||
echo $i
|
||||
done >expected.file1 &&
|
||||
|
||||
diff -u file1 expected.file1
|
||||
diff -u file1 saved.file1
|
||||
'
|
||||
|
||||
test_expect_success 'apply with --reject should fail but update the file' '
|
||||
|
||||
cat saved.file1 >file1
|
||||
cat saved.file1 >file1 &&
|
||||
rm -f file1.rej file2.rej &&
|
||||
|
||||
if git apply --reject patch.1
|
||||
then
|
||||
echo "succeeds with --reject?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
diff -u file1 expected &&
|
||||
|
||||
cat file1.rej &&
|
||||
|
||||
if test -f file2.rej
|
||||
then
|
||||
echo "file2 should not have been touched"
|
||||
exit 1
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success 'apply with --reject should fail but update the file' '
|
||||
|
||||
cat saved.file1 >file1 &&
|
||||
rm -f file1.rej file2.rej file2 &&
|
||||
|
||||
if git apply --reject patch.2 >rejects
|
||||
then
|
||||
@@ -79,18 +101,57 @@ test_expect_success 'apply with --reject should fail but update the file' '
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat rejects
|
||||
test -f file1 && {
|
||||
echo "file1 still exists?"
|
||||
exit 1
|
||||
}
|
||||
diff -u file2 expected &&
|
||||
|
||||
for i in 1 E 2 3 4 5 6 7 8 9 10 11 12 C 13 14 15 16 17 18 19 20 F 21
|
||||
do
|
||||
echo $i
|
||||
done >expected.file2 &&
|
||||
cat file2.rej &&
|
||||
|
||||
if test -f file1.rej
|
||||
then
|
||||
echo "file2 should not have been touched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'the same test with --verbose' '
|
||||
|
||||
cat saved.file1 >file1 &&
|
||||
rm -f file1.rej file2.rej file2 &&
|
||||
|
||||
if git apply --reject --verbose patch.2 >rejects
|
||||
then
|
||||
echo "succeeds with --reject?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test -f file1 && {
|
||||
echo "file1 still exists?"
|
||||
exit 1
|
||||
}
|
||||
diff -u file2 expected.file2
|
||||
diff -u file2 expected &&
|
||||
|
||||
cat file2.rej &&
|
||||
|
||||
if test -f file1.rej
|
||||
then
|
||||
echo "file2 should not have been touched"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'apply cleanly with --verbose' '
|
||||
|
||||
git cat-file -p HEAD:file1 >file1 &&
|
||||
rm -f file?.rej file2 &&
|
||||
|
||||
git apply --verbose patch.1 &&
|
||||
|
||||
diff -u file1 clean
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
Reference in New Issue
Block a user