Merge branch 'js/apply-recount'
* js/apply-recount: Allow git-apply to recount the lines in a hunk (AKA recountdiff)
This commit is contained in:
commit
27158e463a
@ -12,7 +12,7 @@ SYNOPSIS
|
||||
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index]
|
||||
[--apply] [--no-add] [--build-fake-ancestor <file>] [-R | --reverse]
|
||||
[--allow-binary-replacement | --binary] [--reject] [-z]
|
||||
[-pNUM] [-CNUM] [--inaccurate-eof] [--cached]
|
||||
[-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
|
||||
[--whitespace=<nowarn|warn|fix|error|error-all>]
|
||||
[--exclude=PATH] [--verbose] [<patch>...]
|
||||
|
||||
@ -177,6 +177,11 @@ behavior:
|
||||
current patch being applied will be printed. This option will cause
|
||||
additional information to be reported.
|
||||
|
||||
--recount::
|
||||
Do not trust the line counts in the hunk headers, but infer them
|
||||
by inspecting the patch (e.g. after editing the patch without
|
||||
adjusting the hunk headers appropriately).
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
@ -154,6 +154,7 @@ struct patch {
|
||||
unsigned int is_binary:1;
|
||||
unsigned int is_copy:1;
|
||||
unsigned int is_rename:1;
|
||||
unsigned int recount:1;
|
||||
struct fragment *fragments;
|
||||
char *result;
|
||||
size_t resultsize;
|
||||
@ -890,6 +891,56 @@ static int parse_range(const char *line, int len, int offset, const char *expect
|
||||
return offset + ex;
|
||||
}
|
||||
|
||||
static void recount_diff(char *line, int size, struct fragment *fragment)
|
||||
{
|
||||
int oldlines = 0, newlines = 0, ret = 0;
|
||||
|
||||
if (size < 1) {
|
||||
warning("recount: ignore empty hunk");
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int len = linelen(line, size);
|
||||
size -= len;
|
||||
line += len;
|
||||
|
||||
if (size < 1)
|
||||
break;
|
||||
|
||||
switch (*line) {
|
||||
case ' ': case '\n':
|
||||
newlines++;
|
||||
/* fall through */
|
||||
case '-':
|
||||
oldlines++;
|
||||
continue;
|
||||
case '+':
|
||||
newlines++;
|
||||
continue;
|
||||
case '\\':
|
||||
break;
|
||||
case '@':
|
||||
ret = size < 3 || prefixcmp(line, "@@ ");
|
||||
break;
|
||||
case 'd':
|
||||
ret = size < 5 || prefixcmp(line, "diff ");
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (ret) {
|
||||
warning("recount: unexpected line: %.*s",
|
||||
(int)linelen(line, size), line);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fragment->oldlines = oldlines;
|
||||
fragment->newlines = newlines;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a unified diff fragment header of the
|
||||
* form "@@ -a,b +c,d @@"
|
||||
@ -1020,6 +1071,8 @@ static int parse_fragment(char *line, unsigned long size,
|
||||
offset = parse_fragment_header(line, len, fragment);
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
if (offset > 0 && patch->recount)
|
||||
recount_diff(line + offset, size - offset, fragment);
|
||||
oldlines = fragment->oldlines;
|
||||
newlines = fragment->newlines;
|
||||
leading = 0;
|
||||
@ -2971,7 +3024,10 @@ static void prefix_patches(struct patch *p)
|
||||
}
|
||||
}
|
||||
|
||||
static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
||||
#define INACCURATE_EOF (1<<0)
|
||||
#define RECOUNT (1<<1)
|
||||
|
||||
static int apply_patch(int fd, const char *filename, int options)
|
||||
{
|
||||
size_t offset;
|
||||
struct strbuf buf;
|
||||
@ -2989,7 +3045,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
|
||||
int nr;
|
||||
|
||||
patch = xcalloc(1, sizeof(*patch));
|
||||
patch->inaccurate_eof = inaccurate_eof;
|
||||
patch->inaccurate_eof = !!(options & INACCURATE_EOF);
|
||||
patch->recount = !!(options & RECOUNT);
|
||||
nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
|
||||
if (nr < 0)
|
||||
break;
|
||||
@ -3058,7 +3115,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
{
|
||||
int i;
|
||||
int read_stdin = 1;
|
||||
int inaccurate_eof = 0;
|
||||
int options = 0;
|
||||
int errs = 0;
|
||||
int is_not_gitdir;
|
||||
|
||||
@ -3076,7 +3133,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
int fd;
|
||||
|
||||
if (!strcmp(arg, "-")) {
|
||||
errs |= apply_patch(0, "<stdin>", inaccurate_eof);
|
||||
errs |= apply_patch(0, "<stdin>", options);
|
||||
read_stdin = 0;
|
||||
continue;
|
||||
}
|
||||
@ -3176,7 +3233,11 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--inaccurate-eof")) {
|
||||
inaccurate_eof = 1;
|
||||
options |= INACCURATE_EOF;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--recount")) {
|
||||
options |= RECOUNT;
|
||||
continue;
|
||||
}
|
||||
if (0 < prefix_length)
|
||||
@ -3187,12 +3248,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
die("can't open patch '%s': %s", arg, strerror(errno));
|
||||
read_stdin = 0;
|
||||
set_default_whitespace_mode(whitespace_option);
|
||||
errs |= apply_patch(fd, arg, inaccurate_eof);
|
||||
errs |= apply_patch(fd, arg, options);
|
||||
close(fd);
|
||||
}
|
||||
set_default_whitespace_mode(whitespace_option);
|
||||
if (read_stdin)
|
||||
errs |= apply_patch(0, "<stdin>", inaccurate_eof);
|
||||
errs |= apply_patch(0, "<stdin>", options);
|
||||
if (whitespace_error) {
|
||||
if (squelch_whitespace_errors &&
|
||||
squelch_whitespace_errors < whitespace_error) {
|
||||
|
@ -3,44 +3,36 @@
|
||||
# Copyright (c) 2005 Junio C Hamano
|
||||
#
|
||||
|
||||
test_description='git apply --stat --summary test.
|
||||
test_description='git apply --stat --summary test, with --recount
|
||||
|
||||
'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success \
|
||||
'rename' \
|
||||
'git apply --stat --summary <../t4100/t-apply-1.patch >current &&
|
||||
test_cmp ../t4100/t-apply-1.expect current'
|
||||
UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/'
|
||||
|
||||
test_expect_success \
|
||||
'copy' \
|
||||
'git apply --stat --summary <../t4100/t-apply-2.patch >current &&
|
||||
test_cmp ../t4100/t-apply-2.expect current'
|
||||
num=0
|
||||
while read title
|
||||
do
|
||||
num=$(( $num + 1 ))
|
||||
test_expect_success "$title" '
|
||||
git apply --stat --summary \
|
||||
<"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current &&
|
||||
test_cmp ../t4100/t-apply-$num.expect current
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'rewrite' \
|
||||
'git apply --stat --summary <../t4100/t-apply-3.patch >current &&
|
||||
test_cmp ../t4100/t-apply-3.expect current'
|
||||
|
||||
test_expect_success \
|
||||
'mode' \
|
||||
'git apply --stat --summary <../t4100/t-apply-4.patch >current &&
|
||||
test_cmp ../t4100/t-apply-4.expect current'
|
||||
|
||||
test_expect_success \
|
||||
'non git' \
|
||||
'git apply --stat --summary <../t4100/t-apply-5.patch >current &&
|
||||
test_cmp ../t4100/t-apply-5.expect current'
|
||||
|
||||
test_expect_success \
|
||||
'non git' \
|
||||
'git apply --stat --summary <../t4100/t-apply-6.patch >current &&
|
||||
test_cmp ../t4100/t-apply-6.expect current'
|
||||
|
||||
test_expect_success \
|
||||
'non git' \
|
||||
'git apply --stat --summary <../t4100/t-apply-7.patch >current &&
|
||||
test_cmp ../t4100/t-apply-7.expect current'
|
||||
test_expect_success "$title with recount" '
|
||||
sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" |
|
||||
git apply --recount --stat --summary >current &&
|
||||
test_cmp ../t4100/t-apply-$num.expect current
|
||||
'
|
||||
done <<\EOF
|
||||
rename
|
||||
copy
|
||||
rewrite
|
||||
mode
|
||||
non git (1)
|
||||
non git (2)
|
||||
non git (3)
|
||||
EOF
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user