Merge branch 'js/add-p-diff-parsing-fix'
Those who use diff-so-fancy as the diff-filter noticed a regression or two in the code that parses the diff output in the built-in version of "add -p", which has been corrected. * js/add-p-diff-parsing-fix: add -p: ignore dirty submodules add -p: gracefully handle unparseable hunk headers in colored diffs add -p: detect more mismatches between plain vs colored diffs
This commit is contained in:
commit
fb094cb583
33
add-patch.c
33
add-patch.c
@ -238,6 +238,7 @@ struct hunk_header {
|
||||
* include the newline.
|
||||
*/
|
||||
size_t extra_start, extra_end, colored_extra_start, colored_extra_end;
|
||||
unsigned suppress_colored_line_range:1;
|
||||
};
|
||||
|
||||
struct hunk {
|
||||
@ -358,15 +359,14 @@ static int parse_hunk_header(struct add_p_state *s, struct hunk *hunk)
|
||||
if (!eol)
|
||||
eol = s->colored.buf + s->colored.len;
|
||||
p = memmem(line, eol - line, "@@ -", 4);
|
||||
if (!p)
|
||||
return error(_("could not parse colored hunk header '%.*s'"),
|
||||
(int)(eol - line), line);
|
||||
p = memmem(p + 4, eol - p - 4, " @@", 3);
|
||||
if (!p)
|
||||
return error(_("could not parse colored hunk header '%.*s'"),
|
||||
(int)(eol - line), line);
|
||||
if (p && (p = memmem(p + 4, eol - p - 4, " @@", 3))) {
|
||||
header->colored_extra_start = p + 3 - s->colored.buf;
|
||||
} else {
|
||||
/* could not parse colored hunk header, leave as-is */
|
||||
header->colored_extra_start = hunk->colored_start;
|
||||
header->suppress_colored_line_range = 1;
|
||||
}
|
||||
hunk->colored_start = eol - s->colored.buf + (*eol == '\n');
|
||||
header->colored_extra_start = p + 3 - s->colored.buf;
|
||||
header->colored_extra_end = hunk->colored_start;
|
||||
|
||||
return 0;
|
||||
@ -419,7 +419,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
|
||||
}
|
||||
color_arg_index = args.nr;
|
||||
/* Use `--no-color` explicitly, just in case `diff.color = always`. */
|
||||
strvec_pushl(&args, "--no-color", "-p", "--", NULL);
|
||||
strvec_pushl(&args, "--no-color", "--ignore-submodules=dirty", "-p",
|
||||
"--", NULL);
|
||||
for (i = 0; i < ps->nr; i++)
|
||||
strvec_push(&args, ps->items[i].original);
|
||||
|
||||
@ -592,7 +593,10 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
|
||||
if (colored_eol)
|
||||
colored_p = colored_eol + 1;
|
||||
else if (p != pend)
|
||||
/* colored shorter than non-colored? */
|
||||
/* non-colored has more lines? */
|
||||
goto mismatched_output;
|
||||
else if (colored_p == colored_pend)
|
||||
/* last line has no matching colored one? */
|
||||
goto mismatched_output;
|
||||
else
|
||||
colored_p = colored_pend;
|
||||
@ -656,6 +660,15 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
|
||||
if (!colored) {
|
||||
p = s->plain.buf + header->extra_start;
|
||||
len = header->extra_end - header->extra_start;
|
||||
} else if (header->suppress_colored_line_range) {
|
||||
strbuf_add(out,
|
||||
s->colored.buf + header->colored_extra_start,
|
||||
header->colored_extra_end -
|
||||
header->colored_extra_start);
|
||||
|
||||
strbuf_add(out, s->colored.buf + hunk->colored_start,
|
||||
hunk->colored_end - hunk->colored_start);
|
||||
return;
|
||||
} else {
|
||||
strbuf_addstr(out, s->s.fraginfo_color);
|
||||
p = s->colored.buf + header->colored_extra_start;
|
||||
|
@ -761,9 +761,20 @@ test_expect_success 'detect bogus diffFilter output' '
|
||||
git reset --hard &&
|
||||
|
||||
echo content >test &&
|
||||
test_config interactive.diffFilter "sed 1d" &&
|
||||
test_config interactive.diffFilter "sed 6d" &&
|
||||
printf y >y &&
|
||||
force_color test_must_fail git add -p <y
|
||||
force_color test_must_fail git add -p <y >output 2>&1 &&
|
||||
grep "mismatched output" output
|
||||
'
|
||||
|
||||
test_expect_success 'handle iffy colored hunk headers' '
|
||||
git reset --hard &&
|
||||
|
||||
echo content >test &&
|
||||
printf n >n &&
|
||||
force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \
|
||||
add -p >output 2>&1 <n &&
|
||||
grep "^XX$" output
|
||||
'
|
||||
|
||||
test_expect_success 'handle very large filtered diff' '
|
||||
@ -944,6 +955,18 @@ test_expect_success 'status ignores dirty submodules (except HEAD)' '
|
||||
! grep dirty-otherwise output
|
||||
'
|
||||
|
||||
test_expect_success 'handle submodules' '
|
||||
echo 123 >>for-submodules/dirty-otherwise/initial.t &&
|
||||
|
||||
force_color git -C for-submodules add -p dirty-otherwise >output 2>&1 &&
|
||||
grep "No changes" output &&
|
||||
|
||||
force_color git -C for-submodules add -p dirty-head >output 2>&1 <y &&
|
||||
git -C for-submodules ls-files --stage dirty-head >actual &&
|
||||
rev="$(git -C for-submodules/dirty-head rev-parse HEAD)" &&
|
||||
grep "$rev" actual
|
||||
'
|
||||
|
||||
test_expect_success 'set up pathological context' '
|
||||
git reset --hard &&
|
||||
test_write_lines a a a a a a a a a a a >a &&
|
||||
|
Loading…
Reference in New Issue
Block a user