Download raw body.
diff.git: Fix ed script output
On Tue, Sep 06, 2022 at 01:33:37PM +0100, Tom Jones wrote:
> The rc check is happening in the look twice, once for diff_output_lines
> and once for the fprintf, so it doesn't need to happen here again.
>
> I have removed that and made the check for printf to be < 0.
This patch looks very good to me.
However, it breaks a regression test. Can you reproduce this failure?
And, if so, do you have time to figure out why it breaks?
$ make -C test
[...]
cmp: EOF on expect123.diff
FAIL: verify.expect123.diff != expect123.diff
OK: arraylist_test
OK: results_test
Tests failed:
FAIL: verify.expect123.diff != expect123.diff
*** Error 1 in /home/stsp/src/diff/test (Makefile:7 'verify')
$
> diff --git a/lib/diff_output_edscript.c b/lib/diff_output_edscript.c
> index 42d4d5b..e7c8353 100644
> --- a/lib/diff_output_edscript.c
> +++ b/lib/diff_output_edscript.c
> @@ -32,9 +32,9 @@ static int
> output_edscript_chunk(struct diff_output_info *outinfo,
> FILE *dest, const struct diff_input_info *info,
> const struct diff_result *result,
> - struct diff_chunk_context *cc)
> + struct diff_chunk_context *cc, off_t *outoff)
> {
> - off_t outoff = 0, *offp;
> + off_t *offp;
> int left_start, left_len, right_start, right_len;
> int rc;
>
> @@ -81,17 +81,10 @@ output_edscript_chunk(struct diff_output_info *outinfo,
> }
> } else {
> /* change */
> - if (left_len == 1 && right_len == 1) {
> - rc = fprintf(dest, "%dc%d\n", left_start, right_start);
> - } else if (left_len == 1) {
> - rc = fprintf(dest, "%dc%d,%d\n", left_start,
> - right_start, cc->right.end);
> - } else if (right_len == 1) {
> - rc = fprintf(dest, "%d,%dc%d\n", left_start,
> - cc->left.end, right_start);
> + if (left_len == 1) {
> + rc = fprintf(dest, "%dc\n", left_start);
> } else {
> - rc = fprintf(dest, "%d,%dc%d,%d\n", left_start,
> - cc->left.end, right_start, cc->right.end);
> + rc = fprintf(dest, "%d,%dc\n", left_start, cc->left.end);
> }
> }
> if (rc < 0)
> @@ -100,8 +93,39 @@ output_edscript_chunk(struct diff_output_info *outinfo,
> ARRAYLIST_ADD(offp, outinfo->line_offsets);
> if (offp == NULL)
> return ENOMEM;
> - outoff += rc;
> - *offp = outoff;
> + *outoff += rc;
> + *offp = *outoff;
> + }
> +
> + /* Now write out the new lines in all the joined chunks. */
> + int c_idx;
> + for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) {
> + const struct diff_chunk *c = &result->chunks.head[c_idx];
> + if (c->left_count && !c->right_count)
> + continue;
> + if (c->right_count && !c->left_count) {
> + rc = diff_output_lines(outinfo, dest,
> + c->solved ? "" : "?",
> + c->right_start, c->right_count);
> + if (rc != DIFF_RC_OK)
> + return rc;
> +
> + rc = fprintf(dest, ".\n");
> + if (rc < 0)
> + return errno;
> + if (outinfo) {
> + ARRAYLIST_ADD(offp, outinfo->line_offsets);
> + if (offp == NULL)
> + return ENOMEM;
> + outoff += rc;
> + *offp = *outoff;
> + }
> + }
> + if (cc->chunk.end == result->chunks.len) {
> + rc = diff_output_trailing_newline_msg(outinfo, dest, c);
> + if (rc != DIFF_RC_OK)
> + return rc;
> + }
> }
>
> return DIFF_RC_OK;
> @@ -121,6 +145,7 @@ diff_output_edscript(struct diff_output_info **output_info,
> bool force_text = (flags & DIFF_FLAG_FORCE_TEXT_DATA);
> bool have_binary = (atomizer_flags & DIFF_ATOMIZER_FOUND_BINARY_DATA);
> int i, rc;
> + off_t outoff = 0, *offp;
>
> if (!result)
> return EINVAL;
> @@ -151,7 +176,11 @@ diff_output_edscript(struct diff_output_info **output_info,
> return DIFF_RC_OK;
> }
>
> - for (i = 0; i < result->chunks.len; i++) {
> + /*
> + * Changes in an ed script are in reverse order, the last change to the
> + * file has to be made first to keep state while making edits.
> + */
> + for (i = result->chunks.len-1; i >= 0 ; i--) {
> struct diff_chunk *chunk = &result->chunks.head[i];
> enum diff_chunk_type t = diff_chunk_type(chunk);
> struct diff_chunk_context next;
> @@ -178,13 +207,15 @@ diff_output_edscript(struct diff_output_info **output_info,
> continue;
> }
>
> - rc = output_edscript_chunk(outinfo, dest, info, result, &cc);
> + rc = output_edscript_chunk(outinfo, dest, info, result, &cc,
> + &outoff);
> if (rc != DIFF_RC_OK)
> return rc;
> cc = next;
> }
>
> if (!diff_chunk_context_empty(&cc))
> - return output_edscript_chunk(outinfo, dest, info, result, &cc);
> + return output_edscript_chunk(outinfo, dest, info, result, &cc,
> + &outoff);
> return DIFF_RC_OK;
> }
diff.git: Fix ed script output