mergetool: new config guiDefault supports auto-toggling gui by DISPLAY
When no merge.tool or diff.tool is configured or manually selected, the selection of a default tool is sensitive to the DISPLAY variable; in a GUI session a gui-specific tool will be proposed if found, and otherwise a terminal-based one. This "GUI-optimizing" behavior is important because a GUI can make a huge difference to a user's ability to understand and correctly complete a non-trivial conflicting merge. Some time ago the merge.guitool and diff.guitool config options were introduced to enable users to configure both a GUI tool, and a non-GUI tool (with fallback if no GUI tool configured), in the same environment. Unfortunately, the --gui argument introduced to support the selection of the guitool is still explicit. When using configured tools, there is no equivalent of the no-tool-configured "propose a GUI tool if we are in a GUI environment" behavior. As proposed in <xmqqmtb8jsej.fsf@gitster.g>, introduce new configuration options, difftool.guiDefault and mergetool.guiDefault, supporting a special value "auto" which causes the corresponding tool or guitool to be selected depending on the presence of a non-empty DISPLAY value. Also support "true" to say "default to the guitool (unless --no-gui is passed on the commandline)", and "false" as the previous default behavior when these new configuration options are not specified. Signed-off-by: Tao Klerks <tao@klerks.biz> Acked-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
ae73b2c8f1
commit
42943b950e
@ -34,3 +34,10 @@ See the `--trust-exit-code` option in linkgit:git-difftool[1] for more details.
|
|||||||
|
|
||||||
difftool.prompt::
|
difftool.prompt::
|
||||||
Prompt before each invocation of the diff tool.
|
Prompt before each invocation of the diff tool.
|
||||||
|
|
||||||
|
difftool.guiDefault::
|
||||||
|
Set `true` to use the `diff.guitool` by default (equivalent to specifying
|
||||||
|
the `--gui` argument), or `auto` to select `diff.guitool` or `diff.tool`
|
||||||
|
depending on the presence of a `DISPLAY` environment variable value. The
|
||||||
|
default is `false`, where the `--gui` argument must be provided
|
||||||
|
explicitly for the `diff.guitool` to be used.
|
||||||
|
@ -85,3 +85,10 @@ mergetool.writeToTemp::
|
|||||||
|
|
||||||
mergetool.prompt::
|
mergetool.prompt::
|
||||||
Prompt before each invocation of the merge resolution program.
|
Prompt before each invocation of the merge resolution program.
|
||||||
|
|
||||||
|
mergetool.guiDefault::
|
||||||
|
Set `true` to use the `merge.guitool` by default (equivalent to
|
||||||
|
specifying the `--gui` argument), or `auto` to select `merge.guitool`
|
||||||
|
or `merge.tool` depending on the presence of a `DISPLAY` environment
|
||||||
|
variable value. The default is `false`, where the `--gui` argument
|
||||||
|
must be provided explicitly for the `merge.guitool` to be used.
|
||||||
|
@ -97,10 +97,12 @@ instead. `--no-symlinks` is the default on Windows.
|
|||||||
--[no-]gui::
|
--[no-]gui::
|
||||||
When 'git-difftool' is invoked with the `-g` or `--gui` option
|
When 'git-difftool' is invoked with the `-g` or `--gui` option
|
||||||
the default diff tool will be read from the configured
|
the default diff tool will be read from the configured
|
||||||
`diff.guitool` variable instead of `diff.tool`. The `--no-gui`
|
`diff.guitool` variable instead of `diff.tool`. This may be
|
||||||
option can be used to override this setting. If `diff.guitool`
|
selected automatically using the configuration variable
|
||||||
is not set, we will fallback in the order of `merge.guitool`,
|
`difftool.guiDefault`. The `--no-gui` option can be used to
|
||||||
`diff.tool`, `merge.tool` until a tool is found.
|
override these settings. If `diff.guitool` is not set, we will
|
||||||
|
fallback in the order of `merge.guitool`, `diff.tool`,
|
||||||
|
`merge.tool` until a tool is found.
|
||||||
|
|
||||||
--[no-]trust-exit-code::
|
--[no-]trust-exit-code::
|
||||||
'git-difftool' invokes a diff tool individually on each file.
|
'git-difftool' invokes a diff tool individually on each file.
|
||||||
|
@ -85,12 +85,13 @@ success of the resolution after the custom tool has exited.
|
|||||||
the default merge tool will be read from the configured
|
the default merge tool will be read from the configured
|
||||||
`merge.guitool` variable instead of `merge.tool`. If
|
`merge.guitool` variable instead of `merge.tool`. If
|
||||||
`merge.guitool` is not set, we will fallback to the tool
|
`merge.guitool` is not set, we will fallback to the tool
|
||||||
configured under `merge.tool`.
|
configured under `merge.tool`. This may be autoselected using
|
||||||
|
the configuration variable `mergetool.guiDefault`.
|
||||||
|
|
||||||
--no-gui::
|
--no-gui::
|
||||||
This overrides a previous `-g` or `--gui` setting and reads the
|
This overrides a previous `-g` or `--gui` setting or
|
||||||
default merge tool will be read from the configured `merge.tool`
|
`mergetool.guiDefault` configuration and reads the default merge
|
||||||
variable.
|
tool from the configured `merge.tool` variable.
|
||||||
|
|
||||||
-O<orderfile>::
|
-O<orderfile>::
|
||||||
Process files in the order specified in the
|
Process files in the order specified in the
|
||||||
|
@ -685,7 +685,7 @@ static int run_file_diff(int prompt, const char *prefix,
|
|||||||
|
|
||||||
int cmd_difftool(int argc, const char **argv, const char *prefix)
|
int cmd_difftool(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
|
int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0,
|
||||||
tool_help = 0, no_index = 0;
|
tool_help = 0, no_index = 0;
|
||||||
static char *difftool_cmd = NULL, *extcmd = NULL;
|
static char *difftool_cmd = NULL, *extcmd = NULL;
|
||||||
struct option builtin_difftool_options[] = {
|
struct option builtin_difftool_options[] = {
|
||||||
@ -735,13 +735,21 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
|
|||||||
} else if (dir_diff)
|
} else if (dir_diff)
|
||||||
die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
|
die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
|
||||||
|
|
||||||
die_for_incompatible_opt3(use_gui_tool, "--gui",
|
die_for_incompatible_opt3(use_gui_tool == 1, "--gui",
|
||||||
!!difftool_cmd, "--tool",
|
!!difftool_cmd, "--tool",
|
||||||
!!extcmd, "--extcmd");
|
!!extcmd, "--extcmd");
|
||||||
|
|
||||||
if (use_gui_tool)
|
/*
|
||||||
|
* Explicitly specified GUI option is forwarded to git-mergetool--lib.sh;
|
||||||
|
* empty or unset means "use the difftool.guiDefault config or default to
|
||||||
|
* false".
|
||||||
|
*/
|
||||||
|
if (use_gui_tool == 1)
|
||||||
setenv("GIT_MERGETOOL_GUI", "true", 1);
|
setenv("GIT_MERGETOOL_GUI", "true", 1);
|
||||||
else if (difftool_cmd) {
|
else if (use_gui_tool == 0)
|
||||||
|
setenv("GIT_MERGETOOL_GUI", "false", 1);
|
||||||
|
|
||||||
|
if (difftool_cmd) {
|
||||||
if (*difftool_cmd)
|
if (*difftool_cmd)
|
||||||
setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
|
setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
|
||||||
else
|
else
|
||||||
|
@ -75,6 +75,11 @@ then
|
|||||||
merge_tool="$GIT_DIFF_TOOL"
|
merge_tool="$GIT_DIFF_TOOL"
|
||||||
else
|
else
|
||||||
merge_tool="$(get_merge_tool)"
|
merge_tool="$(get_merge_tool)"
|
||||||
|
subshell_exit_status=$?
|
||||||
|
if test $subshell_exit_status -gt 1
|
||||||
|
then
|
||||||
|
exit $subshell_exit_status
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -97,7 +97,42 @@ merge_mode () {
|
|||||||
test "$TOOL_MODE" = merge
|
test "$TOOL_MODE" = merge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_gui_default () {
|
||||||
|
if diff_mode
|
||||||
|
then
|
||||||
|
GUI_DEFAULT_KEY="difftool.guiDefault"
|
||||||
|
else
|
||||||
|
GUI_DEFAULT_KEY="mergetool.guiDefault"
|
||||||
|
fi
|
||||||
|
GUI_DEFAULT_CONFIG_LCASE=$(git config --default false --get "$GUI_DEFAULT_KEY" | tr 'A-Z' 'a-z')
|
||||||
|
if test "$GUI_DEFAULT_CONFIG_LCASE" = "auto"
|
||||||
|
then
|
||||||
|
if test -n "$DISPLAY"
|
||||||
|
then
|
||||||
|
GUI_DEFAULT=true
|
||||||
|
else
|
||||||
|
GUI_DEFAULT=false
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
GUI_DEFAULT=$(git config --default false --bool --get "$GUI_DEFAULT_KEY")
|
||||||
|
subshell_exit_status=$?
|
||||||
|
if test $subshell_exit_status -ne 0
|
||||||
|
then
|
||||||
|
exit $subshell_exit_status
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo $GUI_DEFAULT
|
||||||
|
}
|
||||||
|
|
||||||
gui_mode () {
|
gui_mode () {
|
||||||
|
if test -z "$GIT_MERGETOOL_GUI"
|
||||||
|
then
|
||||||
|
GIT_MERGETOOL_GUI=$(get_gui_default)
|
||||||
|
if test $? -ne 0
|
||||||
|
then
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
test "$GIT_MERGETOOL_GUI" = true
|
test "$GIT_MERGETOOL_GUI" = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +502,11 @@ get_merge_tool () {
|
|||||||
is_guessed=false
|
is_guessed=false
|
||||||
# Check if a merge tool has been configured
|
# Check if a merge tool has been configured
|
||||||
merge_tool=$(get_configured_merge_tool)
|
merge_tool=$(get_configured_merge_tool)
|
||||||
|
subshell_exit_status=$?
|
||||||
|
if test $subshell_exit_status -gt "1"
|
||||||
|
then
|
||||||
|
exit $subshell_exit_status
|
||||||
|
fi
|
||||||
# Try to guess an appropriate merge tool if no tool has been set.
|
# Try to guess an appropriate merge tool if no tool has been set.
|
||||||
if test -z "$merge_tool"
|
if test -z "$merge_tool"
|
||||||
then
|
then
|
||||||
|
@ -451,7 +451,7 @@ print_noop_and_exit () {
|
|||||||
|
|
||||||
main () {
|
main () {
|
||||||
prompt=$(git config --bool mergetool.prompt)
|
prompt=$(git config --bool mergetool.prompt)
|
||||||
GIT_MERGETOOL_GUI=false
|
GIT_MERGETOOL_GUI=
|
||||||
guessed_merge_tool=false
|
guessed_merge_tool=false
|
||||||
orderfile=
|
orderfile=
|
||||||
|
|
||||||
@ -511,9 +511,14 @@ main () {
|
|||||||
|
|
||||||
if test -z "$merge_tool"
|
if test -z "$merge_tool"
|
||||||
then
|
then
|
||||||
if ! merge_tool=$(get_merge_tool)
|
merge_tool=$(get_merge_tool)
|
||||||
|
subshell_exit_status=$?
|
||||||
|
if test $subshell_exit_status = 1
|
||||||
then
|
then
|
||||||
guessed_merge_tool=true
|
guessed_merge_tool=true
|
||||||
|
elif test $subshell_exit_status -gt 1
|
||||||
|
then
|
||||||
|
exit $subshell_exit_status
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
|
merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
|
||||||
|
@ -860,4 +860,42 @@ test_expect_success 'mergetool hideResolved' '
|
|||||||
git commit -m "test resolved with mergetool"
|
git commit -m "test resolved with mergetool"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'mergetool with guiDefault' '
|
||||||
|
test_config merge.guitool myguitool &&
|
||||||
|
test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" &&
|
||||||
|
test_config mergetool.myguitool.trustExitCode true &&
|
||||||
|
test_when_finished "git reset --hard" &&
|
||||||
|
git checkout -b test$test_count branch1 &&
|
||||||
|
git submodule update -N &&
|
||||||
|
test_must_fail git merge main &&
|
||||||
|
|
||||||
|
test_config mergetool.guiDefault auto &&
|
||||||
|
DISPLAY=SOMETHING && export DISPLAY &&
|
||||||
|
yes "" | git mergetool both &&
|
||||||
|
yes "" | git mergetool file1 file1 &&
|
||||||
|
|
||||||
|
DISPLAY= && export DISPLAY &&
|
||||||
|
yes "" | git mergetool file2 "spaced name" &&
|
||||||
|
|
||||||
|
test_config mergetool.guiDefault true &&
|
||||||
|
yes "" | git mergetool subdir/file3 &&
|
||||||
|
|
||||||
|
yes "d" | git mergetool file11 &&
|
||||||
|
yes "d" | git mergetool file12 &&
|
||||||
|
yes "l" | git mergetool submod &&
|
||||||
|
|
||||||
|
echo "gui main updated" >expect &&
|
||||||
|
test_cmp expect file1 &&
|
||||||
|
|
||||||
|
echo "main new" >expect &&
|
||||||
|
test_cmp expect file2 &&
|
||||||
|
|
||||||
|
echo "gui main new sub" >expect &&
|
||||||
|
test_cmp expect subdir/file3 &&
|
||||||
|
|
||||||
|
echo "branch1 submodule" >expect &&
|
||||||
|
test_cmp expect submod/bar &&
|
||||||
|
git commit -m "branch1 resolved with mergetool"
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -155,6 +155,58 @@ test_expect_success 'difftool honors --gui' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'difftool with guiDefault auto selects gui tool when there is DISPLAY' '
|
||||||
|
difftool_test_setup &&
|
||||||
|
test_config merge.tool bogus-tool &&
|
||||||
|
test_config diff.tool bogus-tool &&
|
||||||
|
test_config diff.guitool test-tool &&
|
||||||
|
test_config difftool.guiDefault auto &&
|
||||||
|
DISPLAY=SOMETHING && export DISPLAY &&
|
||||||
|
|
||||||
|
echo branch >expect &&
|
||||||
|
git difftool --no-prompt branch >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
test_expect_success 'difftool with guiDefault auto selects regular tool when no DISPLAY' '
|
||||||
|
difftool_test_setup &&
|
||||||
|
test_config diff.guitool bogus-tool &&
|
||||||
|
test_config diff.tool test-tool &&
|
||||||
|
test_config difftool.guiDefault Auto &&
|
||||||
|
DISPLAY= && export DISPLAY &&
|
||||||
|
|
||||||
|
echo branch >expect &&
|
||||||
|
git difftool --no-prompt branch >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'difftool with guiDefault true selects gui tool' '
|
||||||
|
difftool_test_setup &&
|
||||||
|
test_config diff.tool bogus-tool &&
|
||||||
|
test_config diff.guitool test-tool &&
|
||||||
|
test_config difftool.guiDefault true &&
|
||||||
|
|
||||||
|
DISPLAY= && export DISPLAY &&
|
||||||
|
echo branch >expect &&
|
||||||
|
git difftool --no-prompt branch >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
|
||||||
|
DISPLAY=Something && export DISPLAY &&
|
||||||
|
echo branch >expect &&
|
||||||
|
git difftool --no-prompt branch >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'difftool --no-gui trumps config guiDefault' '
|
||||||
|
difftool_test_setup &&
|
||||||
|
test_config diff.guitool bogus-tool &&
|
||||||
|
test_config diff.tool test-tool &&
|
||||||
|
test_config difftool.guiDefault true &&
|
||||||
|
|
||||||
|
echo branch >expect &&
|
||||||
|
git difftool --no-prompt --no-gui branch >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'difftool --gui last setting wins' '
|
test_expect_success 'difftool --gui last setting wins' '
|
||||||
difftool_test_setup &&
|
difftool_test_setup &&
|
||||||
: >expect &&
|
: >expect &&
|
||||||
|
Loading…
Reference in New Issue
Block a user