blame: honor the diff heuristic options and config

Teach "git blame" and "git annotate" the --compaction-heuristic and
--indent-heuristic options that are now supported by "git diff".

Also teach them to honor the `diff.compactionHeuristic` and
`diff.indentHeuristic` configuration options.

It would be conceivable to introduce separate configuration options for
"blame" and "annotate"; for example `blame.compactionHeuristic` and
`blame.indentHeuristic`. But it would be confusing to users if blame
output is inconsistent with diff output, so it makes more sense for them
to respect the same configuration.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Michael Haggerty 2016-09-05 11:44:53 +02:00 committed by Junio C Hamano
parent ce564eb1bd
commit 5b162879e9
8 changed files with 70 additions and 19 deletions

View file

@ -0,0 +1,7 @@
--indent-heuristic::
--no-indent-heuristic::
--compaction-heuristic::
--no-compaction-heuristic::
These are to help debugging and tuning experimental heuristics
(which are off by default) that shift diff hunk boundaries to
make patches easier to read.

View file

@ -63,13 +63,7 @@ ifndef::git-format-patch[]
Synonym for `-p --raw`.
endif::git-format-patch[]
--indent-heuristic::
--no-indent-heuristic::
--compaction-heuristic::
--no-compaction-heuristic::
These are to help debugging and tuning experimental heuristics
(which are off by default) that shift diff hunk boundaries to
make patches easier to read.
include::diff-heuristic-options.txt[]
--minimal::
Spend extra time to make sure the smallest possible

View file

@ -23,6 +23,7 @@ familiar command name for people coming from other SCM systems.
OPTIONS
-------
include::blame-options.txt[]
include::diff-heuristic-options.txt[]
SEE ALSO
--------

View file

@ -89,6 +89,8 @@ include::blame-options.txt[]
abbreviated object name, use <n>+1 digits. Note that 1 column
is used for a caret to mark the boundary commit.
include::diff-heuristic-options.txt[]
THE PORCELAIN FORMAT
--------------------

View file

@ -2221,6 +2221,8 @@ static int git_blame_config(const char *var, const char *value, void *cb)
return 0;
}
if (git_diff_heuristic_config(var, value, cb) < 0)
return -1;
if (userdiff_config(var, value) < 0)
return -1;
@ -2542,6 +2544,15 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
OPT_BIT('s', NULL, &output_option, N_("Suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
OPT_BIT('e', "show-email", &output_option, N_("Show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
OPT_BIT('w', NULL, &xdl_opts, N_("Ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
/*
* The following two options are parsed by parse_revision_opt()
* and are only included here to get included in the "-h"
* output:
*/
{ OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental indent-based heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb },
{ OPTION_LOWLEVEL_CALLBACK, 0, "compaction-heuristic", NULL, NULL, N_("Use an experimental blank-line-based heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb },
OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL),
OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")),
OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")),
@ -2588,6 +2599,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
}
parse_done:
no_whole_file_rename = !DIFF_OPT_TST(&revs.diffopt, FOLLOW_RENAMES);
xdl_opts |= revs.diffopt.xdl_opts & (XDF_COMPACTION_HEURISTIC | XDF_INDENT_HEURISTIC);
DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES);
argc = parse_options_end(&ctx);

29
diff.c
View file

@ -175,6 +175,21 @@ void init_diff_ui_defaults(void)
diff_detect_rename_default = 1;
}
int git_diff_heuristic_config(const char *var, const char *value, void *cb)
{
if (!strcmp(var, "diff.indentheuristic")) {
diff_indent_heuristic = git_config_bool(var, value);
if (diff_indent_heuristic)
diff_compaction_heuristic = 0;
}
if (!strcmp(var, "diff.compactionheuristic")) {
diff_compaction_heuristic = git_config_bool(var, value);
if (diff_compaction_heuristic)
diff_indent_heuristic = 0;
}
return 0;
}
int git_diff_ui_config(const char *var, const char *value, void *cb)
{
if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
@ -191,18 +206,6 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
diff_detect_rename_default = git_config_rename(var, value);
return 0;
}
if (!strcmp(var, "diff.indentheuristic")) {
diff_indent_heuristic = git_config_bool(var, value);
if (diff_indent_heuristic)
diff_compaction_heuristic = 0;
return 0;
}
if (!strcmp(var, "diff.compactionheuristic")) {
diff_compaction_heuristic = git_config_bool(var, value);
if (diff_compaction_heuristic)
diff_indent_heuristic = 0;
return 0;
}
if (!strcmp(var, "diff.autorefreshindex")) {
diff_auto_refresh_index = git_config_bool(var, value);
return 0;
@ -243,6 +246,8 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
return 0;
}
if (git_diff_heuristic_config(var, value, cb) < 0)
return -1;
if (git_color_config(var, value, cb) < 0)
return -1;

1
diff.h
View file

@ -266,6 +266,7 @@ extern int parse_long_opt(const char *opt, const char **argv,
const char **optarg);
extern int git_diff_basic_config(const char *var, const char *value, void *cb);
extern int git_diff_heuristic_config(const char *var, const char *value, void *cb);
extern void init_diff_ui_defaults(void);
extern int git_diff_ui_config(const char *var, const char *value, void *cb);
extern void diff_setup(struct diff_options *);

View file

@ -14,6 +14,14 @@ compare_diff () {
test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
# Compare blame output using the expectation for a diff as reference.
# Only look for the lines coming from non-boundary commits.
compare_blame () {
sed -n -e "1,4d" -e "s/^\+//p" <"$1" >.tmp-1
sed -ne "s/^[^^][^)]*) *//p" <"$2" >.tmp-2
test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
test_expect_success 'prepare' '
cat <<-\EOF >spaces.txt &&
1
@ -184,4 +192,25 @@ test_expect_success 'diff: nice functions with --indent-heuristic' '
compare_diff functions-compacted-expect out-compacted
'
test_expect_success 'blame: ugly spaces' '
git blame old..new -- spaces.txt >out-blame &&
compare_blame spaces-expect out-blame
'
test_expect_success 'blame: nice spaces with --indent-heuristic' '
git blame --indent-heuristic old..new -- spaces.txt >out-blame-compacted &&
compare_blame spaces-compacted-expect out-blame-compacted
'
test_expect_success 'blame: nice spaces with diff.indentHeuristic' '
git -c diff.indentHeuristic=true blame old..new -- spaces.txt >out-blame-compacted2 &&
compare_blame spaces-compacted-expect out-blame-compacted2
'
test_expect_success 'blame: --no-indent-heuristic overrides config' '
git -c diff.indentHeuristic=true blame --no-indent-heuristic old..new -- spaces.txt >out-blame2 &&
git blame old..new -- spaces.txt >out-blame &&
compare_blame spaces-expect out-blame2
'
test_done