Merge branch 'so/log-diff-merge'

"git log" learned "--diff-merges=<style>" option, with an
associated configuration variable log.diffMerges.

* so/log-diff-merge:
  doc/diff-options: document new --diff-merges features
  diff-merges: introduce log.diffMerges config variable
  diff-merges: adapt -m to enable default diff format
  diff-merges: refactor set_diff_merges()
  diff-merges: introduce --diff-merges=on
This commit is contained in:
Junio C Hamano 2021-04-30 13:50:26 +09:00
Родитель 8e97852919 364bc11fe5
Коммит 59bb0aa93e
7 изменённых файлов: 96 добавлений и 22 удалений

Просмотреть файл

@ -24,6 +24,11 @@ log.excludeDecoration::
the config option can be overridden by the `--decorate-refs` the config option can be overridden by the `--decorate-refs`
option. option.
log.diffMerges::
Set default diff format to be used for merge commits. See
`--diff-merges` in linkgit:git-log[1] for details.
Defaults to `separate`.
log.follow:: log.follow::
If `true`, `git log` will act as if the `--follow` option was used when If `true`, `git log` will act as if the `--follow` option was used when
a single <path> is given. This has the same limitations as `--follow`, a single <path> is given. This has the same limitations as `--follow`,

Просмотреть файл

@ -34,7 +34,7 @@ endif::git-diff[]
endif::git-format-patch[] endif::git-format-patch[]
ifdef::git-log[] ifdef::git-log[]
--diff-merges=(off|none|first-parent|1|separate|m|combined|c|dense-combined|cc):: --diff-merges=(off|none|on|first-parent|1|separate|m|combined|c|dense-combined|cc)::
--no-diff-merges:: --no-diff-merges::
Specify diff format to be used for merge commits. Default is Specify diff format to be used for merge commits. Default is
{diff-merges-default} unless `--first-parent` is in use, in which case {diff-merges-default} unless `--first-parent` is in use, in which case
@ -45,17 +45,24 @@ ifdef::git-log[]
Disable output of diffs for merge commits. Useful to override Disable output of diffs for merge commits. Useful to override
implied value. implied value.
+ +
--diff-merges=on:::
--diff-merges=m:::
-m:::
This option makes diff output for merge commits to be shown in
the default format. `-m` will produce the output only if `-p`
is given as well. The default format could be changed using
`log.diffMerges` configuration parameter, which default value
is `separate`.
+
--diff-merges=first-parent::: --diff-merges=first-parent:::
--diff-merges=1::: --diff-merges=1:::
This option makes merge commits show the full diff with This option makes merge commits show the full diff with
respect to the first parent only. respect to the first parent only.
+ +
--diff-merges=separate::: --diff-merges=separate:::
--diff-merges=m:::
-m:::
This makes merge commits show the full diff with respect to This makes merge commits show the full diff with respect to
each of the parents. Separate log entry and diff is generated each of the parents. Separate log entry and diff is generated
for each parent. `-m` doesn't produce any output without `-p`. for each parent.
+ +
--diff-merges=combined::: --diff-merges=combined:::
--diff-merges=c::: --diff-merges=c:::

Просмотреть файл

