Merge branch 'js/range-diff-wo-dotdot'

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
This commit is contained in:
Junio C Hamano 2021-02-17 17:21:41 -08:00
commit 77348b0e6e
6 changed files with 65 additions and 5 deletions

View 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 second commit range, with unmatched commits being inserted just after
all of their ancestors have been shown. 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 OPTIONS
------- -------

View File

@ -1672,7 +1672,7 @@ static void infer_range_diff_ranges(struct strbuf *r1,
struct commit *head) struct commit *head)
{ {
const char *head_oid = oid_to_hex(&head->object.oid); 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) if (prev_is_range)
strbuf_addstr(r1, prev); strbuf_addstr(r1, prev);

View File

@ -3,6 +3,7 @@
#include "parse-options.h" #include "parse-options.h"
#include "range-diff.h" #include "range-diff.h"
#include "config.h" #include "config.h"
#include "revision.h"
static const char * const builtin_range_diff_usage[] = { static const char * const builtin_range_diff_usage[] = {
N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"), 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; diffopt.use_color = 1;
if (argc == 2) { if (argc == 2) {
if (!strstr(argv[0], "..")) if (!is_range_diff_range(argv[0]))
die(_("no .. in range: '%s'"), argv[0]); die(_("not a commit range: '%s'"), argv[0]);
strbuf_addstr(&range1, argv[0]); strbuf_addstr(&range1, argv[0]);
if (!strstr(argv[1], "..")) if (!is_range_diff_range(argv[1]))
die(_("no .. in range: '%s'"), argv[1]); die(_("not a commit range: '%s'"), argv[1]);
strbuf_addstr(&range2, argv[1]); strbuf_addstr(&range2, argv[1]);
} else if (argc == 3) { } else if (argc == 3) {
strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);

View File

@ -11,6 +11,7 @@
#include "pretty.h" #include "pretty.h"
#include "userdiff.h" #include "userdiff.h"
#include "apply.h" #include "apply.h"
#include "revision.h"
struct patch_util { struct patch_util {
/* For the search for an exact match */ /* For the search for an exact match */
@ -564,3 +565,31 @@ int show_range_diff(const char *range1, const char *range2,
return res; 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;
}

View File

@ -16,4 +16,10 @@ int show_range_diff(const char *range1, const char *range2,
const struct diff_options *diffopt, const struct diff_options *diffopt,
const struct strvec *other_arg); 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 #endif

View File

@ -153,6 +153,19 @@ test_expect_success 'simple A B C (unmodified)' '
test_cmp expect actual 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' ' test_expect_success 'trivial reordering' '
git range-diff --no-color main topic reordered >actual && git range-diff --no-color main topic reordered >actual &&
cat >expect <<-EOF && cat >expect <<-EOF &&