diff --git a/range-diff.c b/range-diff.c index 15d418afa6..2d94200d30 100644 --- a/range-diff.c +++ b/range-diff.c @@ -12,7 +12,7 @@ struct patch_util { struct hashmap_entry e; const char *diff, *patch; - int i; + int i, shown; int diffsize; size_t diff_offset; /* the index of the matching item in the other branch, or -1 */ @@ -260,28 +260,49 @@ static const char *short_oid(struct patch_util *util) static void output(struct string_list *a, struct string_list *b) { - int i; + int i = 0, j = 0; - for (i = 0; i < b->nr; i++) { - struct patch_util *util = b->items[i].util, *prev; + /* + * We assume the user is really more interested in the second argument + * ("newer" version). To that end, we print the output in the order of + * the RHS (the `b` parameter). To put the LHS (the `a` parameter) + * commits that are no longer in the RHS into a good place, we place + * them once we have shown all of their predecessors in the LHS. + */ - if (util->matching < 0) - printf("-: -------- > %d: %s\n", - i + 1, short_oid(util)); - else { - prev = a->items[util->matching].util; - printf("%d: %s ! %d: %s\n", - util->matching + 1, short_oid(prev), - i + 1, short_oid(util)); - } - } + while (i < a->nr || j < b->nr) { + struct patch_util *a_util, *b_util; + a_util = i < a->nr ? a->items[i].util : NULL; + b_util = j < b->nr ? b->items[j].util : NULL; - for (i = 0; i < a->nr; i++) { - struct patch_util *util = a->items[i].util; + /* Skip all the already-shown commits from the LHS. */ + while (i < a->nr && a_util->shown) + a_util = ++i < a->nr ? a->items[i].util : NULL; - if (util->matching < 0) + /* Show unmatched LHS commit whose predecessors were shown. */ + if (i < a->nr && a_util->matching < 0) { printf("%d: %s < -: --------\n", - i + 1, short_oid(util)); + i + 1, short_oid(a_util)); + i++; + continue; + } + + /* Show unmatched RHS commits. */ + while (j < b->nr && b_util->matching < 0) { + printf("-: -------- > %d: %s\n", + j + 1, short_oid(b_util)); + b_util = ++j < b->nr ? b->items[j].util : NULL; + } + + /* Show matching LHS/RHS pair. */ + if (j < b->nr) { + a_util = a->items[b_util->matching].util; + printf("%d: %s ! %d: %s\n", + b_util->matching + 1, short_oid(a_util), + j + 1, short_oid(b_util)); + a_util->shown = 1; + j++; + } } }