Skip to content

Commit

Permalink
git-difftool--helper: honor --trust-exit-code with --dir-diff
Browse files Browse the repository at this point in the history
The `--trust-exit-code` option for git-diff-tool(1) was introduced via
2b52123 (difftool: add support for --trust-exit-code, 2014-10-26).
When set, it makes us return the exit code of the invoked diff tool when
diffing multiple files. This patch didn't change the code path where
`--dir-diff` was passed because we already returned the exit code of the
diff tool unconditionally in that case.

This was changed a month later via c41d3fe (difftool--helper: add
explicit exit statement, 2014-11-20), where an explicit `exit 0` was
added to the end of git-difftool--helper.sh. While the stated intent of
that commit was merely a cleanup, it had the consequence that we now
to ignore the exit code of the diff tool when `--dir-diff` was set. This
change in behaviour is thus very likely an unintended side effect of
this patch.

Now there are two ways to fix this:

  - We can either restore the original behaviour, which unconditionally
    returned the exit code of the diffing tool when `--dir-diff` is
    passed.

  - Or we can make the `--dir-diff` case respect the `--trust-exit-code`
    flag.

The fact that we have been ignoring exit codes for 7 years by now makes
me rather lean towards the latter option. Furthermore, respecting the
flag in one case but not the other would needlessly make the user
interface more complex.

Fix the bug so that we also honor `--trust-exit-code` for dir diffs and
adjust the documentation accordingly.

Reported-by: Jean-Rémy Falleri <jr.falleri@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
pks-t authored and gitster committed Feb 20, 2024
1 parent efb050b commit eb84c8b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 46 deletions.
1 change: 0 additions & 1 deletion Documentation/git-difftool.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ instead. `--no-symlinks` is the default on Windows.
`merge.tool` until a tool is found.

--[no-]trust-exit-code::
'git-difftool' invokes a diff tool individually on each file.
Errors reported by the diff tool are ignored by default.
Use `--trust-exit-code` to make 'git-difftool' exit when an
invoked diff tool returns a non-zero exit code.
Expand Down
13 changes: 13 additions & 0 deletions git-difftool--helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ then
# ignore the error from the above --- run_merge_tool
# will diagnose unusable tool by itself
run_merge_tool "$merge_tool" false

status=$?
if test $status -ge 126
then
# Command not found (127), not executable (126) or
# exited via a signal (>= 128).
exit $status
fi

if test "$GIT_DIFFTOOL_TRUST_EXIT_CODE" = true
then
exit $status
fi
else
# Launch the merge tool on each path provided by 'git diff'
while test $# -gt 6
Expand Down
99 changes: 54 additions & 45 deletions t/t7800-difftool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,58 +91,67 @@ test_expect_success 'difftool forwards arguments to diff' '
rm for-diff
'

test_expect_success 'difftool ignores exit code' '
test_config difftool.error.cmd false &&
git difftool -y -t error branch
'
for opt in '' '--dir-diff'
do
test_expect_success "difftool ${opt} ignores exit code" "
test_config difftool.error.cmd false &&
git difftool ${opt} -y -t error branch
"

test_expect_success 'difftool forwards exit code with --trust-exit-code' '
test_config difftool.error.cmd false &&
test_must_fail git difftool -y --trust-exit-code -t error branch
'
test_expect_success "difftool ${opt} forwards exit code with --trust-exit-code" "
test_config difftool.error.cmd false &&
test_must_fail git difftool ${opt} -y --trust-exit-code -t error branch
"

test_expect_success 'difftool forwards exit code with --trust-exit-code for built-ins' '
test_config difftool.vimdiff.path false &&
test_must_fail git difftool -y --trust-exit-code -t vimdiff branch
'
test_expect_success "difftool ${opt} forwards exit code with --trust-exit-code for built-ins" "
test_config difftool.vimdiff.path false &&
test_must_fail git difftool ${opt} -y --trust-exit-code -t vimdiff branch
"

test_expect_success 'difftool honors difftool.trustExitCode = true' '
test_config difftool.error.cmd false &&
test_config difftool.trustExitCode true &&
test_must_fail git difftool -y -t error branch
'
test_expect_success "difftool ${opt} honors difftool.trustExitCode = true" "
test_config difftool.error.cmd false &&
test_config difftool.trustExitCode true &&
test_must_fail git difftool ${opt} -y -t error branch
"

test_expect_success 'difftool honors difftool.trustExitCode = false' '
test_config difftool.error.cmd false &&
test_config difftool.trustExitCode false &&
git difftool -y -t error branch
'
test_expect_success "difftool ${opt} honors difftool.trustExitCode = false" "
test_config difftool.error.cmd false &&
test_config difftool.trustExitCode false &&
git difftool ${opt} -y -t error branch
"

test_expect_success 'difftool ignores exit code with --no-trust-exit-code' '
test_config difftool.error.cmd false &&
test_config difftool.trustExitCode true &&
git difftool -y --no-trust-exit-code -t error branch
'
test_expect_success "difftool ${opt} ignores exit code with --no-trust-exit-code" "
test_config difftool.error.cmd false &&
test_config difftool.trustExitCode true &&
git difftool ${opt} -y --no-trust-exit-code -t error branch
"

test_expect_success 'difftool stops on error with --trust-exit-code' '
test_when_finished "rm -f for-diff .git/fail-right-file" &&
test_when_finished "git reset -- for-diff" &&
write_script .git/fail-right-file <<-\EOF &&
echo failed
exit 1
EOF
>for-diff &&
git add for-diff &&
test_must_fail git difftool -y --trust-exit-code \
--extcmd .git/fail-right-file branch >actual &&
test_line_count = 1 actual
'
test_expect_success "difftool ${opt} stops on error with --trust-exit-code" "
test_when_finished 'rm -f for-diff .git/fail-right-file' &&
test_when_finished 'git reset -- for-diff' &&
write_script .git/fail-right-file <<-\EOF &&
echo failed
exit 1
EOF
>for-diff &&
git add for-diff &&
test_must_fail git difftool ${opt} -y --trust-exit-code \
--extcmd .git/fail-right-file branch >actual &&
test_line_count = 1 actual
"

test_expect_success 'difftool honors exit status if command not found' '
test_config difftool.nonexistent.cmd i-dont-exist &&
test_config difftool.trustExitCode false &&
test_must_fail git difftool -y -t nonexistent branch
'
test_expect_success "difftool ${opt} honors exit status if command not found" "
test_config difftool.nonexistent.cmd i-dont-exist &&
test_config difftool.trustExitCode false &&
if test "${opt}" = '--dir-diff'
then
expected_code=127
else
expected_code=128
fi &&
test_expect_code \${expected_code} git difftool ${opt} -y -t nonexistent branch
"
done

test_expect_success 'difftool honors --gui' '
difftool_test_setup &&
Expand Down

0 comments on commit eb84c8b

Please sign in to comment.