[Fix] nvm: ignore option variables set by the caller

In dash, and in bash for a variable assigned in the command's own prefix (like `PATTERN=x nvm ls`), `local` keeps the outer value,
so a variable a subcommand only sets conditionally, like `PATTERN`, `NVM_LTS`, `LTS`, or `VERSION`, could come from the caller,
replacing the version argument, applying an LTS filter that was never requested,
or making `nvm use`, without a version or an .nvmrc, use the caller's `VERSION`.
Each such local is now initialized where it is declared.
This commit is contained in:
Jordan Harband committed 2026-10-21 12:48:18 -07:00
1 parent 6a085bc8b4
commit 139ed9ccc6
2 files changed
+90

No files matched your search

+33
View File
@@ -4285,7 +4285,9 @@ nvm() {
# initialize local variables # initialize local variables
local VERSION local VERSION
VERSION=''
local ADDITIONAL_PARAMETERS local ADDITIONAL_PARAMETERS
ADDITIONAL_PARAMETERS=''
case $COMMAND in case $COMMAND in
"cache") "cache")
@@ -4424,15 +4426,20 @@ nvm() {
nosource=0 nosource=0
NVM_OFFLINE=0 NVM_OFFLINE=0
local LTS local LTS
LTS=''
local ALIAS local ALIAS
ALIAS=''
local NVM_UPGRADE_NPM local NVM_UPGRADE_NPM
NVM_UPGRADE_NPM=0 NVM_UPGRADE_NPM=0
local NVM_WRITE_TO_NVMRC local NVM_WRITE_TO_NVMRC
NVM_WRITE_TO_NVMRC=0 NVM_WRITE_TO_NVMRC=0
local PROVIDED_REINSTALL_PACKAGES_FROM local PROVIDED_REINSTALL_PACKAGES_FROM
PROVIDED_REINSTALL_PACKAGES_FROM=''
local REINSTALL_PACKAGES_FROM local REINSTALL_PACKAGES_FROM
REINSTALL_PACKAGES_FROM=''
local SKIP_DEFAULT_PACKAGES local SKIP_DEFAULT_PACKAGES
SKIP_DEFAULT_PACKAGES=''
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
case "$1" in case "$1" in
@@ -4624,6 +4631,7 @@ nvm() {
if [ "${VERSION}" = 'N/A' ] || [ $EXIT_CODE -ne 0 ]; then if [ "${VERSION}" = 'N/A' ] || [ $EXIT_CODE -ne 0 ]; then
local LTS_MSG local LTS_MSG
LTS_MSG=''
local REMOTE_CMD local REMOTE_CMD
if [ "${LTS-}" = '*' ]; then if [ "${LTS-}" = '*' ]; then
LTS_MSG='(with LTS filter) ' LTS_MSG='(with LTS filter) '
@@ -4944,6 +4952,7 @@ nvm() {
;; ;;
"deactivate") "deactivate")
local NVM_SILENT local NVM_SILENT
NVM_SILENT=''
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
case "${1}" in case "${1}" in
--silent) NVM_SILENT=1 ;; --silent) NVM_SILENT=1 ;;
@@ -4997,11 +5006,15 @@ nvm() {
;; ;;
"use") "use")
local PROVIDED_VERSION local PROVIDED_VERSION
PROVIDED_VERSION=''
local NVM_SILENT local NVM_SILENT
NVM_SILENT=''
local NVM_SILENT_ARG local NVM_SILENT_ARG
NVM_SILENT_ARG=''
local NVM_DELETE_PREFIX local NVM_DELETE_PREFIX
NVM_DELETE_PREFIX=0 NVM_DELETE_PREFIX=0
local NVM_LTS local NVM_LTS
NVM_LTS=''
local IS_VERSION_FROM_NVMRC local IS_VERSION_FROM_NVMRC
IS_VERSION_FROM_NVMRC=0 IS_VERSION_FROM_NVMRC=0
local NVM_WRITE_TO_NVMRC local NVM_WRITE_TO_NVMRC
@@ -5152,6 +5165,7 @@ nvm() {
;; ;;
"run") "run")
local provided_version local provided_version
provided_version=''
local has_checked_nvmrc local has_checked_nvmrc
has_checked_nvmrc=0 has_checked_nvmrc=0
local IS_VERSION_FROM_NVMRC local IS_VERSION_FROM_NVMRC
@@ -5159,8 +5173,11 @@ nvm() {
# run given version of node # run given version of node
local NVM_SILENT local NVM_SILENT
NVM_SILENT=''
local NVM_SILENT_ARG local NVM_SILENT_ARG
NVM_SILENT_ARG=''
local NVM_LTS local NVM_LTS
NVM_LTS=''
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
--silent) --silent)
@@ -5182,6 +5199,7 @@ nvm() {
if [ $# -lt 1 ] && [ -z "${NVM_LTS-}" ]; then if [ $# -lt 1 ] && [ -z "${NVM_LTS-}" ]; then
local NVM_RC_VERSION local NVM_RC_VERSION
NVM_RC_VERSION=''
{ NVM_RC_VERSION="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1 && has_checked_nvmrc=1 { NVM_RC_VERSION="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1 && has_checked_nvmrc=1
if [ -n "${NVM_RC_VERSION}" ]; then if [ -n "${NVM_RC_VERSION}" ]; then
VERSION="$(nvm_version "${NVM_RC_VERSION}")" ||: VERSION="$(nvm_version "${NVM_RC_VERSION}")" ||:
@@ -5221,6 +5239,7 @@ nvm() {
fi fi
local NVM_IOJS local NVM_IOJS
NVM_IOJS=''
if nvm_is_iojs_version "${VERSION}"; then if nvm_is_iojs_version "${VERSION}"; then
NVM_IOJS=true NVM_IOJS=true
fi fi
@@ -5229,6 +5248,7 @@ nvm() {
nvm_is_zsh && setopt local_options shwordsplit nvm_is_zsh && setopt local_options shwordsplit
local LTS_ARG local LTS_ARG
LTS_ARG=''
if [ -n "${NVM_LTS-}" ]; then if [ -n "${NVM_LTS-}" ]; then
LTS_ARG="--lts=${NVM_LTS-}" LTS_ARG="--lts=${NVM_LTS-}"
VERSION='' VERSION=''
@@ -5245,7 +5265,9 @@ nvm() {
;; ;;
"exec") "exec")
local NVM_SILENT local NVM_SILENT
NVM_SILENT=''
local NVM_LTS local NVM_LTS
NVM_LTS=''
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
--silent) NVM_SILENT=1 ; shift ;; --silent) NVM_SILENT=1 ; shift ;;
@@ -5320,8 +5342,11 @@ nvm() {
;; ;;
"ls" | "list") "ls" | "list")
local PATTERN local PATTERN
PATTERN=''
local NVM_NO_COLORS local NVM_NO_COLORS
NVM_NO_COLORS=''
local NVM_NO_ALIAS local NVM_NO_ALIAS
NVM_NO_ALIAS=''
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "${1}" in case "${1}" in
@@ -5358,8 +5383,11 @@ nvm() {
;; ;;
"ls-remote" | "list-remote") "ls-remote" | "list-remote")
local NVM_LTS local NVM_LTS
NVM_LTS=''
local PATTERN local PATTERN
PATTERN=''
local NVM_NO_COLORS local NVM_NO_COLORS
NVM_NO_COLORS=''
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "${1-}" in case "${1-}" in
@@ -5420,7 +5448,9 @@ nvm() {
;; ;;
"which") "which")
local NVM_SILENT local NVM_SILENT
NVM_SILENT=''
local provided_version local provided_version
provided_version=''
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
case "${1}" in case "${1}" in
--silent) NVM_SILENT=1 ;; --silent) NVM_SILENT=1 ;;
@@ -5484,6 +5514,7 @@ nvm() {
local ALIAS local ALIAS
local TARGET local TARGET
local NVM_NO_COLORS local NVM_NO_COLORS
NVM_NO_COLORS=''
ALIAS='--' ALIAS='--'
TARGET='--' TARGET='--'
@@ -5651,7 +5682,9 @@ nvm() {
;; ;;
"version-remote") "version-remote")
local NVM_LTS local NVM_LTS
NVM_LTS=''
local PATTERN local PATTERN
PATTERN=''
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "${1-}" in case "${1-}" in
--) ;; --) ;;
@@ -0,0 +1,57 @@
#!/bin/sh
ORIG_NVM_DIR="${NVM_DIR}"
TMP_DIR=''
cleanup () {
case "${TMP_DIR}" in
/*) rm -rf "${TMP_DIR}" ;;
esac
NVM_DIR="${ORIG_NVM_DIR}"
export NVM_DIR
unset PATTERN NVM_LTS VERSION
unset -f nvm_download
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
\. ../../common.sh
TMP_DIR="$(mktemp -d)"
NVM_DIR="${TMP_DIR}/nvm"
export NVM_DIR
make_fake_node v20.0.0 || die 'fake node v20.0.0 could not be made'
make_fake_node v22.0.0 || die 'fake node v22.0.0 could not be made'
nvm_download() {
case "$*" in
*iojs*) return 1 ;;
esac
printf 'version\tdate\tfiles\tnpm\tv8\tuv\tzlib\topenssl\tmodules\tlts\tsecurity\n'
printf 'v22.0.0\t2024-04-24\tsrc\t-\t-\t-\t-\t-\t-\t-\t-\n'
printf 'v20.0.0\t2023-04-18\tsrc\t-\t-\t-\t-\t-\t-\tIron\t-\n'
}
# dash keeps an outer value after `local`, which these commands must ignore
PATTERN=v20
NVM_LTS=iron
OUTPUT="$(nvm ls --no-colors 22 | tr -d ' *')"
[ "_${OUTPUT}" = '_v22.0.0' ] || die "nvm ls 22 should list v22.0.0; got >${OUTPUT}<"
OUTPUT="$(nvm ls-remote --no-colors 22 | tr -d ' *')"
[ "_${OUTPUT}" = '_v22.0.0' ] || die "nvm ls-remote 22 should list v22.0.0; got >${OUTPUT}<"
OUTPUT="$(nvm version-remote 22)"
[ "_${OUTPUT}" = '_v22.0.0' ] || die "nvm version-remote 22 should be v22.0.0; got >${OUTPUT}<"
# without a version or an .nvmrc, `nvm use` fails, rather than use an outer VERSION
VERSION=v20.0.0
(cd "${TMP_DIR}" && nvm use >/dev/null 2>&1)
[ $? = 127 ] || die 'nvm use without a version or an .nvmrc should fail, rather than use an outer VERSION'
unset VERSION
cleanup