From: Junio C Hamano Date: Wed, 12 Nov 2025 22:02:50 +0000 (-0800) Subject: diff: keep track of the type of the last line seen X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ced0561828271e8fc3fa2699754c5925969111b5;p=thirdparty%2Fgit.git diff: keep track of the type of the last line seen The "\ No newline at the end of the file" can come after any of the "-" (deleted preimage line), " " (unchanged line), or "+" (added postimage line). In later steps in this series, we will start treating a change that makes a file to end in an incomplete line as a whitespace error, and we would need to know what the previous line was when we react to "\ No newline" in the diff output. If the previous line was a context (i.e., unchanged) line, the file lacked the final newline before the change, and the change did not touch that line and left it still incomplete, so we do not want to warn in such a case. Teach fn_out_consume() function to keep track of what the previous line was, and prepare an otherwise empty switch statement to let us react differently to "\ No newline" based on that. Note that there is an existing curiosity (read: likely to be a bug) in the code that increments line number in the preimage file every time it sees a line with "\ No newline" on it, regardless of what the previous line was. I left it as-is, because it does not affect the main theme of this series, and more importantly, I do not think it matters, as these numbers are used only to compare them with blank_at_eof_in_{pre,post}image to issue a warning when we see more empty line was added at the end, but by definition, after we see "\ No newline at the end of the file" for an added line, we will not see an added line for the file. An independent audit to ensure that this curious increment can be safely removed would make a good #leftoverbits clean-up (we may even find some code that decrements this counter or over-increments the other quantity this counter is compared with that compensates the effect of this curious increment that hides a bug, in which case we may also need to remove them). Signed-off-by: Junio C Hamano --- diff --git a/diff.c b/diff.c index b9ef8550cc..ff8fc91f88 100644 --- a/diff.c +++ b/diff.c @@ -601,6 +601,7 @@ struct emit_callback { int blank_at_eof_in_postimage; int lno_in_preimage; int lno_in_postimage; + int last_line_kind; const char **label_path; struct diff_words_data *diff_words; struct diff_options *opt; @@ -2426,6 +2427,15 @@ static int fn_out_consume(void *priv, char *line, unsigned long len) break; case '\\': /* incomplete line at the end */ + switch (ecbdata->last_line_kind) { + case '+': + case '-': + case ' ': + break; + default: + BUG("fn_out_consume: '\\No newline' after unknown line (%c)", + ecbdata->last_line_kind); + } ecbdata->lno_in_preimage++; emit_diff_symbol(o, DIFF_SYMBOL_CONTEXT_INCOMPLETE, line, len, 0); @@ -2433,6 +2443,7 @@ static int fn_out_consume(void *priv, char *line, unsigned long len) default: BUG("fn_out_consume: unknown line '%s'", line); } + ecbdata->last_line_kind = line[0]; return 0; }