git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH v3 07/12] diff: update the way rewrite diff handles incomplete lines
Date: Mon, 10 Nov 2025 16:04:46 -0800	[thread overview]
Message-ID: <20251111000451.2243195-8-gitster@pobox.com> (raw)
In-Reply-To: <20251111000451.2243195-1-gitster@pobox.com>

The diff_symbol based output framework uses one DIFF_SYMBOL_* enum
value per the kind of output lines of "git diff", which corresponds
to one output line from the xdiff machinery used internally.  Most
notably, DIFF_SYMBOL_PLUS and DIFF_SYMBOL_MINUS that correspond to
"+" and "-" lines are designed to always take a complete line, even
if the output from xdiff machinery may produce "\ No newline at the
end of file" immediately after them.

But this is not true in the rewrite-diff codepath, which completely
bypasses the xdiff machinery.  Since the code path feeds the bytes
directly from the payload to the output routines, the output layer
has to deal with an incomplete line with DIFF_SYMBOL_PLUS and
DIFF_SYMBOL_MINUS, which never would see an incomplete line in the
normal code paths.  This lack of final newline is compensated by an
ugly hack for a fabricated DIFF_SYMBOL_NO_LF_EOF token to inject an
extra newline to the output to simulate output coming from the xdiff
machinery.

Revamp the way the complete-rewrite code path feeds the lines to the
output layer by treating the last line of the pre/post image when it
is an incomplete line specially.

