Stefan Beller <sbeller@xxxxxxxxxx> writes: > In a later patch, I want to propose an option to detect&color > moved lines in a diff, which cannot be done in a one-pass over > the diff. Instead we need to go over the whole diff twice, > because we cannot detect the first line of the two corresponding > lines (+ and -) that got moved. > > So to prepare the diff machinery for two pass algorithms > (i.e. buffer it all up and then operate on the result), > move all emissions to places, such that the only emitting > function is emit_line_0. > > This covers emit_rewrite_lines. > > Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> > --- > diff.c | 27 +++++++++++++++++++-------- > 1 file changed, 19 insertions(+), 8 deletions(-) > > diff --git a/diff.c b/diff.c > index 3dda9f3c8e..690794aeb8 100644 > --- a/diff.c > +++ b/diff.c > @@ -722,15 +722,25 @@ static void add_line_count(struct strbuf *out, int count) > static void emit_rewrite_lines(struct emit_callback *ecb, > int prefix, const char *data, int size) > { > - const char *endp = NULL; > - static const char *nneof = " No newline at end of file\n"; > const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET); > + struct strbuf sb = STRBUF_INIT; > > while (0 < size) { > int len; > > - endp = memchr(data, '\n', size); > - len = endp ? (endp - data + 1) : size; > + const char *endp = memchr(data, '\n', size); > + if (endp) > + len = endp - data + 1; > + else { > + while (0 < size) { > + strbuf_addch(&sb, *data); > + size -= len; > + data += len; > + } > + strbuf_addch(&sb, '\n'); > + data = sb.buf; > + len = sb.len; > + } > if (prefix != '+') { > ecb->lno_in_preimage++; > emit_del_line(reset, ecb, data, len); > @@ -741,12 +751,13 @@ static void emit_rewrite_lines(struct emit_callback *ecb, > size -= len; > data += len; > } > - if (!endp) { > + if (sb.len) { > + static const char *nneof = "\\ No newline at end of file\n"; > const char *context = diff_get_color(ecb->color_diff, > DIFF_CONTEXT); > - putc('\n', ecb->opt->file); > - emit_line(ecb->opt, context, reset, 1, '\\', > - nneof, strlen(nneof)); > + emit_line(ecb->opt, context, reset, 1, 0, > + nneof, strlen(nneof)); > + strbuf_release(&sb); The reason why we can lose the LF immediately after the incomplete line we found in the above loop is because the updated emit_line_0() adds LF if its input is an incomplete line? Even before this series started, emit_line_0() was already prepared to see a complete or incomplete line and emit the "reset" color after the optional EOL bytes at the end, so emit_line() and emit_{add,del}_line() calls throughout the code can pass the body of the line with or without the EOL and right things will happen. Sounds about right. > } > }