Subject: Re: [PATCH 02/12] t: prepare `test_must_fail ()` for `set -e`

From: Junio C Hamano <[email-masked]>
Date: Tue, 14 Apr 2026 10:41:29 -0700

Jeff King <[email-masked]> writes:

> On Mon, Apr 13, 2026 at 11:49:23AM +0200, Patrick Steinhardt wrote:
>
>> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
>> index f3af10fb7e..f8bc77619b 100644
>> --- a/t/test-lib-functions.sh
>> +++ b/t/test-lib-functions.sh
>> @@ -1195,8 +1195,12 @@ test_must_fail () {
>>  		echo >&7 "test_must_fail: only 'git' is allowed: $*"
>>  		return 1
>>  	fi
>> -	"$@" 2>&7
>> -	exit_code=$?
>> +	if "$@" 2>&7
>> +	then
>> +		exit_code=0
>> +	else
>> +		exit_code=$?
>> +	fi
>
> One subtle interaction here is that the command in "$@" will be run with
> "set -e" suppressed if it's a shell function (even if the body
> explicitly says "set -e").
>
> I think it's mostly academic since we don't tend to use "set -e" in the
> tests at all, but it may be an eventual gotcha.

Yeah, ugly, but this is tricky that they felt the need to explain it
with an example in the informative section X-<.

"set" is described in

  https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_26

and the description for "-e" does not even talk about any function.
The application usage notes associated with the "set" gives this

    Application writers should avoid relying on set -e within
    functions. For example, in the following script:

    set -e
    start() {
        some_server
        echo some_server started successfully
    }
    start || echo >&2 some_server failed

    the -e setting is ignored within the function body (because the
    function is a command in an AND-OR list other than the
    last). Therefore, if some_server fails, the function carries on to
    echo "some_server started successfully", and the exit status of the
    function is zero (which means "some_server failed" is not output).

which greatly helps.