difftool: allow running outside Git worktrees with --no-index

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>

Johannes Schindelin committed Mar 14, 2019 at 04:25 UTC 20de316e33446f37200e51aa333ba7d824dfd478
3 files changed +21 -4
builtin/difftool.c
+10 -3
@@ -690,7 +690,7 @@ static int run_file_diff(int prompt, const char *prefix,
690 int cmd_difftool(int argc, const char **argv, const char *prefix)
691 {
692 int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
693 - tool_help = 0;
693 + tool_help = 0, no_index = 0;
694 static char *difftool_cmd = NULL, *extcmd = NULL;
695 struct option builtin_difftool_options[] = {
696 OPT_BOOL('g', "gui", &use_gui_tool,
@@ -714,6 +714,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
714 "tool returns a non - zero exit code")),
715 OPT_STRING('x', "extcmd", &extcmd, N_("command"),
716 N_("specify a custom command for viewing diffs")),
717 + OPT_ARGUMENT("no-index", &no_index, N_("passed to `diff`")),
718 OPT_END()
719 };
720
@@ -727,8 +728,14 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
728 if (tool_help)
729 return print_tool_help();
730
730 - setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
731 - setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
731 + if (!no_index && !startup_info->have_repository)
732 + die(_("difftool requires worktree or --no-index"));
733 +
734 + if (!no_index){
735 + setup_work_tree();
736 + setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
737 + setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
738 + }
739
740 if (use_gui_tool && diff_gui_tool && *diff_gui_tool)
741 setenv("GIT_DIFF_TOOL", diff_gui_tool, 1);
git.c
+1 -1
@@ -491,7 +491,7 @@ static struct cmd_struct commands[] = {
491 { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
492 { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT },
493 { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT },
494 - { "difftool", cmd_difftool, RUN_SETUP | NEED_WORK_TREE },
494 + { "difftool", cmd_difftool, RUN_SETUP_GENTLY },
495 { "fast-export", cmd_fast_export, RUN_SETUP },
496 { "fetch", cmd_fetch, RUN_SETUP },
497 { "fetch-pack", cmd_fetch_pack, RUN_SETUP | NO_PARSEOPT },
t/t7800-difftool.sh
+10
@@ -705,4 +705,14 @@ test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' '
705 test_cmp expect actual
706 '
707
708 +test_expect_success 'outside worktree' '
709 + echo 1 >1 &&
710 + echo 2 >2 &&
711 + test_expect_code 1 nongit git \
712 + -c diff.tool=echo -c difftool.echo.cmd="echo \$LOCAL \$REMOTE" \
713 + difftool --no-prompt --no-index ../1 ../2 >actual &&
714 + echo "../1 ../2" >expect &&
715 + test_cmp expect actual
716 +'
717 +
718 test_done