commit 26595c7df947f97507904fa391034b6a52bfca7d from: Stefan Sperling date: Thu Oct 15 21:30:21 2020 UTC in ed output mode, show changed lines as XXcYY etc. as UNIX diff(1) does commit - 227cd87e537c560f428629cf170b0f19422b1c56 commit + 26595c7df947f97507904fa391034b6a52bfca7d blob - 5c8fd1fc7ae45e166e7af7a09a3e9b4cfa0f47b9 blob + 0450a007a948e500aa26ebd54a8aa533da5bbd63 --- lib/diff_internal.h +++ lib/diff_internal.h @@ -178,6 +178,16 @@ diff_chunk_type(const struct diff_chunk *chunk) return CHUNK_SAME; } +struct diff_chunk_context; + +bool +diff_chunk_contexts_touch(const struct diff_chunk_context *cc, + const struct diff_chunk_context *other); + +void +diff_chunk_contexts_merge(struct diff_chunk_context *cc, + const struct diff_chunk_context *other); + struct diff_state { /* The final result passed to the original diff caller. */ struct diff_result *result; blob - 65ef9ad4da6435426210a1e93aeda9c7e57539c3 blob + 38053a9163403e9b1871f8d864aec3d3d8460956 --- lib/diff_output_edscript.c +++ lib/diff_output_edscript.c @@ -31,7 +31,7 @@ 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, enum diff_chunk_type chunk_type) + struct diff_chunk_context *cc) { off_t outoff = 0, *offp; int left_start, left_len, right_start, right_len; @@ -57,23 +57,38 @@ output_edscript_chunk(struct diff_output_info *outinfo else right_start = cc->right.start + 1; - if (chunk_type == CHUNK_MINUS) { + if (left_len == 0) { + /* addition */ + if (right_len == 1) { + rc = fprintf(dest, "%da%d\n", left_start, right_start); + } else { + rc = fprintf(dest, "%da%d,%d\n", left_start, + right_start, cc->right.end); + } + } else if (right_len == 0) { + /* deletion */ if (left_len == 1) { - rc = fprintf(dest, "%dd%d\n", left_start, right_start); + rc = fprintf(dest, "%dd%d\n", left_start, + right_start); } else { rc = fprintf(dest, "%d,%dd%d\n", left_start, cc->left.end, right_start); } - } else if (chunk_type == CHUNK_PLUS) { - if (right_len == 1) { - rc = fprintf(dest, "%da%d\n", left_start, right_start); - } else { - rc = fprintf(dest, "%da%d,%d\n", left_start, + } 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); + } else { + rc = fprintf(dest, "%d,%dc%d,%d\n", left_start, + cc->left.end, right_start, cc->right.end); } - } else - return EINVAL; - + } if (rc < 0) return errno; if (outinfo) { @@ -93,6 +108,7 @@ diff_output_edscript(struct diff_output_info **output_ const struct diff_result *result) { struct diff_output_info *outinfo = NULL; + struct diff_chunk_context cc = {}; int i, rc; if (!result) @@ -110,20 +126,37 @@ diff_output_edscript(struct diff_output_info **output_ for (i = 0; i < result->chunks.len; i++) { struct diff_chunk *chunk = &result->chunks.head[i]; enum diff_chunk_type t = diff_chunk_type(chunk); - struct diff_chunk_context cc = {}; + struct diff_chunk_context next; if (t != CHUNK_MINUS && t != CHUNK_PLUS) continue; - diff_chunk_context_get(&cc, result, i, 0); + if (diff_range_empty(&cc.chunk)) { + /* Note down the start point, any number of subsequent + * chunks may be joined up to this chunk by being + * directly adjacent. */ + diff_chunk_context_get(&cc, result, i, 0); + continue; + } - if (diff_range_empty(&cc.chunk)) + /* There already is a previous chunk noted down for being + * printed. Does it join up with this one? */ + diff_chunk_context_get(&next, result, i, 0); + + if (diff_chunk_contexts_touch(&cc, &next)) { + /* This next context touches or overlaps the previous + * one, join. */ + diff_chunk_contexts_merge(&cc, &next); continue; + } - rc = output_edscript_chunk(outinfo, dest, info, result, &cc, t); + rc = output_edscript_chunk(outinfo, dest, info, result, &cc); if (rc != DIFF_RC_OK) return rc; + cc = next; } + if (!diff_range_empty(&cc.chunk)) + return output_edscript_chunk(outinfo, dest, info, result, &cc); return DIFF_RC_OK; } blob - d4dfc359e4f14a7a3d3593b4b5d252865abd5e57 blob + eaea44c1044a8f6ee273c5559c2945e50f2475c9 --- lib/diff_output_unidiff.c +++ lib/diff_output_unidiff.c @@ -94,18 +94,18 @@ diff_chunk_context_get(struct diff_chunk_context *cc, }; } -static bool -chunk_contexts_touch(const struct diff_chunk_context *cc, - const struct diff_chunk_context *other) +bool +diff_chunk_contexts_touch(const struct diff_chunk_context *cc, + const struct diff_chunk_context *other) { return diff_ranges_touch(&cc->chunk, &other->chunk) || diff_ranges_touch(&cc->left, &other->left) || diff_ranges_touch(&cc->right, &other->right); } -static void -chunk_contexts_merge(struct diff_chunk_context *cc, - const struct diff_chunk_context *other) +void +diff_chunk_contexts_merge(struct diff_chunk_context *cc, + const struct diff_chunk_context *other) { diff_ranges_merge(&cc->chunk, &other->chunk); diff_ranges_merge(&cc->left, &other->left); @@ -380,10 +380,10 @@ diff_output_unidiff(struct diff_output_info **output_i next.left.start, next.left.end, next.right.start, next.right.end); - if (chunk_contexts_touch(&cc, &next)) { + if (diff_chunk_contexts_touch(&cc, &next)) { /* This next context touches or overlaps the previous * one, join. */ - chunk_contexts_merge(&cc, &next); + diff_chunk_contexts_merge(&cc, &next); debug("new chunk to be printed touches previous chunk," " now: left %d-%d right %d-%d\n", cc.left.start, cc.left.end,