apply: fix new-style empty context line triggering incomplete-line check

A new-style unified context diff represents an empty context line with an empty line (instead of a line with a single SP on it). The code to check whitespace errors in an incoming patch is designed to omit the first byte of a line (typically SP, "-", or "+") and pass the remainder of the line to the whitespace checker. Usually we do not pass a context line to the whitespace error checker, but when we are correcting errors, we do. This "remove the first byte and send the remainder" strategy of checking a line ended up sending a zero-length string to the whitespace checker when seeing a new-style empty context line, which caused the whitespace checker to say "ah, you do not even have a newline at the end!", leading to an "incomplete line" in the middle of the patch! Fix this by pretending that we got a traditional empty context line when we drive the whitespace checker. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Mar 17, 2026 at 11:01 UTC afdb4c665f664e04c0f68c930ad50e5b05be71e1
2 files changed +26 -2
apply.c
+10 -2
@@ -1796,8 +1796,16 @@ static int parse_fragment(struct apply_state *state,
1796 trailing++;
1797 check_old_for_crlf(patch, line, len);
1798 if (!state->apply_in_reverse &&
1799 - state->ws_error_action == correct_ws_error)
1800 - check_whitespace(state, line, len, patch->ws_rule);
1799 + state->ws_error_action == correct_ws_error) {
1800 + const char *test_line = line;
1801 + int test_len = len;
1802 + if (*line == '\n') {
1803 + test_line = " \n";
1804 + test_len = 2;
1805 + }
1806 + check_whitespace(state, test_line, test_len,
1807 + patch->ws_rule);
1808 + }
1809 break;
1810 case '-':
1811 if (!state->apply_in_reverse)
t/t4124-apply-ws-rule.sh
+16
@@ -561,6 +561,22 @@ test_expect_success 'check incomplete lines (setup)' '
561 git config core.whitespace incomplete-line
562 '
563
564 +test_expect_success 'no incomplete context line (not an error)' '
565 + test_when_finished "rm -f sample*-i patch patch-new target" &&
566 + test_write_lines 1 2 3 "" 4 5 >sample-i &&
567 + test_write_lines 1 2 3 "" 0 5 >sample2-i &&
568 + cat sample-i >target &&
569 + git add target &&
570 + cat sample2-i >target &&
571 + git diff-files -p target >patch &&
572 + sed -e "s/^ $//" <patch >patch-new &&
573 +
574 + cat sample-i >target &&
575 + git apply --whitespace=fix <patch-new 2>error &&
576 + test_cmp sample2-i target &&
577 + test_must_be_empty error
578 +'
579 +
580 test_expect_success 'incomplete context line (not an error)' '
581 (test_write_lines 1 2 3 4 5 && printf 6) >sample-i &&
582 (test_write_lines 1 2 3 0 5 && printf 6) >sample2-i &&