This lets us remove the DIFF_SYMBOL_NO_LF_EOF hack and use the usual
DIFF_SYMBOL_CONTEXT_INCOMPLETE code path, which will later learn how
to handle whitespace errors.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 diff.c | 37 ++++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/diff.c b/diff.c
index 67071136a4..c3fb3015d6 100644
--- a/diff.c
+++ b/diff.c
@@ -797,7 +797,6 @@ enum diff_symbol {
 	DIFF_SYMBOL_CONTEXT_INCOMPLETE,
 	DIFF_SYMBOL_PLUS,
 	DIFF_SYMBOL_MINUS,
-	DIFF_SYMBOL_NO_LF_EOF,
 	DIFF_SYMBOL_CONTEXT_FRAGINFO,
 	DIFF_SYMBOL_CONTEXT_MARKER,
 	DIFF_SYMBOL_SEPARATOR
@@ -1352,7 +1351,6 @@ static void emit_line_ws_markup(struct diff_options *o,
 static void emit_diff_symbol_from_struct(struct diff_options *o,
 					 struct emitted_diff_symbol *eds)
 {
-	static const char *nneof = " No newline at end of file\n";
 	const char *context, *reset, *set, *set_sign, *meta, *fraginfo;
 
 	enum diff_symbol s = eds->s;
@@ -1361,13 +1359,6 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
 	unsigned flags = eds->flags;
 
 	switch (s) {
-	case DIFF_SYMBOL_NO_LF_EOF:
-		context = diff_get_color_opt(o, DIFF_CONTEXT);
-		reset = diff_get_color_opt(o, DIFF_RESET);
-		putc('\n', o->file);
-		emit_line_0(o, context, NULL, 0, reset, '\\',
-			    nneof, strlen(nneof));
-		break;
 	case DIFF_SYMBOL_SUBMODULE_HEADER:
 	case DIFF_SYMBOL_SUBMODULE_ERROR:
 	case DIFF_SYMBOL_SUBMODULE_PIPETHROUGH:
@@ -1786,22 +1777,38 @@ static void emit_rewrite_lines(struct emit_callback *ecbdata,
 	const char *endp = NULL;
 
 	while (0 < size) {
-		int len;
+		int len, plen;
+		char *pdata = NULL;
 
 		endp = memchr(data, '\n', size);
-		len = endp ? (endp - data + 1) : size;
+
+		if (endp) {
+			len = endp - data + 1;
+			plen = len;
+		} else {
+			len = size;
+			plen = len + 1;
+			pdata = xmalloc(plen + 2);
+			memcpy(pdata, data, len);
+			pdata[len] = '\n';
+			pdata[len + 1] = '\0';
+		}
 		if (prefix != '+') {
 			ecbdata->lno_in_preimage++;
-			emit_del_line(ecbdata, data, len);
+			emit_del_line(ecbdata, pdata ? pdata : data, plen);
 		} else {
 			ecbdata->lno_in_postimage++;
-			emit_add_line(ecbdata, data, len);
+			emit_add_line(ecbdata, pdata ? pdata : data, plen);
 		}
+		free(pdata);
 		size -= len;
 		data += len;
 	}
-	if (!endp)
-		emit_diff_symbol(ecbdata->opt, DIFF_SYMBOL_NO_LF_EOF, NULL, 0, 0);
+	if (!endp) {
+		static const char nneof[] = "\\ No newline at end of file\n";
+		ecbdata->last_line_kind = prefix;
+		emit_incomplete_line_marker(ecbdata, nneof, sizeof(nneof) - 1);
+	}
 }
 
 static void emit_rewrite_diff(const char *name_a,
-- 
2.52.0-rc1-455-g30608eb744


  parent reply	other threads:[~2025-11-11  0:05 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-04  2:09 [PATCH 00/12] Incomplete lines Junio C Hamano
2025-11-04  2:09 ` [PATCH 01/12] whitespace: correct bit assignment comments Junio C Hamano
2025-11-04  2:09 ` [PATCH 02/12] diff: emit_line_ws_markup() if/else style fix Junio C Hamano
2025-11-04  2:09 ` [PATCH 03/12] diff: correct suppress_blank_empty hack Junio C Hamano
2025-11-04  2:09 ` [PATCH 04/12] diff: fix incorrect counting of line numbers Junio C Hamano
2025-11-10 14:54   ` Phillip Wood
2025-11-10 18:29     ` Junio C Hamano
2025-11-11 14:26       ` Phillip Wood
2025-11-11 14:37         ` Junio C Hamano
2025-11-04  2:09 ` [PATCH 05/12] diff: refactor output of incomplete line Junio C Hamano
2025-11-04  2:09 ` [PATCH 06/12] diff: call emit_callback ecbdata everywhere Junio C Hamano
2025-11-04  2:09 ` [PATCH 07/12] diff: update the way rewrite diff handles incomplete lines Junio C Hamano
2025-11-10 14:54   ` Phillip Wood
2025-11-10 18:33     ` Junio C Hamano
2025-11-04  2:09 ` [PATCH 08/12] apply: revamp the parsing of " Junio C Hamano
2025-11-04  2:09 ` [PATCH 09/12] whitespace: allocate a few more bits Junio C Hamano
2025-11-04  2:09 ` [PATCH 10/12] apply: check and fix incomplete lines Junio C Hamano
2025-11-04  2:09 ` [PATCH 11/12] diff: highlight and error out on " Junio C Hamano
2025-11-10 14:55   ` Phillip Wood
2025-11-10 18:38     ` Junio C Hamano
2025-11-10 23:56       ` D. Ben Knoble
2025-11-04  2:09 ` [PATCH 12/12] attr: enable incomplete-line whitespace error for this project Junio C Hamano
2025-11-10 14:55   ` Phillip Wood
2025-11-10 18:40     ` Junio C Hamano
2025-11-05 21:30 ` [PATCH v2 00/12] Incomplete lines Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 01/12] whitespace: correct bit assignment comments Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 02/12] diff: emit_line_ws_markup() if/else style fix Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 03/12] diff: correct suppress_blank_empty hack Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 04/12] diff: fix incorrect counting of line numbers Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 05/12] diff: refactor output of incomplete line Junio C Hamano
2025-11-10 10:06     ` Patrick Steinhardt
2025-11-10 17:58       ` Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 06/12] diff: call emit_callback ecbdata everywhere Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 07/12] diff: update the way rewrite diff handles incomplete lines Junio C Hamano
2025-11-10 10:06     ` Patrick Steinhardt
2025-11-10 18:14       ` Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 08/12] apply: revamp the parsing of " Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 09/12] whitespace: allocate a few more bits and define WS_INCOMPLETE_LINE Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 10/12] apply: check and fix incomplete lines Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 11/12] diff: highlight and error out on " Junio C Hamano
2025-11-05 21:30   ` [PATCH v2 12/12] attr: enable incomplete-line whitespace error for this project Junio C Hamano
2025-11-10 10:09   ` [PATCH v2 00/12] Incomplete lines Patrick Steinhardt
2025-11-10 14:53   ` Phillip Wood
2025-11-11  0:04   ` [PATCH v3 " Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 01/12] whitespace: correct bit assignment comments Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 02/12] diff: emit_line_ws_markup() if/else style fix Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 03/12] diff: correct suppress_blank_empty hack Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 04/12] diff: fix incorrect counting of line numbers Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 05/12] diff: refactor output of incomplete line Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 06/12] diff: call emit_callback ecbdata everywhere Junio C Hamano
2025-11-11  0:04     ` Junio C Hamano [this message]
2025-11-11  0:04     ` [PATCH v3 08/12] apply: revamp the parsing of incomplete lines Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 09/12] whitespace: allocate a few more bits and define WS_INCOMPLETE_LINE Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 10/12] apply: check and fix incomplete lines Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 11/12] diff: highlight and error out on " Junio C Hamano
2025-11-11  0:04     ` [PATCH v3 12/12] attr: enable incomplete-line whitespace error for this project Junio C Hamano
2025-11-11 14:29     ` [PATCH v3 00/12] Incomplete lines Phillip Wood
2025-11-12 22:02     ` [PATCH v4 " Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 01/12] whitespace: correct bit assignment comments Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 02/12] diff: emit_line_ws_markup() if/else style fix Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 03/12] diff: correct suppress_blank_empty hack Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 04/12] diff: keep track of the type of the last line seen Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 05/12] diff: refactor output of incomplete line Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 06/12] diff: call emit_callback ecbdata everywhere Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 07/12] diff: update the way rewrite diff handles incomplete lines Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 08/12] apply: revamp the parsing of " Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 09/12] whitespace: allocate a few more bits and define WS_INCOMPLETE_LINE Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 10/12] apply: check and fix incomplete lines Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 11/12] diff: highlight and error out on " Junio C Hamano
2025-11-12 22:02       ` [PATCH v4 12/12] attr: enable incomplete-line whitespace error for this project Junio C Hamano
2025-11-14 10:24       ` [PATCH v4 00/12] Incomplete lines Phillip Wood
2025-11-14 16:25         ` Junio C Hamano
2025-11-23  2:35           ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251111000451.2243195-8-gitster@pobox.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).