From f05be89217d7706a74c4ed0953cb3357b18f8e41 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 26 Jan 2026 15:07:01 -0800 Subject: [PATCH] [Fix] `nvm_install_source`: explicitly set SHELL=/bin/sh for make Old Node.js versions have Makefiles with unquoted glob patterns like `rm -f *.o` that fail in zsh's strict glob mode. By passing SHELL=/bin/sh to make, we ensure POSIX-compliant shell behavior regardless of what shell nvm is running in. --- nvm.sh | 12 ++- .../nvm_install_source SHELL override | 91 +++++++++++++++++++ 2 files changed, 100 insertions(+), 3 deletions(-) create mode 100755 test/fast/Unit tests/nvm_install_source SHELL override diff --git a/nvm.sh b/nvm.sh index 2300f96..fe95895 100755 --- a/nvm.sh +++ b/nvm.sh @@ -2642,18 +2642,24 @@ nvm_install_source() { NVM_OS="$(nvm_get_os)" local make - make='make' local MAKE_CXX + # For old Node.js versions (< 0.12), explicitly set SHELL=/bin/sh to avoid + # issues with zsh's strict glob handling in Makefiles with unquoted globs + local MAKE_SHELL_OVERRIDE + if nvm_version_greater "0.12.0" "${VERSION}"; then + MAKE_SHELL_OVERRIDE=' SHELL=/bin/sh' + fi + make="make${MAKE_SHELL_OVERRIDE-}" case "${NVM_OS}" in 'freebsd' | 'openbsd') - make='gmake' + make="gmake${MAKE_SHELL_OVERRIDE-}" MAKE_CXX="CC=${CC:-cc} CXX=${CXX:-c++}" ;; 'darwin') MAKE_CXX="CC=${CC:-cc} CXX=${CXX:-c++}" ;; 'aix') - make='gmake' + make="gmake${MAKE_SHELL_OVERRIDE-}" ;; esac if nvm_has "clang++" && nvm_has "clang" && nvm_version_greater_than_or_equal_to "$(nvm_clang_version)" 3.5; then diff --git a/test/fast/Unit tests/nvm_install_source SHELL override b/test/fast/Unit tests/nvm_install_source SHELL override new file mode 100755 index 0000000..f544948 --- /dev/null +++ b/test/fast/Unit tests/nvm_install_source SHELL override @@ -0,0 +1,91 @@ +#!/bin/sh + +cleanup () { + unset -f make gmake nvm_download nvm_get_os nvm_get_arch nvm_extract_tarball nvm_version_path nvm_get_make_jobs + rm -rf "${FAKE_TMPDIR-}" +} +die () { echo "$@" ; cleanup ; exit 1; } + +\. ../../../nvm.sh + +# Create a fake directory structure for the build +FAKE_TMPDIR="$(mktemp -d)" +mkdir -p "${FAKE_TMPDIR}/files" +touch "${FAKE_TMPDIR}/node-old.tar.gz" +touch "${FAKE_TMPDIR}/node-new.tar.gz" + +# Track make invocations +MAKE_CALLS="" + +make() { + MAKE_CALLS="${MAKE_CALLS}make $* +" + return 1 # Fail to prevent actual build +} + +gmake() { + MAKE_CALLS="${MAKE_CALLS}gmake $* +" + return 1 # Fail to prevent actual build +} + +nvm_download() { + return 0 +} + +nvm_get_arch() { + echo "x64" +} + +nvm_extract_tarball() { + return 0 +} + +nvm_version_path() { + echo "${FAKE_TMPDIR}/versions/${1}" +} + +nvm_get_make_jobs() { + NVM_MAKE_JOBS=1 +} + +# Test 1: Old version (0.6.21) should have SHELL=/bin/sh +MAKE_CALLS="" +NVM_DIR="${FAKE_TMPDIR}" +export NVM_DIR + +# Manually test the version check logic +if nvm_version_greater "0.12.0" "0.6.21"; then + OLD_VERSION_DETECTED="yes" +else + OLD_VERSION_DETECTED="no" +fi +[ "${OLD_VERSION_DETECTED}" = "yes" ] || die "Expected 0.6.21 to be detected as old version" + +# Test 2: New version (0.12.0) should NOT have SHELL=/bin/sh +if nvm_version_greater "0.12.0" "0.12.0"; then + NEW_VERSION_DETECTED="yes" +else + NEW_VERSION_DETECTED="no" +fi +[ "${NEW_VERSION_DETECTED}" = "no" ] || die "Expected 0.12.0 to NOT be detected as old version" + +# Test 3: Newer version (14.0.0) should NOT have SHELL=/bin/sh +if nvm_version_greater "0.12.0" "14.0.0"; then + NEWER_VERSION_DETECTED="yes" +else + NEWER_VERSION_DETECTED="no" +fi +[ "${NEWER_VERSION_DETECTED}" = "no" ] || die "Expected 14.0.0 to NOT be detected as old version" + +# Test 4: Edge case version (0.11.99) should have SHELL=/bin/sh +if nvm_version_greater "0.12.0" "0.11.99"; then + EDGE_VERSION_DETECTED="yes" +else + EDGE_VERSION_DETECTED="no" +fi +[ "${EDGE_VERSION_DETECTED}" = "yes" ] || die "Expected 0.11.99 to be detected as old version" + +echo "All nvm_install_source SHELL override tests passed" + +cleanup