]> git.ipfire.org Git - thirdparty/git.git/blobdiff - range-diff.c
Merge branch 'ab/pager-exit-log'
[thirdparty/git.git] / range-diff.c
index b9950f10c8c486b16a2b916b0898d88c8d82fb59..a3cc7c94a3d5c881a0eb9037a06c1a7cf8803bbd 100644 (file)
@@ -11,6 +11,7 @@
 #include "pretty.h"
 #include "userdiff.h"
 #include "apply.h"
+#include "revision.h"
 
 struct patch_util {
        /* For the search for an exact match */
@@ -80,6 +81,8 @@ static int read_patches(const char *range, struct string_list *list,
                finish_command(&cp);
                return -1;
        }
+       if (finish_command(&cp))
+               return -1;
 
        line = contents.buf;
        size = contents.len;
@@ -97,10 +100,10 @@ static int read_patches(const char *range, struct string_list *list,
                        if (get_oid(p, &util->oid)) {
                                error(_("could not parse commit '%s'"), p);
                                free(util);
+                               free(current_filename);
                                string_list_clear(list, 1);
                                strbuf_release(&buf);
                                strbuf_release(&contents);
-                               finish_command(&cp);
                                return -1;
                        }
                        util->matching = -1;
@@ -112,10 +115,10 @@ static int read_patches(const char *range, struct string_list *list,
                        error(_("could not parse first line of `log` output: "
                                "did not start with 'commit ': '%s'"),
                              line);
+                       free(current_filename);
                        string_list_clear(list, 1);
                        strbuf_release(&buf);
                        strbuf_release(&contents);
-                       finish_command(&cp);
                        return -1;
                }
 
@@ -133,9 +136,16 @@ static int read_patches(const char *range, struct string_list *list,
                        orig_len = len;
                        len = parse_git_diff_header(&root, &linenr, 0, line,
                                                    len, size, &patch);
-                       if (len < 0)
-                               die(_("could not parse git header '%.*s'"),
-                                   orig_len, line);
+                       if (len < 0) {
+                               error(_("could not parse git header '%.*s'"),
+                                     orig_len, line);
+                               free(util);
+                               free(current_filename);
+                               string_list_clear(list, 1);
+                               strbuf_release(&buf);
+                               strbuf_release(&contents);
+                               return -1;
+                       }
                        strbuf_addstr(&buf, " ## ");
                        if (patch.is_new > 0)
                                strbuf_addf(&buf, "%s (new)", patch.new_name);
@@ -218,9 +228,6 @@ static int read_patches(const char *range, struct string_list *list,
        strbuf_release(&buf);
        free(current_filename);
 
-       if (finish_command(&cp))
-               return -1;
-
        return 0;
 }
 
@@ -458,12 +465,35 @@ static void patch_diff(const char *a, const char *b,
        diff_flush(diffopt);
 }
 
+static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data)
+{
+       return data;
+}
+
 static void output(struct string_list *a, struct string_list *b,
-                  struct diff_options *diffopt)
+                  struct range_diff_options *range_diff_opts)
 {
        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;
+       struct diff_options opts;
+       struct strbuf indent = STRBUF_INIT;
+
+       if (range_diff_opts->diffopt)
+               memcpy(&opts, range_diff_opts->diffopt, sizeof(opts));
+       else
+               diff_setup(&opts);
+
+       if (!opts.output_format)
+               opts.output_format = DIFF_FORMAT_PATCH;
+       opts.flags.suppress_diff_headers = 1;
+       opts.flags.dual_color_diffed_diffs =
+               range_diff_opts->dual_color;
+       opts.flags.suppress_hunk_header_line_count = 1;
+       opts.output_prefix = output_prefix_cb;
+       strbuf_addstr(&indent, "    ");
+       opts.output_prefix_data = &indent;
+       diff_setup_done(&opts);
 
        /*
         * We assume the user is really more interested in the second argument
@@ -484,7 +514,8 @@ 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(diffopt, patch_no_width,
+                       if (!range_diff_opts->right_only)
+                               output_pair_header(&opts, patch_no_width,
                                           &buf, &dashes, a_util, NULL);
                        i++;
                        continue;
@@ -492,7 +523,8 @@ static void output(struct string_list *a, struct string_list *b,
 
                /* Show unmatched RHS commits. */
                while (j < b->nr && b_util->matching < 0) {
-                       output_pair_header(diffopt, patch_no_width,
+                       if (!range_diff_opts->left_only)
+                               output_pair_header(&opts, patch_no_width,
                                           &buf, &dashes, NULL, b_util);
                        b_util = ++j < b->nr ? b->items[j].util : NULL;
                }
@@ -500,63 +532,41 @@ static void output(struct string_list *a, struct string_list *b,
                /* Show matching LHS/RHS pair. */
                if (j < b->nr) {
                        a_util = a->items[b_util->matching].util;
-                       output_pair_header(diffopt, patch_no_width,
+                       output_pair_header(&opts, patch_no_width,
                                           &buf, &dashes, a_util, b_util);
-                       if (!(diffopt->output_format & DIFF_FORMAT_NO_OUTPUT))
+                       if (!(opts.output_format & DIFF_FORMAT_NO_OUTPUT))
                                patch_diff(a->items[b_util->matching].string,
-                                          b->items[j].string, diffopt);
+                                          b->items[j].string, &opts);
                        a_util->shown = 1;
                        j++;
                }
        }
        strbuf_release(&buf);
        strbuf_release(&dashes);
-}
-
-static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data)
-{
-       return data;
+       strbuf_release(&indent);
 }
 
 int show_range_diff(const char *range1, const char *range2,
-                   int creation_factor, int dual_color,
-                   const struct diff_options *diffopt,
-                   const struct strvec *other_arg)
+                   struct range_diff_options *range_diff_opts)
 {
        int res = 0;
 
        struct string_list branch1 = STRING_LIST_INIT_DUP;
        struct string_list branch2 = STRING_LIST_INIT_DUP;
 
-       if (read_patches(range1, &branch1, other_arg))
+       if (range_diff_opts->left_only && range_diff_opts->right_only)
+               res = error(_("--left-only and --right-only are mutually exclusive"));
+
+       if (!res && read_patches(range1, &branch1, range_diff_opts->other_arg))
                res = error(_("could not parse log for '%s'"), range1);
-       if (!res && read_patches(range2, &branch2, other_arg))
+       if (!res && read_patches(range2, &branch2, range_diff_opts->other_arg))
                res = error(_("could not parse log for '%s'"), range2);
 
        if (!res) {
-               struct diff_options opts;
-               struct strbuf indent = STRBUF_INIT;
-
-               if (diffopt)
-                       memcpy(&opts, diffopt, sizeof(opts));
-               else
-                       diff_setup(&opts);
-
-               if (!opts.output_format)
-                       opts.output_format = DIFF_FORMAT_PATCH;
-               opts.flags.suppress_diff_headers = 1;
-               opts.flags.dual_color_diffed_diffs = dual_color;
-               opts.flags.suppress_hunk_header_line_count = 1;
-               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, &opts);
-
-               strbuf_release(&indent);
+               get_correspondences(&branch1, &branch2,
+                                   range_diff_opts->creation_factor);
+               output(&branch1, &branch2, range_diff_opts);
        }
 
        string_list_clear(&branch1, 1);
@@ -564,3 +574,31 @@ int show_range_diff(const char *range1, const char *range2,
 
        return res;
 }
+
+int is_range_diff_range(const char *arg)
+{
+       char *copy = xstrdup(arg); /* setup_revisions() modifies it */
+       const char *argv[] = { "", copy, "--", NULL };
+       int i, positive = 0, negative = 0;
+       struct rev_info revs;
+
+       init_revisions(&revs, NULL);
+       if (setup_revisions(3, argv, &revs, NULL) == 1) {
+               for (i = 0; i < revs.pending.nr; i++)
+                       if (revs.pending.objects[i].item->flags & UNINTERESTING)
+                               negative++;
+                       else
+                               positive++;
+               for (i = 0; i < revs.pending.nr; i++) {
+                       struct object *obj = revs.pending.objects[i].item;
+
+                       if (obj->type == OBJ_COMMIT)
+                               clear_commit_marks((struct commit *)obj,
+                                                  ALL_REV_FLAGS);
+               }
+       }
+
+       free(copy);
+       object_array_clear(&revs.pending);
+       return negative > 0 && positive > 0;
+}