]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mergetool: allow auto-merge for meld to follow the vim-diff behavior
authorLin Sun <lin.sun@zoom.us>
Wed, 6 May 2020 23:31:14 +0000 (07:31 +0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 17 Sep 2020 00:11:20 +0000 (17:11 -0700)
Make the mergetool used with "meld" backend behave similarly to "vimdiff" by
telling it to auto-merge non-conflicting parts and highlight the conflicting
parts when `mergetool.meld.useAutoMerge` is configured with `true`, or `auto`
for detecting the `--auto-merge` option automatically.

Helped-by: Đoàn Trần Công Danh <congdanhqx@gmail.com>
Helped-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Lin Sun <lin.sun@zoom.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config/mergetool.txt
builtin/config.c
mergetools/meld

index 09ed31dbfa9ce17a0080405658e07ff4bfcb2457..16a27443a3edc1d1a1f25ea03bad04896caa59c8 100644 (file)
@@ -30,6 +30,16 @@ mergetool.meld.hasOutput::
        to `true` tells Git to unconditionally use the `--output` option,
        and `false` avoids using `--output`.
 
+mergetool.meld.useAutoMerge::
+       When the `--auto-merge` is given, meld will merge all non-conflicting
+       parts automatically, highlight the conflicting parts and wait for
+       user decision.  Setting `mergetool.meld.useAutoMerge` to `true` tells
+       Git to unconditionally use the `--auto-merge` option with `meld`.
+       Setting this value to `auto` makes git detect whether `--auto-merge`
+       is supported and will only use `--auto-merge` when available.  A
+       value of `false` avoids using `--auto-merge` altogether, and is the
+       default value.
+
 mergetool.keepBackup::
        After performing a merge, the original file with conflict markers
        can be saved as a file with a `.orig` extension.  If this variable
index ee4aef6a3555765a9ed74263d68c765ba8431f85..7891e070a42ed9e27e39e08b4364fa394358f9be 100644 (file)
@@ -65,6 +65,7 @@ static int show_scope;
 #define TYPE_PATH              4
 #define TYPE_EXPIRY_DATE       5
 #define TYPE_COLOR             6
+#define TYPE_BOOL_OR_STR       7
 
 #define OPT_CALLBACK_VALUE(s, l, v, h, i) \
        { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
@@ -94,6 +95,8 @@ static int option_parse_type(const struct option *opt, const char *arg,
                        new_type = TYPE_INT;
                else if (!strcmp(arg, "bool-or-int"))
                        new_type = TYPE_BOOL_OR_INT;
+               else if (!strcmp(arg, "bool-or-str"))
+                       new_type = TYPE_BOOL_OR_STR;
                else if (!strcmp(arg, "path"))
                        new_type = TYPE_PATH;
                else if (!strcmp(arg, "expiry-date"))
@@ -149,6 +152,7 @@ static struct option builtin_config_options[] = {
        OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
        OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
        OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
+       OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR),
        OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
        OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
        OPT_GROUP(N_("Other")),
@@ -250,6 +254,12 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
                                strbuf_addstr(buf, v ? "true" : "false");
                        else
                                strbuf_addf(buf, "%d", v);
+               } else if (type == TYPE_BOOL_OR_STR) {
+                       int v = git_parse_maybe_bool(value_);
+                       if (v < 0)
+                               strbuf_addstr(buf, value_);
+                       else
+                               strbuf_addstr(buf, v ? "true" : "false");
                } else if (type == TYPE_PATH) {
                        const char *v;
                        if (git_config_pathname(&v, key_, value_) < 0)
@@ -411,6 +421,13 @@ static char *normalize_value(const char *key, const char *value)
                else
                        return xstrdup(v ? "true" : "false");
        }
+       if (type == TYPE_BOOL_OR_STR) {
+               int v = git_parse_maybe_bool(value);
+               if (v < 0)
+                       return xstrdup(value);
+               else
+                       return xstrdup(v ? "true" : "false");
+       }
        if (type == TYPE_COLOR) {
                char v[COLOR_MAXLEN];
                if (git_config_color(v, key, value))
index 7a08470f8836e14824a215b29e0c3a5dbeba9c17..aab4ebb9355ae946f1c7b289569f1892ea29e583 100644 (file)
@@ -3,34 +3,87 @@ diff_cmd () {
 }
 
 merge_cmd () {
-       if test -z "${meld_has_output_option:+set}"
+       check_meld_for_features
+
+       option_auto_merge=
+       if test "$meld_use_auto_merge_option" = true
        then
-               check_meld_for_output_version
+               option_auto_merge="--auto-merge"
        fi
 
        if test "$meld_has_output_option" = true
        then
-               "$merge_tool_path" --output="$MERGED" \
+               "$merge_tool_path" $option_auto_merge --output="$MERGED" \
                        "$LOCAL" "$BASE" "$REMOTE"
        else
-               "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
+               "$merge_tool_path" $option_auto_merge "$LOCAL" "$MERGED" "$REMOTE"
        fi
 }
 
-# Check whether we should use 'meld --output <file>'
-check_meld_for_output_version () {
-       meld_path="$(git config mergetool.meld.path)"
-       meld_path="${meld_path:-meld}"
+# Get meld help message
+init_meld_help_msg () {
+       if test -z "$meld_help_msg"
+       then
+               meld_path="$(git config mergetool.meld.path || echo meld)"
+               meld_help_msg=$("$meld_path" --help 2>&1)
+       fi
+}
 
-       if meld_has_output_option=$(git config --bool mergetool.meld.hasOutput)
+# Check the features and set flags
+check_meld_for_features () {
+       # Check whether we should use 'meld --output <file>'
+       if test -z "$meld_has_output_option"
        then
-               : use configured value
-       elif "$meld_path" --help 2>&1 |
-               grep -e '--output=' -e '\[OPTION\.\.\.\]' >/dev/null
+               meld_has_output_option=$(git config --bool mergetool.meld.hasOutput)
+               case "$meld_has_output_option" in
+               true | false)
+                       : use configured value
+                       ;;
+               *)
+                       : empty or invalid configured value, detecting "--output" automatically
+                       init_meld_help_msg
+
+                       case "$meld_help_msg" in
+                       *"--output="* | *'[OPTION...]'*)
+                               # All version that has [OPTION...] supports --output
+                               meld_has_output_option=true
+                               ;;
+                       *)
+                               meld_has_output_option=false
+                               ;;
+                       esac
+                       ;;
+               esac
+       fi
+       # Check whether we should use 'meld --auto-merge ...'
+       if test -z "$meld_use_auto_merge_option"
        then
-               : old ones mention --output and new ones just say OPTION...
-               meld_has_output_option=true
-       else
-               meld_has_output_option=false
+               meld_use_auto_merge_option=$(
+                       git config --bool-or-str mergetool.meld.useAutoMerge
+               )
+               case "$meld_use_auto_merge_option" in
+               true | false)
+                       : use well formatted boolean value
+                       ;;
+               auto)
+                       # testing the "--auto-merge" option only if config is "auto"
+                       init_meld_help_msg
+
+                       case "$meld_help_msg" in
+                       *"--auto-merge"* | *'[OPTION...]'*)
+                               meld_use_auto_merge_option=true
+                               ;;
+                       *)
+                               meld_use_auto_merge_option=false
+                               ;;
+                       esac
+                       ;;
+               "")
+                       meld_use_auto_merge_option=false
+                       ;;
+               *)
+                       die "unknown mergetool.meld.useAutoMerge: $meld_use_auto_merge_option"
+                       ;;
+               esac
        fi
 }