]> git.ipfire.org Git - thirdparty/git.git/commitdiff
range-diff: also show the diff between patches
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Mon, 13 Aug 2018 11:33:07 +0000 (04:33 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 13 Aug 2018 17:44:50 +0000 (10:44 -0700)
Just like tbdiff, we now show the diff between matching patches. This is
a "diff of two diffs", so it can be a bit daunting to read for the
beginner.

An alternative would be to display an interdiff, i.e. the hypothetical
diff which is the result of first reverting the old diff and then
applying the new diff.

Especially when rebasing frequently, an interdiff is often not feasible,
though: if the old diff cannot be applied in reverse (due to a moving
upstream), an interdiff can simply not be inferred.

This commit brings `range-diff` closer to feature parity with regard
to tbdiff.

To make `git range-diff` respect e.g. color.diff.* settings, we have
to adjust git_branch_config() accordingly.

Note: while we now parse diff options such as --color, the effect is not
yet the same as in tbdiff, where also the commit pairs would be colored.
This is left for a later commit.

Note also: while tbdiff accepts the `--no-patches` option to suppress
these diffs between patches, we prefer the `-s` (or `--no-patch`) option
that is automatically supported via our use of diff_opt_parse().

And finally note: to support diff options, we have to call
`parse_options()` such that it keeps unknown options, and then loop over
those and let `diff_opt_parse()` handle them. After that loop, we have
to call `parse_options()` again, to make sure that no unknown options
are left.

Helped-by: Thomas Gummerer <t.gummerer@gmail.com>
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/range-diff.c
range-diff.c
range-diff.h

index 94c1f362cc4feec11c2ab622f9399c1dff7e2840..3b06ed9449a39168aa606994e6e2cf28fcd22fee 100644 (file)
@@ -2,6 +2,7 @@
 #include "builtin.h"
 #include "parse-options.h"
 #include "range-diff.h"
+#include "config.h"
 
 static const char * const builtin_range_diff_usage[] = {
 N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"),
@@ -13,15 +14,40 @@ NULL
 int cmd_range_diff(int argc, const char **argv, const char *prefix)
 {
        int creation_factor = 60;
+       struct diff_options diffopt = { NULL };
        struct option options[] = {
                OPT_INTEGER(0, "creation-factor", &creation_factor,
                            N_("Percentage by which creation is weighted")),
                OPT_END()
        };
-       int res = 0;
+       int i, j, res = 0;
        struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT;
 
+       git_config(git_diff_ui_config, NULL);
+
+       diff_setup(&diffopt);
+       diffopt.output_format = DIFF_FORMAT_PATCH;
+
        argc = parse_options(argc, argv, NULL, options,
+                            builtin_range_diff_usage, PARSE_OPT_KEEP_UNKNOWN |
+                            PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
+
+       for (i = j = 1; i < argc && strcmp("--", argv[i]); ) {
+               int c = diff_opt_parse(&diffopt, argv + i, argc - i, prefix);
+
+               if (!c)
+                       argv[j++] = argv[i++];
+               else
+                       i += c;
+       }
+       while (i < argc)
+               argv[j++] = argv[i++];
+       argc = j;
+       diff_setup_done(&diffopt);
+
+       /* Make sure that there are no unparsed options */
+       argc = parse_options(argc, argv, NULL,
+                            options + ARRAY_SIZE(options) - 1, /* OPT_END */
                             builtin_range_diff_usage, 0);
 
        if (argc == 2) {
@@ -59,7 +85,8 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
                usage_with_options(builtin_range_diff_usage, options);
        }
 
-       res = show_range_diff(range1.buf, range2.buf, creation_factor);
+       res = show_range_diff(range1.buf, range2.buf, creation_factor,
+                             &diffopt);
 
        strbuf_release(&range1);
        strbuf_release(&range2);
index 2d94200d3034b1914aac1507c86be16f3298cf4b..71883a4b7d06ddf2b4df6e7a731287013ed34b6d 100644 (file)
@@ -6,6 +6,7 @@
 #include "hashmap.h"
 #include "xdiff-interface.h"
 #include "linear-assignment.h"
+#include "diffcore.h"
 
 struct patch_util {
        /* For the search for an exact match */
@@ -258,7 +259,31 @@ static const char *short_oid(struct patch_util *util)
        return find_unique_abbrev(&util->oid, DEFAULT_ABBREV);
 }
 
-static void output(struct string_list *a, struct string_list *b)
+static struct diff_filespec *get_filespec(const char *name, const char *p)
+{
+       struct diff_filespec *spec = alloc_filespec(name);
+
+       fill_filespec(spec, &null_oid, 0, 0644);
+       spec->data = (char *)p;
+       spec->size = strlen(p);
+       spec->should_munmap = 0;
+       spec->is_stdin = 1;
+
+       return spec;
+}
+
+static void patch_diff(const char *a, const char *b,
+                             struct diff_options *diffopt)
+{
+       diff_queue(&diff_queued_diff,
+                  get_filespec("a", a), get_filespec("b", b));
+
+       diffcore_std(diffopt);
+       diff_flush(diffopt);
+}
+
+static void output(struct string_list *a, struct string_list *b,
+                  struct diff_options *diffopt)
 {
        int i = 0, j = 0;
 
@@ -300,6 +325,9 @@ static void output(struct string_list *a, struct string_list *b)
                        printf("%d: %s ! %d: %s\n",
                               b_util->matching + 1, short_oid(a_util),
                               j + 1, short_oid(b_util));
+                       if (!(diffopt->output_format & DIFF_FORMAT_NO_OUTPUT))
+                               patch_diff(a->items[b_util->matching].string,
+                                          b->items[j].string, diffopt);
                        a_util->shown = 1;
                        j++;
                }
@@ -307,7 +335,7 @@ static void output(struct string_list *a, struct string_list *b)
 }
 
 int show_range_diff(const char *range1, const char *range2,
-                   int creation_factor)
+                   int creation_factor, struct diff_options *diffopt)
 {
        int res = 0;
 
@@ -322,7 +350,7 @@ int show_range_diff(const char *range1, const char *range2,
        if (!res) {
                find_exact_matches(&branch1, &branch2);
                get_correspondences(&branch1, &branch2, creation_factor);
-               output(&branch1, &branch2);
+               output(&branch1, &branch2, diffopt);
        }
 
        string_list_clear(&branch1, 1);
index 7b6eef303f5efbe6400d4b58a999bdd770b9fecc..2407d46a301e5554bf3a4f855d20cc408b1f89bd 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef RANGE_DIFF_H
 #define RANGE_DIFF_H
 
+#include "diff.h"
+
 int show_range_diff(const char *range1, const char *range2,
-                   int creation_factor);
+                   int creation_factor, struct diff_options *diffopt);
 
 #endif