difftool: allow running outside Git worktrees with --no-index
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 14 Mar 2019 11:25:04 +0000 (04:25 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 18 Mar 2019 02:48:19 +0000 (11:48 +0900)
As far as this developer can tell, the conversion from a Perl script to
a built-in caused the regression in the difftool that it no longer runs
outside of a Git worktree (with `--no-index`, of course).

It is a bit embarrassing that it took over two years after retiring the
Perl version to discover this regression, but at least we now know, and
can do something, about it.

This fixes https://github.com/git-for-windows/git/issues/2123

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/difftool.c
git.c
t/t7800-difftool.sh
index 31eece0c8d183472794e6f8e593ee9c95fc2cdad..4fff1e83f91747fb005b7faf022c4a1d504534cf 100644 (file)
@@ -690,7 +690,7 @@ static int run_file_diff(int prompt, 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,
-           tool_help = 0;
+           tool_help = 0, no_index = 0;
        static char *difftool_cmd = NULL, *extcmd = NULL;
        struct option builtin_difftool_options[] = {
                OPT_BOOL('g', "gui", &use_gui_tool,
@@ -714,6 +714,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
                            "tool returns a non - zero exit code")),
                OPT_STRING('x', "extcmd", &extcmd, N_("command"),
                           N_("specify a custom command for viewing diffs")),
+               OPT_ARGUMENT("no-index", &no_index, N_("passed to `diff`")),
                OPT_END()
        };
 
@@ -727,8 +728,14 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
        if (tool_help)
                return print_tool_help();
 
-       setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
-       setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
+       if (!no_index && !startup_info->have_repository)
+               die(_("difftool requires worktree or --no-index"));
+
+       if (!no_index){
+               setup_work_tree();
+               setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
+               setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
+       }
 
        if (use_gui_tool && diff_gui_tool && *diff_gui_tool)
                setenv("GIT_DIFF_TOOL", diff_gui_tool, 1);
diff --git a/git.c b/git.c
index 2014aab6b83c61695d50ac39a18864a8d77858e0..46365ed86a7376d9ca7a4244bbb64dfc86336585 100644 (file)
--- a/git.c
+++ b/git.c
@@ -491,7 +491,7 @@ static struct cmd_struct commands[] = {
        { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
        { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT },
        { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT },
-       { "difftool", cmd_difftool, RUN_SETUP | NEED_WORK_TREE },
+       { "difftool", cmd_difftool, RUN_SETUP_GENTLY },
        { "fast-export", cmd_fast_export, RUN_SETUP },
        { "fetch", cmd_fetch, RUN_SETUP },
        { "fetch-pack", cmd_fetch_pack, RUN_SETUP | NO_PARSEOPT },
index bb9a7f4ff91120424e300f4ced821a9217b5e34e..480dd0633fd3e979aecca82784d38642232d44b4 100755 (executable)
@@ -705,4 +705,14 @@ test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' '
        test_cmp expect actual
 '
 
+test_expect_success 'outside worktree' '
+       echo 1 >1 &&
+       echo 2 >2 &&
+       test_expect_code 1 nongit git \
+               -c diff.tool=echo -c difftool.echo.cmd="echo \$LOCAL \$REMOTE" \
+               difftool --no-prompt --no-index ../1 ../2 >actual &&
+       echo "../1 ../2" >expect &&
+       test_cmp expect actual
+'
+
 test_done