mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
![Jonathan Nieder](/assets/img/avatar_default.png)
This reverts commitf5bfcc823b
, which made "git log -m" imply "--patch" by default. The logic was that "-m", which makes diff generation for merges perform a diff against each parent, has no use unless I am viewing the diff, so we could save the user some typing by turning on display of the resulting diff automatically. That wasn't expected to adversely affect scripts because scripts would either be using a command like "git diff-tree" that already emits diffs by default or would be combining -m with a diff generation option such as --name-status. By saving typing for interactive use without adversely affecting scripts in the wild, it would be a pure improvement. The problem is that although diff generation options are only relevant for the displayed diff, a script author can imagine them affecting path limiting. For example, I might run git log -w --format=%H -- README hoping to list commits that edited README, excluding whitespace-only changes. In fact, a whitespace-only change is not TREESAME so the use of -w here has no effect (since we don't apply these diff generation flags to the diff_options struct rev_info::pruning used for this purpose), but the documentation suggests that it should work Suppose you specified foo as the <paths>. We shall call commits that modify foo !TREESAME, and the rest TREESAME. (In a diff filtered for foo, they look different and equal, respectively.) and a script author who has not tested whitespace-only changes wouldn't notice. Similarly, a script author could include git log -m --first-parent --format=%H -- README to filter the first-parent history for commits that modified README. The -m is a no-op but it reflects the script author's intent. For example, until1e20a407fe
(stash list: stop passing "-m" to "git log", 2021-05-21), "git stash list" did this. As a result, we can't safely change "-m" to imply "-p" without fear of breaking such scripts. Restore the previous behavior. Noticed because Rust's src/bootstrap/bootstrap.py made use of this same construct: https://github.com/rust-lang/rust/pull/87513. That script has been updated to omit the unnecessary "-m" option, but we can expect other scripts in the wild to have similar expectations. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
172 lines
3.9 KiB
C
172 lines
3.9 KiB
C
#include "diff-merges.h"
|
|
|
|
#include "revision.h"
|
|
|
|
typedef void (*diff_merges_setup_func_t)(struct rev_info *);
|
|
static void set_separate(struct rev_info *revs);
|
|
|
|
static diff_merges_setup_func_t set_to_default = set_separate;
|
|
static int suppress_parsing;
|
|
|
|
static void suppress(struct rev_info *revs)
|
|
{
|
|
revs->separate_merges = 0;
|
|
revs->first_parent_merges = 0;
|
|
revs->combine_merges = 0;
|
|
revs->dense_combined_merges = 0;
|
|
revs->combined_all_paths = 0;
|
|
revs->merges_imply_patch = 0;
|
|
revs->merges_need_diff = 0;
|
|
}
|
|
|
|
static void set_separate(struct rev_info *revs)
|
|
{
|
|
suppress(revs);
|
|
revs->separate_merges = 1;
|
|
}
|
|
|
|
static void set_first_parent(struct rev_info *revs)
|
|
{
|
|
set_separate(revs);
|
|
revs->first_parent_merges = 1;
|
|
}
|
|
|
|
static void set_combined(struct rev_info *revs)
|
|
{
|
|
suppress(revs);
|
|
revs->combine_merges = 1;
|
|
revs->dense_combined_merges = 0;
|
|
}
|
|
|
|
static void set_dense_combined(struct rev_info *revs)
|
|
{
|
|
suppress(revs);
|
|
revs->combine_merges = 1;
|
|
revs->dense_combined_merges = 1;
|
|
}
|
|
|
|
static diff_merges_setup_func_t func_by_opt(const char *optarg)
|
|
{
|
|
if (!strcmp(optarg, "off") || !strcmp(optarg, "none"))
|
|
return suppress;
|
|
if (!strcmp(optarg, "1") || !strcmp(optarg, "first-parent"))
|
|
return set_first_parent;
|
|
else if (!strcmp(optarg, "separate"))
|
|
return set_separate;
|
|
else if (!strcmp(optarg, "c") || !strcmp(optarg, "combined"))
|
|
return set_combined;
|
|
else if (!strcmp(optarg, "cc") || !strcmp(optarg, "dense-combined"))
|
|
return set_dense_combined;
|
|
else if (!strcmp(optarg, "m") || !strcmp(optarg, "on"))
|
|
return set_to_default;
|
|
return NULL;
|
|
}
|
|
|
|
static void set_diff_merges(struct rev_info *revs, const char *optarg)
|
|
{
|
|
diff_merges_setup_func_t func = func_by_opt(optarg);
|
|
|
|
if (!func)
|
|
die(_("unknown value for --diff-merges: %s"), optarg);
|
|
|
|
func(revs);
|
|
|
|
/* NOTE: the merges_need_diff flag is cleared by func() call */
|
|
if (func != suppress)
|
|
revs->merges_need_diff = 1;
|
|
}
|
|
|
|
/*
|
|
* Public functions. They are in the order they are called.
|
|
*/
|
|
|
|
int diff_merges_config(const char *value)
|
|
{
|
|
diff_merges_setup_func_t func = func_by_opt(value);
|
|
|
|
if (!func)
|
|
return -1;
|
|
|
|
set_to_default = func;
|
|
return 0;
|
|
}
|
|
|
|
void diff_merges_suppress_options_parsing(void)
|
|
{
|
|
suppress_parsing = 1;
|
|
}
|
|
|
|
int diff_merges_parse_opts(struct rev_info *revs, const char **argv)
|
|
{
|
|
int argcount = 1;
|
|
const char *optarg;
|
|
const char *arg = argv[0];
|
|
|
|
if (suppress_parsing)
|
|
return 0;
|
|
|
|
if (!strcmp(arg, "-m")) {
|
|
set_to_default(revs);
|
|
} else if (!strcmp(arg, "-c")) {
|
|
set_combined(revs);
|
|
revs->merges_imply_patch = 1;
|
|
} else if (!strcmp(arg, "--cc")) {
|
|
set_dense_combined(revs);
|
|
revs->merges_imply_patch = 1;
|
|
} else if (!strcmp(arg, "--no-diff-merges")) {
|
|
suppress(revs);
|
|
} else if (!strcmp(arg, "--combined-all-paths")) {
|
|
revs->combined_all_paths = 1;
|
|
} else if ((argcount = parse_long_opt("diff-merges", argv, &optarg))) {
|
|
set_diff_merges(revs, optarg);
|
|
} else
|
|
return 0;
|
|
|
|
revs->explicit_diff_merges = 1;
|
|
return argcount;
|
|
}
|
|
|
|
void diff_merges_suppress(struct rev_info *revs)
|
|
{
|
|
suppress(revs);
|
|
}
|
|
|
|
void diff_merges_default_to_first_parent(struct rev_info *revs)
|
|
{
|
|
if (!revs->explicit_diff_merges)
|
|
revs->separate_merges = 1;
|
|
if (revs->separate_merges)
|
|
revs->first_parent_merges = 1;
|
|
}
|
|
|
|
void diff_merges_default_to_dense_combined(struct rev_info *revs)
|
|
{
|
|
if (!revs->explicit_diff_merges)
|
|
set_dense_combined(revs);
|
|
}
|
|
|
|
void diff_merges_set_dense_combined_if_unset(struct rev_info *revs)
|
|
{
|
|
if (!revs->combine_merges)
|
|
set_dense_combined(revs);
|
|
}
|
|
|
|
void diff_merges_setup_revs(struct rev_info *revs)
|
|
{
|
|
if (suppress_parsing)
|
|
return;
|
|
|
|
if (revs->combine_merges == 0)
|
|
revs->dense_combined_merges = 0;
|
|
if (revs->separate_merges == 0)
|
|
revs->first_parent_merges = 0;
|
|
if (revs->combined_all_paths && !revs->combine_merges)
|
|
die("--combined-all-paths makes no sense without -c or --cc");
|
|
if (revs->merges_imply_patch)
|
|
revs->diff = 1;
|
|
if (revs->merges_imply_patch || revs->merges_need_diff) {
|
|
if (!revs->diffopt.output_format)
|
|
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
|
|
}
|
|
}
|