Skip to content

Commit 8d8e3c6

Browse files
committed
diff: update the way rewrite diff handles incomplete lines
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>
1 parent 35925f1 commit 8d8e3c6

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

diff.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,6 @@ enum diff_symbol {
797797
DIFF_SYMBOL_CONTEXT_INCOMPLETE,
798798
DIFF_SYMBOL_PLUS,
799799
DIFF_SYMBOL_MINUS,
800-
DIFF_SYMBOL_NO_LF_EOF,
801800
DIFF_SYMBOL_CONTEXT_FRAGINFO,
802801
DIFF_SYMBOL_CONTEXT_MARKER,
803802
DIFF_SYMBOL_SEPARATOR
@@ -1352,7 +1351,6 @@ static void emit_line_ws_markup(struct diff_options *o,
13521351
static void emit_diff_symbol_from_struct(struct diff_options *o,
13531352
struct emitted_diff_symbol *eds)
13541353
{
1355-
static const char *nneof = " No newline at end of file\n";
13561354
const char *context, *reset, *set, *set_sign, *meta, *fraginfo;
13571355

13581356
enum diff_symbol s = eds->s;
@@ -1361,13 +1359,6 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
13611359
unsigned flags = eds->flags;
13621360

13631361
switch (s) {
1364-
case DIFF_SYMBOL_NO_LF_EOF:
1365-
context = diff_get_color_opt(o, DIFF_CONTEXT);
1366-
reset = diff_get_color_opt(o, DIFF_RESET);
1367-
putc('\n', o->file);
1368-
emit_line_0(o, context, NULL, 0, reset, '\\',
1369-
nneof, strlen(nneof));
1370-
break;
13711362
case DIFF_SYMBOL_SUBMODULE_HEADER:
13721363
case DIFF_SYMBOL_SUBMODULE_ERROR:
13731364
case DIFF_SYMBOL_SUBMODULE_PIPETHROUGH:
@@ -1786,22 +1777,38 @@ static void emit_rewrite_lines(struct emit_callback *ecbdata,
17861777
const char *endp = NULL;
17871778

17881779
while (0 < size) {
1789-
int len;
1780+
int len, plen;
1781+
char *pdata = NULL;
17901782

17911783
endp = memchr(data, '\n', size);
1792-
len = endp ? (endp - data + 1) : size;
1784+
1785+
if (endp) {
1786+
len = endp - data + 1;
1787+
plen = len;
1788+
} else {
1789+
len = size;
1790+
plen = len + 1;
1791+
pdata = xmalloc(plen + 2);
1792+
memcpy(pdata, data, len);
1793+
pdata[len] = '\n';
1794+
pdata[len + 1] = '\0';
1795+
}
17931796
if (prefix != '+') {
17941797
ecbdata->lno_in_preimage++;
1795-
emit_del_line(ecbdata, data, len);
1798+
emit_del_line(ecbdata, pdata ? pdata : data, plen);
17961799
} else {
17971800
ecbdata->lno_in_postimage++;
1798-
emit_add_line(ecbdata, data, len);
1801+
emit_add_line(ecbdata, pdata ? pdata : data, plen);
17991802
}
1803+
free(pdata);
18001804
size -= len;
18011805
data += len;
18021806
}
1803-
if (!endp)
1804-
emit_diff_symbol(ecbdata->opt, DIFF_SYMBOL_NO_LF_EOF, NULL, 0, 0);
1807+
if (!endp) {
1808+
static const char nneof[] = "\\ No newline at end of file\n";
1809+
ecbdata->last_line_kind = prefix;
1810+
emit_incomplete_line_marker(ecbdata, nneof, sizeof(nneof) - 1);
1811+
}
18051812
}
18061813

18071814
static void emit_rewrite_diff(const char *name_a,

0 commit comments

Comments
 (0)