diff: Introduce --diff-algorithm command line option

Since command line options have higher priority than config file variables and taking previous commit into account, we need a way how to specify myers algorithm on command line. However, inventing `--myers` is not the right answer. We need far more general option, and that is `--diff-algorithm`. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michal Privoznik committed Jan 16, 2013 at 08:51 UTC 07924d4d50e5304fb53eb60aaba8aef31d4c4e5e
5 files changed +53 -1
Documentation/diff-options.txt
+20
@@ -55,6 +55,26 @@ endif::git-format-patch[]
55 --histogram::
56 Generate a diff using the "histogram diff" algorithm.
57
58 +--diff-algorithm={patience|minimal|histogram|myers}::
59 + Choose a diff algorithm. The variants are as follows:
60 ++
61 +--
62 +`default`, `myers`;;
63 + The basic greedy diff algorithm. Currently, this is the default.
64 +`minimal`;;
65 + Spend extra time to make sure the smallest possible diff is
66 + produced.
67 +`patience`;;
68 + Use "patience diff" algorithm when generating patches.
69 +`histogram`;;
70 + This algorithm extends the patience algorithm to "support
71 + low-occurrence common elements".
72 +--
73 ++
74 +For instance, if you configured diff.algorithm variable to a
75 +non-default value and want to use the default one, then you
76 +have to use `--diff-algorithm=default` option.
77 +
78 --stat[=<width>[,<name-width>[,<count>]]]::
79 Generate a diffstat. By default, as much space as necessary
80 will be used for the filename part, and the rest for the graph
contrib/completion/git-completion.bash
+11
@@ -1021,6 +1021,8 @@ _git_describe ()
1021 __gitcomp_nl "$(__git_refs)"
1022 }
1023
1024 +__git_diff_algorithms="myers minimal patience histogram"
1025 +
1026 __git_diff_common_options="--stat --numstat --shortstat --summary
1027 --patch-with-stat --name-only --name-status --color
1028 --no-color --color-words --no-renames --check
@@ -1035,6 +1037,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
1037 --raw
1038 --dirstat --dirstat= --dirstat-by-file
1039 --dirstat-by-file= --cumulative
1040 + --diff-algorithm=
1041 "
1042
1043 _git_diff ()
@@ -1042,6 +1045,10 @@ _git_diff ()
1045 __git_has_doubledash && return
1046
1047 case "$cur" in
1048 + --diff-algorithm=*)
1049 + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
1050 + return
1051 + ;;
1052 --*)
1053 __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
1054 --base --ours --theirs --no-index
@@ -2114,6 +2121,10 @@ _git_show ()
2121 " "" "${cur#*=}"
2122 return
2123 ;;
2124 + --diff-algorithm=*)
2125 + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
2126 + return
2127 + ;;
2128 --*)
2129 __gitcomp "--pretty= --format= --abbrev-commit --oneline
2130 $__git_diff_common_options
diff.c
+11 -1
@@ -144,7 +144,7 @@ static int git_config_rename(const char *var, const char *value)
144 return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
145 }
146
147 -static long parse_algorithm_value(const char *value)
147 +long parse_algorithm_value(const char *value)
148 {
149 if (!value)
150 return -1;
@@ -3634,6 +3634,16 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3634 options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
3635 else if (!strcmp(arg, "--histogram"))
3636 options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
3637 + else if (!prefixcmp(arg, "--diff-algorithm=")) {
3638 + long value = parse_algorithm_value(arg+17);
3639 + if (value < 0)
3640 + return error("option diff-algorithm accepts \"myers\", "
3641 + "\"minimal\", \"patience\" and \"histogram\"");
3642 + /* clear out previous settings */
3643 + DIFF_XDL_CLR(options, NEED_MINIMAL);
3644 + options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
3645 + options->xdl_opts |= value;
3646 + }
3647
3648 /* flags options */
3649 else if (!strcmp(arg, "--binary")) {
diff.h
+2
@@ -333,6 +333,8 @@ extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
333
334 extern int parse_rename_score(const char **cp_p);
335
336 +extern long parse_algorithm_value(const char *value);
337 +
338 extern int print_stat_summary(FILE *fp, int files,
339 int insertions, int deletions);
340 extern void setup_diff_pager(struct diff_options *);
merge-recursive.c
+9
@@ -2068,6 +2068,15 @@ int parse_merge_opt(struct merge_options *o, const char *s)
2068 o->xdl_opts = DIFF_WITH_ALG(o, PATIENCE_DIFF);
2069 else if (!strcmp(s, "histogram"))
2070 o->xdl_opts = DIFF_WITH_ALG(o, HISTOGRAM_DIFF);
2071 + else if (!strcmp(s, "diff-algorithm=")) {
2072 + long value = parse_algorithm_value(s+15);
2073 + if (value < 0)
2074 + return -1;
2075 + /* clear out previous settings */
2076 + DIFF_XDL_CLR(o, NEED_MINIMAL);
2077 + o->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
2078 + o->xdl_opts |= value;
2079 + }
2080 else if (!strcmp(s, "ignore-space-change"))
2081 o->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
2082 else if (!strcmp(s, "ignore-all-space"))