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