mergetool: allow auto-merge for meld to follow the vim-diff behavior
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>
Lin Sun committed
May 7, 2020 at 07:31 UTC
dbd8c09bfe9d783ae01121bafb26a2dd108c0c3f
3 files changed
+96
-16
Documentation/config/mergetool.txt
+10
@@ -30,6 +30,16 @@ mergetool.meld.hasOutput::
30
to `true` tells Git to unconditionally use the `--output` option,
31
and `false` avoids using `--output`.
32
33
+mergetool.meld.useAutoMerge::
34
+ When the `--auto-merge` is given, meld will merge all non-conflicting
35
+ parts automatically, highlight the conflicting parts and wait for
36
+ user decision. Setting `mergetool.meld.useAutoMerge` to `true` tells
37
+ Git to unconditionally use the `--auto-merge` option with `meld`.
38
+ Setting this value to `auto` makes git detect whether `--auto-merge`
39
+ is supported and will only use `--auto-merge` when available. A
40
+ value of `false` avoids using `--auto-merge` altogether, and is the
41
+ default value.
42
+
43
mergetool.keepBackup::
44
After performing a merge, the original file with conflict markers
45
can be saved as a file with a `.orig` extension. If this variable
builtin/config.c
+17
@@ -65,6 +65,7 @@ static int show_scope;
65
#define TYPE_PATH 4
66
#define TYPE_EXPIRY_DATE 5
67
#define TYPE_COLOR 6
68
+#define TYPE_BOOL_OR_STR 7
69
70
#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
71
{ 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,
95
new_type = TYPE_INT;
96
else if (!strcmp(arg, "bool-or-int"))
97
new_type = TYPE_BOOL_OR_INT;
98
+ else if (!strcmp(arg, "bool-or-str"))
99
+ new_type = TYPE_BOOL_OR_STR;
100
else if (!strcmp(arg, "path"))
101
new_type = TYPE_PATH;
102
else if (!strcmp(arg, "expiry-date"))
@@ -149,6 +152,7 @@ static struct option builtin_config_options[] = {
152
OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
153
OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
154
OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
155
+ OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR),
156
OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
157
OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
158
OPT_GROUP(N_("Other")),
@@ -250,6 +254,12 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
254
strbuf_addstr(buf, v ? "true" : "false");
255
else
256
strbuf_addf(buf, "%d", v);
257
+ } else if (type == TYPE_BOOL_OR_STR) {
258
+ int v = git_parse_maybe_bool(value_);
259
+ if (v < 0)
260
+ strbuf_addstr(buf, value_);
261
+ else
262
+ strbuf_addstr(buf, v ? "true" : "false");
263
} else if (type == TYPE_PATH) {
264
const char *v;
265
if (git_config_pathname(&v, key_, value_) < 0)
@@ -411,6 +421,13 @@ static char *normalize_value(const char *key, const char *value)
421
else
422
return xstrdup(v ? "true" : "false");
423
}
424
+ if (type == TYPE_BOOL_OR_STR) {
425
+ int v = git_parse_maybe_bool(value);
426
+ if (v < 0)
427
+ return xstrdup(value);
428
+ else
429
+ return xstrdup(v ? "true" : "false");
430
+ }
431
if (type == TYPE_COLOR) {
432
char v[COLOR_MAXLEN];
433
if (git_config_color(v, key, value))
mergetools/meld
+69
-16
@@ -3,34 +3,87 @@ diff_cmd () {
3
}
4
5
merge_cmd () {
6
- if test -z "${meld_has_output_option:+set}"
6
+ check_meld_for_features
7
+
8
+ option_auto_merge=
9
+ if test "$meld_use_auto_merge_option" = true
10
then
8
- check_meld_for_output_version
11
+ option_auto_merge="--auto-merge"
12
fi
13
14
if test "$meld_has_output_option" = true
15
then
13
- "$merge_tool_path" --output="$MERGED" \
16
+ "$merge_tool_path" $option_auto_merge --output="$MERGED" \
17
"$LOCAL" "$BASE" "$REMOTE"
18
else
16
- "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
19
+ "$merge_tool_path" $option_auto_merge "$LOCAL" "$MERGED" "$REMOTE"
20
fi
21
}
22
20
-# Check whether we should use 'meld --output <file>'
21
-check_meld_for_output_version () {
22
- meld_path="$(git config mergetool.meld.path)"
23
- meld_path="${meld_path:-meld}"
23
+# Get meld help message
24
+init_meld_help_msg () {
25
+ if test -z "$meld_help_msg"
26
+ then
27
+ meld_path="$(git config mergetool.meld.path || echo meld)"
28
+ meld_help_msg=$("$meld_path" --help 2>&1)
29
+ fi
30
+}
31
25
- if meld_has_output_option=$(git config --bool mergetool.meld.hasOutput)
32
+# Check the features and set flags
33
+check_meld_for_features () {
34
+ # Check whether we should use 'meld --output <file>'
35
+ if test -z "$meld_has_output_option"
36
then
27
- : use configured value
28
- elif "$meld_path" --help 2>&1 |
29
- grep -e '--output=' -e '\[OPTION\.\.\.\]' >/dev/null
37
+ meld_has_output_option=$(git config --bool mergetool.meld.hasOutput)
38
+ case "$meld_has_output_option" in
39
+ true | false)
40
+ : use configured value
41
+ ;;
42
+ *)
43
+ : empty or invalid configured value, detecting "--output" automatically
44
+ init_meld_help_msg
45
+
46
+ case "$meld_help_msg" in
47
+ *"--output="* | *'[OPTION...]'*)
48
+ # All version that has [OPTION...] supports --output
49
+ meld_has_output_option=true
50
+ ;;
51
+ *)
52
+ meld_has_output_option=false
53
+ ;;
54
+ esac
55
+ ;;
56
+ esac
57
+ fi
58
+ # Check whether we should use 'meld --auto-merge ...'
59
+ if test -z "$meld_use_auto_merge_option"
60
then
31
- : old ones mention --output and new ones just say OPTION...
32
- meld_has_output_option=true
33
- else
34
- meld_has_output_option=false
61
+ meld_use_auto_merge_option=$(
62
+ git config --bool-or-str mergetool.meld.useAutoMerge
63
+ )
64
+ case "$meld_use_auto_merge_option" in
65
+ true | false)
66
+ : use well formatted boolean value
67
+ ;;
68
+ auto)
69
+ # testing the "--auto-merge" option only if config is "auto"
70
+ init_meld_help_msg
71
+
72
+ case "$meld_help_msg" in
73
+ *"--auto-merge"* | *'[OPTION...]'*)
74
+ meld_use_auto_merge_option=true
75
+ ;;
76
+ *)
77
+ meld_use_auto_merge_option=false
78
+ ;;
79
+ esac
80
+ ;;
81
+ "")
82
+ meld_use_auto_merge_option=false
83
+ ;;
84
+ *)
85
+ die "unknown mergetool.meld.useAutoMerge: $meld_use_auto_merge_option"
86
+ ;;
87
+ esac
88
fi
89
}