diff --git a/install.sh b/install.sh index 9e66a31a..518123da 100755 --- a/install.sh +++ b/install.sh @@ -374,6 +374,16 @@ nvm_detect_profile() { fi } +nvm_is_wsl() { + if [ -e /proc/sys/fs/binfmt_misc/WSLInterop ] || [ -e /proc/sys/fs/binfmt_misc/WSLInterop-late ]; then + return 0 + fi + case "$(command uname -r 2>/dev/null)" in + *[Mm]icrosoft*) return 0 ;; + esac + return 1 +} + # # Check whether the user has any globally-installed npm modules in their system # Node, and warn them if so. @@ -383,6 +393,11 @@ nvm_check_global_modules() { NPM_COMMAND="$(command -v npm 2>/dev/null)" || return 0 [ -n "${NVM_DIR}" ] && [ -z "${NPM_COMMAND%%"$NVM_DIR"/*}" ] && return 0 + # under WSL, a Windows npm (with its `npm.cmd` beside it) is not a system node that nvm would shadow + case "${NPM_COMMAND}" in + */*) nvm_is_wsl && [ -f "${NPM_COMMAND%/*}/npm.cmd" ] && return 0 ;; + esac + local NPM_VERSION NPM_VERSION="$(npm --version)" NPM_VERSION="${NPM_VERSION:--1}" @@ -552,7 +567,7 @@ nvm_do_install() { nvm_reset() { unset -f nvm_has nvm_has_executable nvm_install_dir nvm_latest_version nvm_profile_is_bash_or_zsh \ nvm_source nvm_node_version nvm_download install_nvm_from_git nvm_install_node \ - install_nvm_as_script nvm_try_profile nvm_detect_profile nvm_check_global_modules \ + install_nvm_as_script nvm_try_profile nvm_detect_profile nvm_is_wsl nvm_check_global_modules \ nvm_do_install nvm_reset nvm_default_install_dir nvm_grep } diff --git a/test/install_script/nvm_check_global_modules b/test/install_script/nvm_check_global_modules index 8c3072f9..3a63cbe2 100755 --- a/test/install_script/nvm_check_global_modules +++ b/test/install_script/nvm_check_global_modules @@ -5,11 +5,12 @@ cleanup () { unset npm_config_prefix rm -f npm + [ -z "${WINDOWS_NPM_DIR-}" ] || rm -rf "${WINDOWS_NPM_DIR}" PATH="$ORIGINAL_PATH" NVM_DIR="$ORIGINAL_NVM_DIR" unset -f setup cleanup die - unset message ORIGINAL_PATH ORIGINAL_NVM_DIR + unset message ORIGINAL_PATH ORIGINAL_NVM_DIR WINDOWS_NPM_DIR } die () { echo "$@" ; cleanup ; exit 1; } @@ -61,5 +62,26 @@ chmod +x npm message=$(nvm_check_global_modules) [ -z "$message" ] || die "nvm_check_global_modules should have not printed a notice when npm was unavailable; got:\n${message}" +# Faking a Windows Node's npm, with a global module installed +WINDOWS_NPM_DIR="$(mktemp -d)" +cat <<'SH' >"${WINDOWS_NPM_DIR}/npm" +#!/bin/sh +case "$1" in + --version) echo '10.0.0' ;; + list) printf '%s\n' 'npm@10.0.0' '└── windows-global@1.0.0' ;; +esac +SH +touch "${WINDOWS_NPM_DIR}/npm.cmd" +chmod +x "${WINDOWS_NPM_DIR}/npm" +PATH="${WINDOWS_NPM_DIR}:${ORIGINAL_PATH}" + +nvm_is_wsl() { return 0; } +message=$(nvm_check_global_modules) +[ -z "$message" ] || die "nvm_check_global_modules should not run a Windows npm under WSL; got:\n${message}" + +nvm_is_wsl() { return 1; } +message=$(nvm_check_global_modules) +[ -n "$message" ] || die 'nvm_check_global_modules should still warn about a Windows npm outside WSL, where it is the system node' + cleanup diff --git a/test/install_script/nvm_is_wsl b/test/install_script/nvm_is_wsl new file mode 100755 index 00000000..15a5f14d --- /dev/null +++ b/test/install_script/nvm_is_wsl @@ -0,0 +1,40 @@ +#!/bin/sh + +cleanup () { + rm -rf "${FAKE_BIN_DIR}" + PATH="$ORIGINAL_PATH" + unset -f cleanup die fake_uname + unset ORIGINAL_PATH FAKE_BIN_DIR +} +die () { echo "$@" ; cleanup ; exit 1; } + +NVM_ENV=testing \. ../../install.sh + +ORIGINAL_PATH="$PATH" +FAKE_BIN_DIR="$(mktemp -d)" +PATH="${FAKE_BIN_DIR}:${PATH}" + +fake_uname() { + printf '#!/bin/sh\necho %s\n' "$1" > "${FAKE_BIN_DIR}/uname" + chmod +x "${FAKE_BIN_DIR}/uname" +} + +type nvm_is_wsl > /dev/null 2>&1 || die 'nvm_is_wsl is not available' + +fake_uname '6.6.87.2-microsoft-standard-WSL2' +nvm_is_wsl || die 'a WSL2 kernel release should be detected as WSL' + +fake_uname '4.4.0-19041-Microsoft' +nvm_is_wsl || die 'a WSL1 kernel release should be detected as WSL' + +if [ -e /proc/sys/fs/binfmt_misc/WSLInterop ] || [ -e /proc/sys/fs/binfmt_misc/WSLInterop-late ]; then + echo 'skipping the non-WSL checks: this machine has a WSL interop entry' +else + fake_uname '6.8.0-45-generic' + ! nvm_is_wsl || die 'a non-WSL kernel release should not be detected as WSL' + + fake_uname '24.5.0' + ! nvm_is_wsl || die 'a macOS kernel release should not be detected as WSL' +fi + +cleanup