Skip to content

Commit 9d8370d

Browse files
committed
Merge branch 'tk/mergetool-gui-default-config'
"git mergetool" and "git difftool" learns a new configuration guiDefault to optionally favor configured guitool over non-gui-tool automatically when $DISPLAY is set. * tk/mergetool-gui-default-config: mergetool: new config guiDefault supports auto-toggling gui by DISPLAY
2 parents d47ee0a + 42943b9 commit 9d8370d

File tree

10 files changed

+179
-14
lines changed

10 files changed

+179
-14
lines changed

Documentation/config/difftool.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,10 @@ See the `--trust-exit-code` option in linkgit:git-difftool[1] for more details.
3434

3535
difftool.prompt::
3636
Prompt before each invocation of the diff tool.
37+
38+
difftool.guiDefault::
39+
Set `true` to use the `diff.guitool` by default (equivalent to specifying
40+
the `--gui` argument), or `auto` to select `diff.guitool` or `diff.tool`
41+
depending on the presence of a `DISPLAY` environment variable value. The
42+
default is `false`, where the `--gui` argument must be provided
43+
explicitly for the `diff.guitool` to be used.

Documentation/config/mergetool.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,10 @@ mergetool.writeToTemp::
8585

8686
mergetool.prompt::
8787
Prompt before each invocation of the merge resolution program.
88+
89+
mergetool.guiDefault::
90+
Set `true` to use the `merge.guitool` by default (equivalent to
91+
specifying the `--gui` argument), or `auto` to select `merge.guitool`
92+
or `merge.tool` depending on the presence of a `DISPLAY` environment
93+
variable value. The default is `false`, where the `--gui` argument
94+
must be provided explicitly for the `merge.guitool` to be used.

Documentation/git-difftool.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ instead. `--no-symlinks` is the default on Windows.
9797
--[no-]gui::
9898
When 'git-difftool' is invoked with the `-g` or `--gui` option
9999
the default diff tool will be read from the configured
100-
`diff.guitool` variable instead of `diff.tool`. The `--no-gui`
101-
option can be used to override this setting. If `diff.guitool`
102-
is not set, we will fallback in the order of `merge.guitool`,
103-
`diff.tool`, `merge.tool` until a tool is found.
100+
`diff.guitool` variable instead of `diff.tool`. This may be
101+
selected automatically using the configuration variable
102+
`difftool.guiDefault`. The `--no-gui` option can be used to
103+
override these settings. If `diff.guitool` is not set, we will
104+
fallback in the order of `merge.guitool`, `diff.tool`,
105+
`merge.tool` until a tool is found.
104106

105107
--[no-]trust-exit-code::
106108
'git-difftool' invokes a diff tool individually on each file.

Documentation/git-mergetool.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ success of the resolution after the custom tool has exited.
8585
the default merge tool will be read from the configured
8686
`merge.guitool` variable instead of `merge.tool`. If
8787
`merge.guitool` is not set, we will fallback to the tool
88-
configured under `merge.tool`.
88+
configured under `merge.tool`. This may be autoselected using
89+
the configuration variable `mergetool.guiDefault`.
8990

9091
--no-gui::
91-
This overrides a previous `-g` or `--gui` setting and reads the
92-
default merge tool will be read from the configured `merge.tool`
93-
variable.
92+
This overrides a previous `-g` or `--gui` setting or
93+
`mergetool.guiDefault` configuration and reads the default merge
94+
tool from the configured `merge.tool` variable.
9495

9596
-O<orderfile>::
9697
Process files in the order specified in the

