Skip to content

Commit fd3f7f6

Browse files
dschogitster
authored andcommitted
add -p: gracefully handle unparseable hunk headers in colored diffs
In https://lore.kernel.org/git/[email protected], Phillipe Blain reported that the built-in `git add -p` command fails when asked to use [`diff-so-fancy`][diff-so-fancy] to colorize the diff. The reason is that this tool produces colored diffs with a hunk header that does not contain any parseable `@@ ... @@` line range information, and therefore we cannot detect any part in that header that comes after the line range. As proposed by Phillip Wood, let's take that for a clear indicator that we should show the hunk headers verbatim. This is what the Perl version of the interactive `add` command did, too. [diff-so-fancy]: https://github.com/so-fancy/diff-so-fancy Reported-by: Philippe Blain <[email protected]> Helped-by: Phillip Wood <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b6633a0 commit fd3f7f6

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

add-patch.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ struct hunk_header {
238238
* include the newline.
239239
*/
240240
size_t extra_start, extra_end, colored_extra_start, colored_extra_end;
241+
unsigned suppress_colored_line_range:1;
241242
};
242243

243244
struct hunk {
@@ -358,15 +359,14 @@ static int parse_hunk_header(struct add_p_state *s, struct hunk *hunk)
358359
if (!eol)
359360
eol = s->colored.buf + s->colored.len;
360361
p = memmem(line, eol - line, "@@ -", 4);
361-
if (!p)
362-
return error(_("could not parse colored hunk header '%.*s'"),
363-
(int)(eol - line), line);
364-
p = memmem(p + 4, eol - p - 4, " @@", 3);
365-
if (!p)
366-
return error(_("could not parse colored hunk header '%.*s'"),
367-
(int)(eol - line), line);
362+
if (p && (p = memmem(p + 4, eol - p - 4, " @@", 3))) {
363+
header->colored_extra_start = p + 3 - s->colored.buf;
364+
} else {
365+
/* could not parse colored hunk header, leave as-is */
366+
header->colored_extra_start = hunk->colored_start;
367+
header->suppress_colored_line_range = 1;
368+
}
368369
hunk->colored_start = eol - s->colored.buf + (*eol == '\n');
369-
header->colored_extra_start = p + 3 - s->colored.buf;
370370
header->colored_extra_end = hunk->colored_start;
371371

372372
return 0;
@@ -659,6 +659,15 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
659659
if (!colored) {
660660
p = s->plain.buf + header->extra_start;
661661
len = header->extra_end - header->extra_start;
662+
} else if (header->suppress_colored_line_range) {
663+
strbuf_add(out,
664+
s->colored.buf + header->colored_extra_start,
665+
header->colored_extra_end -
666+
header->colored_extra_start);
667+
668+
strbuf_add(out, s->colored.buf + hunk->colored_start,
669+
hunk->colored_end - hunk->colored_start);
670+
return;
662671
} else {
663672
strbuf_addstr(out, s->s.fraginfo_color);
664673
p = s->colored.buf + header->colored_extra_start;

t/t3701-add-interactive.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,16 @@ test_expect_success 'detect bogus diffFilter output' '
767767
grep "mismatched output" output
768768
'
769769

770+
test_expect_success 'handle iffy colored hunk headers' '
771+
git reset --hard &&
772+
773+
echo content >test &&
774+
printf n >n &&
775+
force_color git -c interactive.diffFilter="sed s/.*@@.*/XX/" \
776+
add -p >output 2>&1 <n &&
777+
grep "^XX$" output
778+
'
779+
770780
test_expect_success 'diff.algorithm is passed to `git diff-files`' '
771781
git reset --hard &&
772782

0 commit comments

Comments
 (0)