]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'js/range-diff-wo-dotdot'
authorJunio C Hamano <gitster@pobox.com>
Thu, 18 Feb 2021 01:21:41 +0000 (17:21 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Feb 2021 01:21:41 +0000 (17:21 -0800)
There are other ways than ".." for a single token to denote a
"commit range", namely "<rev>^!" and "<rev>^-<n>", but "git
range-diff" did not understand them.

* js/range-diff-wo-dotdot:
  range-diff(docs): explain how to specify commit ranges
  range-diff/format-patch: handle commit ranges other than A..B
  range-diff/format-patch: refactor check for commit range

Documentation/git-range-diff.txt
builtin/log.c
builtin/range-diff.c
range-diff.c
range-diff.h
t/t3206-range-diff.sh

index 9701c1e5fdd5a016c360b8102f0193dfa0fb90fb..a968d5237daed52f007958ab78b47a61b2585cfb 100644 (file)
@@ -28,6 +28,17 @@ Finally, the list of matching commits is shown in the order of the
 second commit range, with unmatched commits being inserted just after
 all of their ancestors have been shown.
 
+There are three ways to specify the commit ranges:
+
+- `<range1> <range2>`: Either commit range can be of the form
+  `<base>..<rev>`, `<rev>^!` or `<rev>^-<n>`. See `SPECIFYING RANGES`
+  in linkgit:gitrevisions[7] for more details.
+
+- `<rev1>...<rev2>`. This is equivalent to
+  `<rev2>..<rev1> <rev1>..<rev2>`.
+
+- `<base> <rev1> <rev2>`: This is equivalent to `<base>..<rev1>
+  <base>..<rev2>`.
 
 OPTIONS
 -------
index d0cbaaf68a083f0cfa3294804f606b5cb6dff5c4..a00da91a1f0c37ed26b658324d23be3d828a89ef 100644 (file)
@@ -1672,7 +1672,7 @@ static void infer_range_diff_ranges(struct strbuf *r1,
                                    struct commit *head)
 {
        const char *head_oid = oid_to_hex(&head->object.oid);
-       int prev_is_range = !!strstr(prev, "..");
+       int prev_is_range = is_range_diff_range(prev);
 
        if (prev_is_range)
                strbuf_addstr(r1, prev);
index 24c4162f7446ce89ff2fe9866bb0dc678785bed4..5b1f6326322f853a4a26a2cb2f2962d6f91ad67a 100644 (file)
@@ -3,6 +3,7 @@
 #include "parse-options.h"
 #include "range-diff.h"
 #include "config.h"
+#include "revision.h"
 
 static const char * const builtin_range_diff_usage[] = {
 N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"),
@@ -46,12 +47,12 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
                diffopt.use_color = 1;
 
        if (argc == 2) {
-               if (!strstr(argv[0], ".."))
-                       die(_("no .. in range: '%s'"), argv[0]);
+               if (!is_range_diff_range(argv[0]))
+                       die(_("not a commit range: '%s'"), argv[0]);
                strbuf_addstr(&range1, argv[0]);
 
-               if (!strstr(argv[1], ".."))
-                       die(_("no .. in range: '%s'"), argv[1]);
+               if (!is_range_diff_range(argv[1]))
+                       die(_("not a commit range: '%s'"), argv[1]);
                strbuf_addstr(&range2, argv[1]);
        } else if (argc == 3) {
                strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
index b9950f10c8c486b16a2b916b0898d88c8d82fb59..a88612cb89233ed30ec945ccab9cbab56b4c778f 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 */
@@ -564,3 +565,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;
+}
index 583ced2e8e749003b9a22fe2496d0db49f5ba7f9..4abd70c40fed668b80ad935668c026c0ddbf9ce8 100644 (file)
@@ -16,4 +16,10 @@ int show_range_diff(const char *range1, const char *range2,
                    const struct diff_options *diffopt,
                    const struct strvec *other_arg);
 
+/*
+ * Determine whether the given argument is usable as a range argument of `git
+ * range-diff`, e.g. A..B.
+ */
+int is_range_diff_range(const char *arg);
+
 #endif
index ce24b5d735abc263be7c4125155a47663d1616cf..b782d26820c6d1e62c9ad0b3d55176bc567b4cad 100755 (executable)
@@ -153,6 +153,19 @@ test_expect_success 'simple A B C (unmodified)' '
        test_cmp expect actual
 '
 
+test_expect_success 'A^! and A^-<n> (unmodified)' '
+       git range-diff --no-color topic^! unmodified^-1 >actual &&
+       cat >expect <<-EOF &&
+       1:  $(test_oid t4) = 1:  $(test_oid u4) s/12/B/
+       EOF
+       test_cmp expect actual
+'
+
+test_expect_success 'A^{/..} is not mistaken for a range' '
+       test_must_fail git range-diff topic^.. topic^{/..} 2>error &&
+       test_i18ngrep "not a commit range" error
+'
+
 test_expect_success 'trivial reordering' '
        git range-diff --no-color main topic reordered >actual &&
        cat >expect <<-EOF &&