builtin/difftool.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ static int run_file_diff(int prompt, const char *prefix,
691691

692692
int cmd_difftool(int argc, const char **argv, const char *prefix)
693693
{
694-
int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
694+
int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0,
695695
tool_help = 0, no_index = 0;
696696
static char *difftool_cmd = NULL, *extcmd = NULL;
697697
struct option builtin_difftool_options[] = {
@@ -741,13 +741,21 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
741741
} else if (dir_diff)
742742
die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
743743

744-
die_for_incompatible_opt3(use_gui_tool, "--gui",
744+
die_for_incompatible_opt3(use_gui_tool == 1, "--gui",
745745
!!difftool_cmd, "--tool",
746746
!!extcmd, "--extcmd");
747747

748-
if (use_gui_tool)
748+
/*
749+
* Explicitly specified GUI option is forwarded to git-mergetool--lib.sh;
750+
* empty or unset means "use the difftool.guiDefault config or default to
751+
* false".
752+
*/
753+
if (use_gui_tool == 1)
749754
setenv("GIT_MERGETOOL_GUI", "true", 1);
750-
else if (difftool_cmd) {
755+
else if (use_gui_tool == 0)
756+
setenv("GIT_MERGETOOL_GUI", "false", 1);
757+
758+
if (difftool_cmd) {
751759
if (*difftool_cmd)
752760
setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
753761
else

git-difftool--helper.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ then
7575
merge_tool="$GIT_DIFF_TOOL"
7676
else
7777
merge_tool="$(get_merge_tool)"
78+
subshell_exit_status=$?
79+
if test $subshell_exit_status -gt 1
80+
then
81+
exit $subshell_exit_status
82+
fi
7883
fi
7984
fi
8085

git-mergetool--lib.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,42 @@ merge_mode () {
9797
test "$TOOL_MODE" = merge
9898
}
9999

100+
get_gui_default () {
101+
if diff_mode
102+
then
103+
GUI_DEFAULT_KEY="difftool.guiDefault"
104+
else
105+
GUI_DEFAULT_KEY="mergetool.guiDefault"
106+
fi
107+
GUI_DEFAULT_CONFIG_LCASE=$(git config --default false --get "$GUI_DEFAULT_KEY" | tr 'A-Z' 'a-z')
108+
if test "$GUI_DEFAULT_CONFIG_LCASE" = "auto"
109+
then
110+
if test -n "$DISPLAY"
111+
then
112+
GUI_DEFAULT=true
113+
else
114+
GUI_DEFAULT=false
115+
fi
116+
else
117+
GUI_DEFAULT=$(git config --default false --bool --get "$GUI_DEFAULT_KEY")
118+
subshell_exit_status=$?
119+
if test $subshell_exit_status -ne 0
120+
then
121+
exit $subshell_exit_status
122+
fi
123+
fi
124+
echo $GUI_DEFAULT
125+
}
126+
100127
gui_mode () {
128+
if test -z "$GIT_MERGETOOL_GUI"
129+
then
130+
GIT_MERGETOOL_GUI=$(get_gui_default)
131+
if test $? -ne 0
132+
then
133+
exit 2
134+
fi
135+
fi
101136
test "$GIT_MERGETOOL_GUI" = true
102137
}
103138

@@ -467,6 +502,11 @@ get_merge_tool () {
467502
is_guessed=false
468503
# Check if a merge tool has been configured
469504
merge_tool=$(get_configured_merge_tool)
505+
subshell_exit_status=$?
506+
if test $subshell_exit_status -gt "1"
507+
then
508+
exit $subshell_exit_status
509+
fi
470510
# Try to guess an appropriate merge tool if no tool has been set.
471511
if test -z "$merge_tool"
472512
then

git-mergetool.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ print_noop_and_exit () {
451451

452452
main () {
453453
prompt=$(git config --bool mergetool.prompt)
454-
GIT_MERGETOOL_GUI=false
454+
GIT_MERGETOOL_GUI=
455455
guessed_merge_tool=false
456456
orderfile=
457457

@@ -511,9 +511,14 @@ main () {
511511

512512
if test -z "$merge_tool"
513513
then
514-
if ! merge_tool=$(get_merge_tool)
514+
merge_tool=$(get_merge_tool)
515+
subshell_exit_status=$?
516+
if test $subshell_exit_status = 1
515517
then
516518
guessed_merge_tool=true
519+
elif test $subshell_exit_status -gt 1
520+
then
521+
exit $subshell_exit_status
517522
fi
518523
fi
519524
merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"

t/t7610-mergetool.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,4 +860,42 @@ test_expect_success 'mergetool hideResolved' '
860860
git commit -m "test resolved with mergetool"
861861
'
862862

863+
test_expect_success 'mergetool with guiDefault' '
864+
test_config merge.guitool myguitool &&
865+
test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" &&
866+
test_config mergetool.myguitool.trustExitCode true &&
867+
test_when_finished "git reset --hard" &&
868+
git checkout -b test$test_count branch1 &&
869+
git submodule update -N &&
870+
test_must_fail git merge main &&
871+
872+
test_config mergetool.guiDefault auto &&
873+
DISPLAY=SOMETHING && export DISPLAY &&
874+
yes "" | git mergetool both &&
875+
yes "" | git mergetool file1 file1 &&
876+
877+
DISPLAY= && export DISPLAY &&
878+
yes "" | git mergetool file2 "spaced name" &&
879+
880+
test_config mergetool.guiDefault true &&
881+
yes "" | git mergetool subdir/file3 &&
882+
883+
yes "d" | git mergetool file11 &&
884+
yes "d" | git mergetool file12 &&
885+
yes "l" | git mergetool submod &&
886+
887+
echo "gui main updated" >expect &&
888+
test_cmp expect file1 &&
889+
890+
echo "main new" >expect &&
891+
test_cmp expect file2 &&
892+
893+
echo "gui main new sub" >expect &&
894+
test_cmp expect subdir/file3 &&
895+
896+
echo "branch1 submodule" >expect &&
897+
test_cmp expect submod/bar &&
898+
git commit -m "branch1 resolved with mergetool"
899+
'
900+
863901
test_done

t/t7800-difftool.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,58 @@ test_expect_success 'difftool honors --gui' '
155155
test_cmp expect actual
156156
'
157157

158+
test_expect_success 'difftool with guiDefault auto selects gui tool when there is DISPLAY' '
159+
difftool_test_setup &&
160+
test_config merge.tool bogus-tool &&
161+
test_config diff.tool bogus-tool &&
162+
test_config diff.guitool test-tool &&
163+
test_config difftool.guiDefault auto &&
164+
DISPLAY=SOMETHING && export DISPLAY &&
165+
166+
echo branch >expect &&
167+
git difftool --no-prompt branch >actual &&
168+
test_cmp expect actual
169+
'
170+
test_expect_success 'difftool with guiDefault auto selects regular tool when no DISPLAY' '
171+
difftool_test_setup &&
172+
test_config diff.guitool bogus-tool &&
173+
test_config diff.tool test-tool &&
174+
test_config difftool.guiDefault Auto &&
175+
DISPLAY= && export DISPLAY &&
176+
177+
echo branch >expect &&
178+
git difftool --no-prompt branch >actual &&
179+
test_cmp expect actual
180+
'
181+
182+
test_expect_success 'difftool with guiDefault true selects gui tool' '
183+
difftool_test_setup &&
184+
test_config diff.tool bogus-tool &&
185+
test_config diff.guitool test-tool &&
186+
test_config difftool.guiDefault true &&
187+
188+
DISPLAY= && export DISPLAY &&
189+
echo branch >expect &&
190+
git difftool --no-prompt branch >actual &&
191+
test_cmp expect actual &&
192+
193+
DISPLAY=Something && export DISPLAY &&
194+
echo branch >expect &&
195+
git difftool --no-prompt branch >actual &&
196+
test_cmp expect actual
197+
'
198+
199+
test_expect_success 'difftool --no-gui trumps config guiDefault' '
200+
difftool_test_setup &&
201+
test_config diff.guitool bogus-tool &&
202+
test_config diff.tool test-tool &&
203+
test_config difftool.guiDefault true &&
204+
205+
echo branch >expect &&
206+
git difftool --no-prompt --no-gui branch >actual &&
207+
test_cmp expect actual
208+
'
209+
158210
test_expect_success 'difftool --gui last setting wins' '
159211
difftool_test_setup &&
160212
: >expect &&

0 commit comments

Comments
 (0)