@ -481,6 +481,8 @@ static int git_log_config(const char *var, const char *value, void *cb)
decoration_style = 0; /* maybe warn? */ decoration_style = 0; /* maybe warn? */
return 0; return 0;
} }
if (!strcmp(var, "log.diffmerges"))
return diff_merges_config(value);
if (!strcmp(var, "log.showroot")) { if (!strcmp(var, "log.showroot")) {
default_show_root = git_config_bool(var, value); default_show_root = git_config_bool(var, value);
return 0; return 0;

Просмотреть файл

@ -2,6 +2,11 @@
#include "revision.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 void suppress(struct rev_info *revs) static void suppress(struct rev_info *revs)
{ {
revs->separate_merges = 0; revs->separate_merges = 0;
@ -29,10 +34,10 @@ static void set_m(struct rev_info *revs)
{ {
/* /*
* To "diff-index", "-m" means "match missing", and to the "log" * To "diff-index", "-m" means "match missing", and to the "log"
* family of commands, it means "show full diff for merges". Set * family of commands, it means "show default diff for merges". Set
* both fields appropriately. * both fields appropriately.
*/ */
set_separate(revs); set_to_default(revs);
revs->match_missing = 1; revs->match_missing = 1;
} }
@ -50,33 +55,52 @@ static void set_dense_combined(struct rev_info *revs)
revs->dense_combined_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) static void set_diff_merges(struct rev_info *revs, const char *optarg)
{ {
if (!strcmp(optarg, "off") || !strcmp(optarg, "none")) { diff_merges_setup_func_t func = func_by_opt(optarg);
suppress(revs);
/* Return early to leave revs->merges_need_diff unset */
return;
}
if (!strcmp(optarg, "1") || !strcmp(optarg, "first-parent")) if (!func)
set_first_parent(revs);
else if (!strcmp(optarg, "m") || !strcmp(optarg, "separate"))
set_separate(revs);
else if (!strcmp(optarg, "c") || !strcmp(optarg, "combined"))
set_combined(revs);
else if (!strcmp(optarg, "cc") || !strcmp(optarg, "dense-combined"))
set_dense_combined(revs);
else
die(_("unknown value for --diff-merges: %s"), optarg); die(_("unknown value for --diff-merges: %s"), optarg);
/* The flag is cleared by set_xxx() functions, so don't move this up */ func(revs);
revs->merges_need_diff = 1;
/* 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. * 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;
}
int diff_merges_parse_opts(struct rev_info *revs, const char **argv) int diff_merges_parse_opts(struct rev_info *revs, const char **argv)
{ {
int argcount = 1; int argcount = 1;

Просмотреть файл

@ -9,6 +9,8 @@
struct rev_info; struct rev_info;
int diff_merges_config(const char *value);
int diff_merges_parse_opts(struct rev_info *revs, const char **argv); int diff_merges_parse_opts(struct rev_info *revs, const char **argv);
void diff_merges_suppress(struct rev_info *revs); void diff_merges_suppress(struct rev_info *revs);

Просмотреть файл

@ -452,6 +452,37 @@ diff-tree --stat --compact-summary initial mode
diff-tree -R --stat --compact-summary initial mode diff-tree -R --stat --compact-summary initial mode
EOF EOF
test_expect_success 'log --diff-merges=on matches --diff-merges=separate' '
git log -p --diff-merges=separate master >result &&
process_diffs result >expected &&
git log -p --diff-merges=on master >result &&
process_diffs result >actual &&
test_cmp expected actual
'
test_expect_success 'deny wrong log.diffMerges config' '
test_config log.diffMerges wrong-value &&
test_expect_code 128 git log
'
test_expect_success 'git config log.diffMerges first-parent' '
git log -p --diff-merges=first-parent master >result &&
process_diffs result >expected &&
test_config log.diffMerges first-parent &&
git log -p --diff-merges=on master >result &&
process_diffs result >actual &&
test_cmp expected actual
'
test_expect_success 'git config log.diffMerges first-parent vs -m' '
git log -p --diff-merges=first-parent master >result &&
process_diffs result >expected &&
test_config log.diffMerges first-parent &&
git log -p -m master >result &&
process_diffs result >actual &&
test_cmp expected actual
'
test_expect_success 'log -S requires an argument' ' test_expect_success 'log -S requires an argument' '
test_must_fail git log -S test_must_fail git log -S
' '

Просмотреть файл

@ -2306,6 +2306,7 @@ test_expect_success 'git config - variable name' '
test_completion "git config log.d" <<-\EOF test_completion "git config log.d" <<-\EOF
log.date Z log.date Z
log.decorate Z log.decorate Z
log.diffMerges Z
EOF EOF
' '
@ -2327,6 +2328,7 @@ test_expect_success 'git -c - variable name' '
test_completion "git -c log.d" <<-\EOF test_completion "git -c log.d" <<-\EOF
log.date=Z log.date=Z
log.decorate=Z log.decorate=Z
log.diffMerges=Z
EOF EOF
' '
@ -2348,6 +2350,7 @@ test_expect_success 'git clone --config= - variable name' '
test_completion "git clone --config=log.d" <<-\EOF test_completion "git clone --config=log.d" <<-\EOF
log.date=Z log.date=Z
log.decorate=Z log.decorate=Z
log.diffMerges=Z
EOF EOF
' '