From ccb49e5cd07e3a73850a1e1d36e666297ced9018 Mon Sep 17 00:00:00 2001 From: Lazizbek Ergashev Date: Tue, 25 Aug 2026 21:35:28 +0500 Subject: [PATCH] [Fix] `nvm_err`, `nvm_err_with_colors`: do not fail when stderr is closed Fixes #3906 --- nvm.sh | 7 +++++-- test/fast/Unit tests/nvm_compare_checksum | 2 ++ test/fast/Unit tests/nvm_err | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100755 test/fast/Unit tests/nvm_err diff --git a/nvm.sh b/nvm.sh index 204c396b..b623e5db 100755 --- a/nvm.sh +++ b/nvm.sh @@ -33,12 +33,15 @@ nvm_cd() { \cd "$@" } +# a caller that closed stderr, rather than redirecting it to /dev/null, makes +# the `>&2` fail; zsh cannot report that, so it aborts the script, which only a +# subshell contains, and `|| return 0` keeps the status from the caller nvm_err() { - >&2 nvm_echo "$@" + (>&2 nvm_echo "$@") || return 0 } nvm_err_with_colors() { - >&2 nvm_echo_with_colors "$@" + (>&2 nvm_echo_with_colors "$@") || return 0 } nvm_grep() { diff --git a/test/fast/Unit tests/nvm_compare_checksum b/test/fast/Unit tests/nvm_compare_checksum index c0769842..2eae1183 100755 --- a/test/fast/Unit tests/nvm_compare_checksum +++ b/test/fast/Unit tests/nvm_compare_checksum @@ -54,4 +54,6 @@ EXPECTED_OUTPUT='Checksums matched!' [ "${CAPTURED_STDERR}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${CAPTURED_STDERR}<" [ "${CAPTURED_EXIT_CODE}" = 0 ] || die "expected to exit with code 0, got ${CAPTURED_EXIT_CODE}" +(set +x; nvm_compare_checksum ../../../nvm.sh checksum 2>&-) || die "with stderr closed, expected to exit with code 0, got $?" + cleanup diff --git a/test/fast/Unit tests/nvm_err b/test/fast/Unit tests/nvm_err new file mode 100755 index 00000000..f0ddf0a2 --- /dev/null +++ b/test/fast/Unit tests/nvm_err @@ -0,0 +1,21 @@ +#!/bin/sh + +die () { echo "$@" ; exit 1; } + +: nvm.sh +\. ../../../nvm.sh + +\. ../../common.sh + +try_err nvm_err 'an error' +EXPECTED_OUTPUT='an error' +[ "${CAPTURED_STDERR}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${CAPTURED_STDERR}<" +[ "${CAPTURED_EXIT_CODE}" = 0 ] || die "expected to exit with code 0, got ${CAPTURED_EXIT_CODE}" + +try_err nvm_err_with_colors 'an error' +EXPECTED_OUTPUT='an error' +[ "${CAPTURED_STDERR}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${CAPTURED_STDERR}<" +[ "${CAPTURED_EXIT_CODE}" = 0 ] || die "expected to exit with code 0, got ${CAPTURED_EXIT_CODE}" + +nvm_err 'an error' 2>&- || die "nvm_err with stderr closed exited with code $?" +nvm_err_with_colors 'an error' 2>&- || die "nvm_err_with_colors with stderr closed exited with code $?"