difftool: add support for --trust-exit-code

Teach difftool to exit when a diff tool returns a non-zero exit code when either --trust-exit-code is specified or difftool.trustExitCode is true. Forward exit codes from invoked diff tools to the caller when --trust-exit-code is used. Suggested-by: Adri Farr <14farresa@gmail.com> Helped-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Aguilar committed Oct 26, 2014 at 18:15 UTC 2b52123fcf840686b69e10807fd0f985ec4167f3
4 files changed +75
Documentation/git-difftool.txt
+14
@@ -91,6 +91,15 @@ instead. `--no-symlinks` is the default on Windows.
91 the default diff tool will be read from the configured
92 `diff.guitool` variable instead of `diff.tool`.
93
94 +--[no-]trust-exit-code::
95 + 'git-difftool' invokes a diff tool individually on each file.
96 + Errors reported by the diff tool are ignored by default.
97 + Use `--trust-exit-code` to make 'git-difftool' exit when an
98 + invoked diff tool returns a non-zero exit code.
99 ++
100 +'git-difftool' will forward the exit code of the invoked tool when
101 +'--trust-exit-code' is used.
102 +
103 See linkgit:git-diff[1] for the full list of supported options.
104
105 CONFIG VARIABLES
@@ -116,6 +125,11 @@ See the `--tool=<tool>` option above for more details.
125 difftool.prompt::
126 Prompt before each invocation of the diff tool.
127
128 +difftool.trustExitCode::
129 + Exit difftool if the invoked diff tool returns a non-zero exit status.
130 ++
131 +See the `--trust-exit-code` option above for more details.
132 +
133 SEE ALSO
134 --------
135 linkgit:git-diff[1]::
git-difftool--helper.sh
+6
@@ -85,6 +85,12 @@ else
85 while test $# -gt 6
86 do
87 launch_merge_tool "$1" "$2" "$5"
88 + status=$?
89 + if test "$status" != 0 &&
90 + test "$GIT_DIFFTOOL_TRUST_EXIT_CODE" = true
91 + then
92 + exit $status
93 + fi
94 shift 7
95 done
96 fi
git-difftool.perl
+12
@@ -346,6 +346,7 @@ sub main
346 symlinks => $^O ne 'cygwin' &&
347 $^O ne 'MSWin32' && $^O ne 'msys',
348 tool_help => undef,
349 + trust_exit_code => undef,
350 );
351 GetOptions('g|gui!' => \$opts{gui},
352 'd|dir-diff' => \$opts{dirdiff},
@@ -356,6 +357,8 @@ sub main
357 'no-symlinks' => sub { $opts{symlinks} = 0; },
358 't|tool:s' => \$opts{difftool_cmd},
359 'tool-help' => \$opts{tool_help},
360 + 'trust-exit-code' => \$opts{trust_exit_code},
361 + 'no-trust-exit-code' => sub { $opts{trust_exit_code} = 0; },
362 'x|extcmd:s' => \$opts{extcmd});
363
364 if (defined($opts{help})) {
@@ -387,6 +390,15 @@ sub main
390 }
391 }
392
393 + if (!defined $opts{trust_exit_code}) {
394 + $opts{trust_exit_code} = Git::config_bool('difftool.trustExitCode');
395 + }
396 + if ($opts{trust_exit_code}) {
397 + $ENV{GIT_DIFFTOOL_TRUST_EXIT_CODE} = 'true';
398 + } else {
399 + $ENV{GIT_DIFFTOOL_TRUST_EXIT_CODE} = 'false';
400 + }
401 +
402 # In directory diff mode, 'git-difftool--helper' is called once
403 # to compare the a/b directories. In file diff mode, 'git diff'
404 # will invoke a separate instance of 'git-difftool--helper' for
t/t7800-difftool.sh
+43
@@ -76,6 +76,49 @@ test_expect_success PERL 'difftool forwards arguments to diff' '
76 rm for-diff
77 '
78
79 +test_expect_success PERL 'difftool ignores exit code' '
80 + test_config difftool.error.cmd false &&
81 + git difftool -y -t error branch
82 +'
83 +
84 +test_expect_success PERL 'difftool forwards exit code with --trust-exit-code' '
85 + test_config difftool.error.cmd false &&
86 + test_must_fail git difftool -y --trust-exit-code -t error branch
87 +'
88 +
89 +test_expect_success PERL 'difftool honors difftool.trustExitCode = true' '
90 + test_config difftool.error.cmd false &&
91 + test_config difftool.trustExitCode true &&
92 + test_must_fail git difftool -y -t error branch
93 +'
94 +
95 +test_expect_success PERL 'difftool honors difftool.trustExitCode = false' '
96 + test_config difftool.error.cmd false &&
97 + test_config difftool.trustExitCode false &&
98 + git difftool -y -t error branch
99 +'
100 +
101 +test_expect_success PERL 'difftool ignores exit code with --no-trust-exit-code' '
102 + test_config difftool.error.cmd false &&
103 + test_config difftool.trustExitCode true &&
104 + git difftool -y --no-trust-exit-code -t error branch
105 +'
106 +
107 +test_expect_success PERL 'difftool stops on error with --trust-exit-code' '
108 + test_when_finished "rm -f for-diff .git/fail-right-file" &&
109 + test_when_finished "git reset -- for-diff" &&
110 + write_script .git/fail-right-file <<-\EOF &&
111 + echo "$2"
112 + exit 1
113 + EOF
114 + >for-diff &&
115 + git add for-diff &&
116 + echo file >expect &&
117 + test_must_fail git difftool -y --trust-exit-code \
118 + --extcmd .git/fail-right-file branch >actual &&
119 + test_cmp expect actual
120 +'
121 +
122 test_expect_success PERL 'difftool honors --gui' '
123 difftool_test_setup &&
124 test_config merge.tool bogus-tool &&