merge-recursive: remove final remaining caller of merge_file_one()
[gitweb.git] / range-diff.c
index 23aa61af594189795bee50fccd5649d7c0e73944..60edb2f518d6d696b8091ef6246791cd730f326f 100644 (file)
@@ -9,6 +9,7 @@
 #include "diffcore.h"
 #include "commit.h"
 #include "pretty.h"
+#include "userdiff.h"
 
 struct patch_util {
        /* For the search for an exact match */
@@ -37,6 +38,14 @@ static int read_patches(const char *range, struct string_list *list)
 
        argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
                        "--reverse", "--date-order", "--decorate=no",
+                       /*
+                        * Choose indicators that are not used anywhere
+                        * else in diffs, but still look reasonable
+                        * (e.g. will not be confusing when debugging)
+                        */
+                       "--output-indicator-new=>",
+                       "--output-indicator-old=<",
+                       "--output-indicator-context=#",
                        "--no-abbrev-commit", range,
                        NULL);
        cp.out = -1;
@@ -81,6 +90,7 @@ static int read_patches(const char *range, struct string_list *list)
                        strbuf_addch(&buf, '\n');
                        if (!util->diff_offset)
                                util->diff_offset = buf.len;
+                       strbuf_addch(&buf, ' ');
                        strbuf_addbuf(&buf, &line);
                } else if (in_header) {
                        if (starts_with(line.buf, "Author: ")) {
@@ -107,8 +117,19 @@ static int read_patches(const char *range, struct string_list *list)
                         * we are not interested.
                         */
                        continue;
-               else
+               else if (line.buf[0] == '>') {
+                       strbuf_addch(&buf, '+');
+                       strbuf_add(&buf, line.buf + 1, line.len - 1);
+               } else if (line.buf[0] == '<') {
+                       strbuf_addch(&buf, '-');
+                       strbuf_add(&buf, line.buf + 1, line.len - 1);
+               } else if (line.buf[0] == '#') {
+                       strbuf_addch(&buf, ' ');
+                       strbuf_add(&buf, line.buf + 1, line.len - 1);
+               } else {
+                       strbuf_addch(&buf, ' ');
                        strbuf_addbuf(&buf, &line);
+               }
 
                strbuf_addch(&buf, '\n');
                util->diffsize++;
@@ -257,51 +278,78 @@ static void get_correspondences(struct string_list *a, struct string_list *b,
        free(b2a);
 }
 
-static void output_pair_header(struct strbuf *buf,
+static void output_pair_header(struct diff_options *diffopt,
+                              int patch_no_width,
+                              struct strbuf *buf,
                               struct strbuf *dashes,
                               struct patch_util *a_util,
                               struct patch_util *b_util)
 {
        struct object_id *oid = a_util ? &a_util->oid : &b_util->oid;
        struct commit *commit;
+       char status;
+       const char *color_reset = diff_get_color_opt(diffopt, DIFF_RESET);
+       const char *color_old = diff_get_color_opt(diffopt, DIFF_FILE_OLD);
+       const char *color_new = diff_get_color_opt(diffopt, DIFF_FILE_NEW);
+       const char *color_commit = diff_get_color_opt(diffopt, DIFF_COMMIT);
+       const char *color;
 
        if (!dashes->len)
                strbuf_addchars(dashes, '-',
                                strlen(find_unique_abbrev(oid,
                                                          DEFAULT_ABBREV)));
 
+       if (!b_util) {
+               color = color_old;
+               status = '<';
+       } else if (!a_util) {
+               color = color_new;
+               status = '>';
+       } else if (strcmp(a_util->patch, b_util->patch)) {
+               color = color_commit;
+               status = '!';
+       } else {
+               color = color_commit;
+               status = '=';
+       }
+
        strbuf_reset(buf);
+       strbuf_addstr(buf, status == '!' ? color_old : color);
        if (!a_util)
-               strbuf_addf(buf, "-:  %s ", dashes->buf);
+               strbuf_addf(buf, "%*s:  %s ", patch_no_width, "-", dashes->buf);
        else
-               strbuf_addf(buf, "%d:  %s ", a_util->i + 1,
+               strbuf_addf(buf, "%*d:  %s ", patch_no_width, a_util->i + 1,
                            find_unique_abbrev(&a_util->oid, DEFAULT_ABBREV));
 
-       if (!a_util)
-               strbuf_addch(buf, '>');
-       else if (!b_util)
-               strbuf_addch(buf, '<');
-       else if (strcmp(a_util->patch, b_util->patch))
-               strbuf_addch(buf, '!');
-       else
-               strbuf_addch(buf, '=');
+       if (status == '!')
+               strbuf_addf(buf, "%s%s", color_reset, color);
+       strbuf_addch(buf, status);
+       if (status == '!')
+               strbuf_addf(buf, "%s%s", color_reset, color_new);
 
        if (!b_util)
-               strbuf_addf(buf, " -:  %s", dashes->buf);
+               strbuf_addf(buf, " %*s:  %s", patch_no_width, "-", dashes->buf);
        else
-               strbuf_addf(buf, " %d:  %s", b_util->i + 1,
+               strbuf_addf(buf, " %*d:  %s", patch_no_width, b_util->i + 1,
                            find_unique_abbrev(&b_util->oid, DEFAULT_ABBREV));
 
        commit = lookup_commit_reference(the_repository, oid);
        if (commit) {
+               if (status == '!')
+                       strbuf_addf(buf, "%s%s", color_reset, color);
+
                strbuf_addch(buf, ' ');
                pp_commit_easy(CMIT_FMT_ONELINE, commit, buf);
        }
-       strbuf_addch(buf, '\n');
+       strbuf_addf(buf, "%s\n", color_reset);
 
-       fwrite(buf->buf, buf->len, 1, stdout);
+       fwrite(buf->buf, buf->len, 1, diffopt->file);
 }
 
+static struct userdiff_driver no_func_name = {
+       .funcname = { "$^", 0 }
+};
+
 static struct diff_filespec *get_filespec(const char *name, const char *p)
 {
        struct diff_filespec *spec = alloc_filespec(name);
@@ -311,6 +359,7 @@ static struct diff_filespec *get_filespec(const char *name, const char *p)
        spec->size = strlen(p);
        spec->should_munmap = 0;
        spec->is_stdin = 1;
+       spec->driver = &no_func_name;
 
        return spec;
 }
@@ -329,6 +378,7 @@ static void output(struct string_list *a, struct string_list *b,
                   struct diff_options *diffopt)
 {
        struct strbuf buf = STRBUF_INIT, dashes = STRBUF_INIT;
+       int patch_no_width = decimal_width(1 + (a->nr > b->nr ? a->nr : b->nr));
        int i = 0, j = 0;
 
        /*
@@ -350,21 +400,24 @@ static void output(struct string_list *a, struct string_list *b,
 
                /* Show unmatched LHS commit whose predecessors were shown. */
                if (i < a->nr && a_util->matching < 0) {
-                       output_pair_header(&buf, &dashes, a_util, NULL);
+                       output_pair_header(diffopt, patch_no_width,
+                                          &buf, &dashes, a_util, NULL);
                        i++;
                        continue;
                }
 
                /* Show unmatched RHS commits. */
                while (j < b->nr && b_util->matching < 0) {
-                       output_pair_header(&buf, &dashes, NULL, b_util);
+                       output_pair_header(diffopt, patch_no_width,
+                                          &buf, &dashes, NULL, 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;
-                       output_pair_header(&buf, &dashes, a_util, b_util);
+                       output_pair_header(diffopt, patch_no_width,
+                                          &buf, &dashes, a_util, b_util);
                        if (!(diffopt->output_format & DIFF_FORMAT_NO_OUTPUT))
                                patch_diff(a->items[b_util->matching].string,
                                           b->items[j].string, diffopt);
@@ -376,8 +429,14 @@ static void output(struct string_list *a, struct string_list *b,
        strbuf_release(&dashes);
 }
 
+static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data)
+{
+       return data;
+}
+
 int show_range_diff(const char *range1, const char *range2,
-                   int creation_factor, struct diff_options *diffopt)
+                   int creation_factor, int dual_color,
+                   struct diff_options *diffopt)
 {
        int res = 0;
 
@@ -390,9 +449,23 @@ int show_range_diff(const char *range1, const char *range2,
                res = error(_("could not parse log for '%s'"), range2);
 
        if (!res) {
+               struct diff_options opts;
+               struct strbuf indent = STRBUF_INIT;
+
+               memcpy(&opts, diffopt, sizeof(opts));
+               opts.output_format = DIFF_FORMAT_PATCH;
+               opts.flags.suppress_diff_headers = 1;
+               opts.flags.dual_color_diffed_diffs = dual_color;
+               opts.output_prefix = output_prefix_cb;
+               strbuf_addstr(&indent, "    ");
+               opts.output_prefix_data = &indent;
+               diff_setup_done(&opts);
+
                find_exact_matches(&branch1, &branch2);
                get_correspondences(&branch1, &branch2, creation_factor);
-               output(&branch1, &branch2, diffopt);
+               output(&branch1, &branch2, &opts);
+
+               strbuf_release(&indent);
        }
 
        string_list_clear(&branch1, 1);