2018-08-13 11:33:02 +00:00
|
|
|
#include "builtin.h"
|
2023-03-21 06:25:54 +00:00
|
|
|
#include "gettext.h"
|
2023-04-11 07:41:49 +00:00
|
|
|
#include "object-name.h"
|
2018-08-13 11:33:02 +00:00
|
|
|
#include "parse-options.h"
|
2018-08-13 11:33:04 +00:00
|
|
|
#include "range-diff.h"
|
range-diff: also show the diff between patches
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>
2018-08-13 11:33:07 +00:00
|
|
|
#include "config.h"
|
2023-05-16 06:34:00 +00:00
|
|
|
#include "repository.h"
|
2018-08-13 11:33:02 +00:00
|
|
|
|
|
|
|
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-tip>...<new-tip>"),
|
|
|
|
N_("git range-diff [<options>] <base> <old-tip> <new-tip>"),
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
int cmd_range_diff(int argc, const char **argv, const char *prefix)
|
|
|
|
{
|
range-diff: also show the diff between patches
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>
2018-08-13 11:33:07 +00:00
|
|
|
struct diff_options diffopt = { NULL };
|
2020-07-28 20:24:27 +00:00
|
|
|
struct strvec other_arg = STRVEC_INIT;
|
2021-02-05 14:46:11 +00:00
|
|
|
struct range_diff_options range_diff_opts = {
|
|
|
|
.creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT,
|
|
|
|
.diffopt = &diffopt,
|
|
|
|
.other_arg = &other_arg
|
|
|
|
};
|
2021-02-05 14:46:13 +00:00
|
|
|
int simple_color = -1, left_only = 0, right_only = 0;
|
2019-03-24 08:20:12 +00:00
|
|
|
struct option range_diff_options[] = {
|
2021-02-05 14:46:11 +00:00
|
|
|
OPT_INTEGER(0, "creation-factor",
|
|
|
|
&range_diff_opts.creation_factor,
|
2021-03-29 14:46:34 +00:00
|
|
|
N_("percentage by which creation is weighted")),
|
2018-08-13 11:33:30 +00:00
|
|
|
OPT_BOOL(0, "no-dual-color", &simple_color,
|
2018-08-23 21:57:48 +00:00
|
|
|
N_("use simple diff colors")),
|
2019-11-20 21:18:45 +00:00
|
|
|
OPT_PASSTHRU_ARGV(0, "notes", &other_arg,
|
|
|
|
N_("notes"), N_("passed to 'git log'"),
|
|
|
|
PARSE_OPT_OPTARG),
|
2021-02-05 14:46:13 +00:00
|
|
|
OPT_BOOL(0, "left-only", &left_only,
|
|
|
|
N_("only emit output related to the first range")),
|
|
|
|
OPT_BOOL(0, "right-only", &right_only,
|
|
|
|
N_("only emit output related to the second range")),
|
2018-08-13 11:33:02 +00:00
|
|
|
OPT_END()
|
|
|
|
};
|
2019-03-24 08:20:12 +00:00
|
|
|
struct option *options;
|
2022-08-26 09:39:30 +00:00
|
|
|
int i, dash_dash = -1, res = 0;
|
2018-08-13 11:33:04 +00:00
|
|
|
struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT;
|
2022-08-26 09:39:29 +00:00
|
|
|
struct object_id oid;
|
2022-08-26 09:39:30 +00:00
|
|
|
const char *three_dots = NULL;
|
2018-08-13 11:33:02 +00:00
|
|
|
|
range-diff: also show the diff between patches
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>
2018-08-13 11:33:07 +00:00
|
|
|
git_config(git_diff_ui_config, NULL);
|
|
|
|
|
2018-09-21 15:57:24 +00:00
|
|
|
repo_diff_setup(the_repository, &diffopt);
|
range-diff: also show the diff between patches
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>
2018-08-13 11:33:07 +00:00
|
|
|
|
2022-12-01 22:49:11 +00:00
|
|
|
options = add_diff_options(range_diff_options, &diffopt);
|
2019-05-09 21:28:51 +00:00
|
|
|
argc = parse_options(argc, argv, prefix, options,
|
2022-08-26 09:39:30 +00:00
|
|
|
builtin_range_diff_usage, PARSE_OPT_KEEP_DASHDASH);
|
range-diff: also show the diff between patches
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>
2018-08-13 11:33:07 +00:00
|
|
|
|
|
|
|
diff_setup_done(&diffopt);
|
|
|
|
|
2018-07-22 09:57:12 +00:00
|
|
|
/* force color when --dual-color was used */
|
|
|
|
if (!simple_color)
|
|
|
|
diffopt.use_color = 1;
|
2018-08-13 11:33:22 +00:00
|
|
|
|
2022-08-26 09:39:30 +00:00
|
|
|
for (i = 0; i < argc; i++)
|
|
|
|
if (!strcmp(argv[i], "--")) {
|
|
|
|
dash_dash = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dash_dash == 3 ||
|
|
|
|
(dash_dash < 0 && argc > 2 &&
|
2023-03-28 13:58:46 +00:00
|
|
|
!repo_get_oid_committish(the_repository, argv[0], &oid) &&
|
|
|
|
!repo_get_oid_committish(the_repository, argv[1], &oid) &&
|
|
|
|
!repo_get_oid_committish(the_repository, argv[2], &oid))) {
|
2022-08-26 09:39:30 +00:00
|
|
|
if (dash_dash < 0)
|
|
|
|
; /* already validated arguments */
|
2023-03-28 13:58:46 +00:00
|
|
|
else if (repo_get_oid_committish(the_repository, argv[0], &oid))
|
2022-08-26 09:39:29 +00:00
|
|
|
usage_msg_optf(_("not a revision: '%s'"),
|
|
|
|
builtin_range_diff_usage, options,
|
|
|
|
argv[0]);
|
2023-03-28 13:58:46 +00:00
|
|
|
else if (repo_get_oid_committish(the_repository, argv[1], &oid))
|
2022-08-26 09:39:29 +00:00
|
|
|
usage_msg_optf(_("not a revision: '%s'"),
|
|
|
|
builtin_range_diff_usage, options,
|
|
|
|
argv[1]);
|
2023-03-28 13:58:46 +00:00
|
|
|
else if (repo_get_oid_committish(the_repository, argv[2], &oid))
|
2022-08-26 09:39:29 +00:00
|
|
|
usage_msg_optf(_("not a revision: '%s'"),
|
|
|
|
builtin_range_diff_usage, options,
|
|
|
|
argv[2]);
|
|
|
|
|
range-diff: reorder argument handling
In d9c66f0b5bf (range-diff: first rudimentary implementation,
2018-08-13), we introduced the argument handling of the `range-diff`
command, special-casing three different stanzas based on the argument
count.
The somewhat unorthodox order (first handling the case of 2 arguments,
then 3, then 1) was chosen for clarity: the natural argument number is 2
because that is how many revision ranges are used internally. The code
to handle three arguments is relatively trivial, so it was added next.
And finally, the code to ungarble a single symmetric range into two
separate ones was added, because it was the most complicated (the most
inelegant part being about interpreting empty sides of the symmetric
range as `HEAD`).
In preparation for allowing pathspecs in `git range-diff` invocations,
where we no longer have the luxury of using the number of arguments to
disambiguate between these three different ways to specify the commit
ranges, we need to order these cases by argument count, in descending
order.
This patch is best viewed with `--color-moved`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-26 09:39:28 +00:00
|
|
|
strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
|
|
|
|
strbuf_addf(&range2, "%s..%s", argv[0], argv[2]);
|
2022-08-26 09:39:30 +00:00
|
|
|
|
|
|
|
strvec_pushv(&other_arg, argv +
|
|
|
|
(dash_dash < 0 ? 3 : dash_dash));
|
|
|
|
} else if (dash_dash == 2 ||
|
|
|
|
(dash_dash < 0 && argc > 1 &&
|
|
|
|
is_range_diff_range(argv[0]) &&
|
|
|
|
is_range_diff_range(argv[1]))) {
|
|
|
|
if (dash_dash < 0)
|
|
|
|
; /* already validated arguments */
|
|
|
|
else if (!is_range_diff_range(argv[0]))
|
2022-08-26 09:39:29 +00:00
|
|
|
usage_msg_optf(_("not a commit range: '%s'"),
|
|
|
|
builtin_range_diff_usage, options,
|
|
|
|
argv[0]);
|
|
|
|
else if (!is_range_diff_range(argv[1]))
|
|
|
|
usage_msg_optf(_("not a commit range: '%s'"),
|
|
|
|
builtin_range_diff_usage, options,
|
|
|
|
argv[1]);
|
2018-08-13 11:33:04 +00:00
|
|
|
|
2022-08-26 09:39:29 +00:00
|
|
|
strbuf_addstr(&range1, argv[0]);
|
2018-08-13 11:33:04 +00:00
|
|
|
strbuf_addstr(&range2, argv[1]);
|
2022-08-26 09:39:30 +00:00
|
|
|
|
|
|
|
strvec_pushv(&other_arg, argv +
|
|
|
|
(dash_dash < 0 ? 2 : dash_dash));
|
|
|
|
} else if (dash_dash == 1 ||
|
|
|
|
(dash_dash < 0 && argc > 0 &&
|
|
|
|
(three_dots = strstr(argv[0], "...")))) {
|
|
|
|
const char *a, *b;
|
2018-08-13 11:33:04 +00:00
|
|
|
int a_len;
|
|
|
|
|
2022-08-26 09:39:30 +00:00
|
|
|
if (dash_dash < 0)
|
|
|
|
; /* already validated arguments */
|
|
|
|
else if (!(three_dots = strstr(argv[0], "...")))
|
2022-08-26 09:39:29 +00:00
|
|
|
usage_msg_optf(_("not a symmetric range: '%s'"),
|
2022-08-26 09:39:30 +00:00
|
|
|
builtin_range_diff_usage, options,
|
|
|
|
argv[0]);
|
2018-08-13 11:33:04 +00:00
|
|
|
|
2022-08-26 09:39:30 +00:00
|
|
|
if (three_dots == argv[0]) {
|
2018-08-13 11:33:04 +00:00
|
|
|
a = "HEAD";
|
|
|
|
a_len = strlen(a);
|
2022-08-26 09:39:30 +00:00
|
|
|
} else {
|
|
|
|
a = argv[0];
|
|
|
|
a_len = (int)(three_dots - a);
|
2018-08-13 11:33:04 +00:00
|
|
|
}
|
2022-08-26 09:39:30 +00:00
|
|
|
|
|
|
|
if (three_dots[3])
|
|
|
|
b = three_dots + 3;
|
|
|
|
else
|
2018-08-13 11:33:04 +00:00
|
|
|
b = "HEAD";
|
2022-08-26 09:39:30 +00:00
|
|
|
|
2018-08-13 11:33:04 +00:00
|
|
|
strbuf_addf(&range1, "%s..%.*s", b, a_len, a);
|
|
|
|
strbuf_addf(&range2, "%.*s..%s", a_len, a, b);
|
2022-08-26 09:39:30 +00:00
|
|
|
|
|
|
|
strvec_pushv(&other_arg, argv +
|
|
|
|
(dash_dash < 0 ? 1 : dash_dash));
|
2022-08-26 09:39:29 +00:00
|
|
|
} else
|
|
|
|
usage_msg_opt(_("need two commit ranges"),
|
|
|
|
builtin_range_diff_usage, options);
|
2019-03-24 08:20:12 +00:00
|
|
|
FREE_AND_NULL(options);
|
2018-08-13 11:33:04 +00:00
|
|
|
|
2021-02-05 14:46:11 +00:00
|
|
|
range_diff_opts.dual_color = simple_color < 1;
|
2021-02-05 14:46:13 +00:00
|
|
|
range_diff_opts.left_only = left_only;
|
|
|
|
range_diff_opts.right_only = right_only;
|
2021-02-05 14:46:11 +00:00
|
|
|
res = show_range_diff(range1.buf, range2.buf, &range_diff_opts);
|
2018-08-13 11:33:04 +00:00
|
|
|
|
2020-07-28 20:24:27 +00:00
|
|
|
strvec_clear(&other_arg);
|
2018-08-13 11:33:04 +00:00
|
|
|
strbuf_release(&range1);
|
|
|
|
strbuf_release(&range2);
|
|
|
|
|
|
|
|
return res;
|
2018-08-13 11:33:02 +00:00
|
|
|
}
|