From 93277112aeb967743d367455ce62a7485420a0b5 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Jul 2024 09:16:03 -0700 Subject: [PATCH 01/19] [Fix] `install-latest-npm`: npm ^8.7 breaks `npm ls` with file: deps --- nvm.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nvm.sh b/nvm.sh index 6dc779e..7f13927 100644 --- a/nvm.sh +++ b/nvm.sh @@ -370,8 +370,9 @@ nvm_install_latest_npm() { || { [ $NVM_IS_16_OR_ABOVE -eq 1 ] && [ $NVM_IS_16_LTS_OR_ABOVE -eq 0 ]; } \ || { [ $NVM_IS_17_OR_ABOVE -eq 1 ] && [ $NVM_IS_18_OR_ABOVE -eq 0 ]; } \ ; then - nvm_echo '* `npm` `v8.x` is the last version that works on `node` `v12`, `v14.13` - `v14.16`, or `v16.0` - `v16.12`' - $NVM_NPM_CMD install -g npm@8 + nvm_echo '* `npm` `v8.6` is the last version that works on `node` `v12`, `v14.13` - `v14.16`, or `v16.0` - `v16.12`' + # ^8.7 breaks `npm ls` on file: deps + $NVM_NPM_CMD install -g npm@8.6 elif \ [ $NVM_IS_18_17_OR_ABOVE -eq 0 ] \ || { [ $NVM_IS_19_OR_ABOVE -eq 1 ] && [ $NVM_IS_20_5_OR_ABOVE -eq 0 ]; } \ From 80cb39d71231f3b75cf8669ee438f0ea512cdea7 Mon Sep 17 00:00:00 2001 From: Andre Kradolfer Date: Mon, 22 Jul 2024 14:07:07 -0600 Subject: [PATCH 02/19] [debug] adding logging to makefile --- Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cc2944b..ddd679e 100644 --- a/Makefile +++ b/Makefile @@ -40,10 +40,14 @@ list: # Note that preexisting NVM_* variables are unset to avoid interfering with tests, except when running the Travis tests (where NVM_DIR must be passed in and the env. is assumed to be pristine). .PHONY: $(SHELL_TARGETS) $(SHELL_TARGETS): - @shell='$@'; shell=$${shell##*-}; which "$$shell" >/dev/null || { printf '\033[0;31m%s\033[0m\n' "WARNING: Cannot test with shell '$$shell': not found." >&2; exit 0; } && \ + @shell='$@'; shell=$${shell##*-}; \ + which "$$shell" >/dev/null || { printf '\033[0;31m%s\033[0m\n' "WARNING: Cannot test with shell '$$shell': not found." >&2; exit 0; } && \ printf '\n\033[0;34m%s\033[0m\n' "Running tests in $$shell"; \ [ -z "$$TRAVIS_BUILD_DIR" ] && for v in $$(set | awk -F'=' '$$1 ~ "^NVM_" { print $$1 }'); do unset $$v; done && unset v; \ - for suite in $(TEST_SUITE); do $(URCHIN) -f -s $$shell test/$$suite || exit; done + for suite in $(TEST_SUITE); do \ + echo "Running test suite: $$suite"; \ + $(URCHIN) -f -s $$shell test/$$suite || exit; \ + done # All-tests target: invokes the specified test suites for ALL shells defined in $(SHELLS). .PHONY: test From 4c7d899447a18d3d06db0c98737460e117d22419 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Jul 2024 12:04:07 -0700 Subject: [PATCH 03/19] [Tests] ignore travis-ci env vars; improve debug output --- ...ing 'nvm unload' should unset all function and variables | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/fast/Running 'nvm unload' should unset all function and variables b/test/fast/Running 'nvm unload' should unset all function and variables index e7fb706..abb5ca4 100755 --- a/test/fast/Running 'nvm unload' should unset all function and variables +++ b/test/fast/Running 'nvm unload' should unset all function and variables @@ -9,7 +9,7 @@ cleanup () { rm -f "${BEFORE}" "${AFTER}"; } die () { echo "$@" ; cleanup ; exit 1; } typeset -f | awk '/ \(\) $/ && !/^main / {print $1}' > "${BEFORE}" -env | grep -v PATH= | grep -v IFS= | grep -v NVM_ | sort >> "${BEFORE}" +env | grep -v PATH= | grep -v IFS= | grep -v NVM_ | grep -v TRAVIS_ | sort >> "${BEFORE}" set +e # TODO: fix \. ../../nvm.sh @@ -20,11 +20,11 @@ type nvm > /dev/null 2>&1 || die "nvm not loaded" nvm unload typeset -f | awk '/ \(\) $/ && !/^main / {print $1}' > "${AFTER}" -env | grep -v PATH= | grep -v IFS= | sort >> "${AFTER}" +env | grep -v PATH= | grep -v IFS= | grep -v TRAVIS_ | sort >> "${AFTER}" ! type nvm > /dev/null 2>&1 || die "nvm not unloaded" DIFF="$(diff "${BEFORE}" "${AFTER}" ||:)" -[ -z "${DIFF}" ] || die "function pollution found: ${DIFF}" +[ -z "${DIFF}" ] || die "function pollution found: >${DIFF}<" cleanup From bd090ef7f89a4521880951dc20de87d21cb6c6d9 Mon Sep 17 00:00:00 2001 From: David Welch Date: Fri, 21 Jun 2024 08:55:22 -0600 Subject: [PATCH 04/19] [New] Add support for `NVM_AUTH_HEADER` env var Closes #3366 Co-authored-by: David Welch Co-authored-by: Andre Kradolfer --- README.md | 8 ++++++++ nvm.sh | 22 +++++++++++++++++++--- test/fast/Unit tests/nvm_download | 12 +++++++++++- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cc021e6..cb8c36a 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ - [Restoring PATH](#restoring-path) - [Set default node version](#set-default-node-version) - [Use a mirror of node binaries](#use-a-mirror-of-node-binaries) + - [Pass Authorization header to mirror](#pass-authorization-header-to-mirror) - [.nvmrc](#nvmrc) - [Deeper Shell Integration](#deeper-shell-integration) - [Calling `nvm use` automatically in a directory with a `.nvmrc` file](#calling-nvm-use-automatically-in-a-directory-with-a-nvmrc-file) @@ -530,6 +531,13 @@ NVM_IOJS_ORG_MIRROR=https://iojs.org/dist nvm install iojs-v1.0.3 `nvm use` will not, by default, create a "current" symlink. Set `$NVM_SYMLINK_CURRENT` to "true" to enable this behavior, which is sometimes useful for IDEs. Note that using `nvm` in multiple shell tabs with this environment variable enabled can cause race conditions. +#### Pass Authorization header to mirror +To pass an Authorization header through to the mirror url, set `$NVM_AUTH_HEADER` + +```sh +NVM_AUTH_HEADER="Bearer secret-token" nvm install node +``` + ### .nvmrc You can create a `.nvmrc` file containing a node version number (or any other string that `nvm` understands; see `nvm --help` for details) in the project root directory (or any parent directory). diff --git a/nvm.sh b/nvm.sh index 7f13927..4b1cd4b 100644 --- a/nvm.sh +++ b/nvm.sh @@ -116,12 +116,19 @@ nvm_get_latest() { } nvm_download() { - local CURL_COMPRESSED_FLAG if nvm_has "curl"; then + local CURL_COMPRESSED_FLAG="" + local CURL_HEADER_FLAG="" + + if [ -n "${NVM_AUTH_HEADER:-}" ]; then + sanitized_header=$(nvm_sanitize_auth_header "${NVM_AUTH_HEADER}") + CURL_HEADER_FLAG="--header \"Authorization: ${sanitized_header}\"" + fi + if nvm_curl_use_compression; then CURL_COMPRESSED_FLAG="--compressed" fi - curl --fail ${CURL_COMPRESSED_FLAG:-} -q "$@" + eval "curl -q --fail ${CURL_COMPRESSED_FLAG:-} ${CURL_HEADER_FLAG:-} $*" elif nvm_has "wget"; then # Emulate curl with wget ARGS=$(nvm_echo "$@" | command sed -e 's/--progress-bar /--progress=bar /' \ @@ -133,11 +140,20 @@ nvm_download() { -e 's/-sS /-nv /' \ -e 's/-o /-O /' \ -e 's/-C - /-c /') + + if [ -n "${NVM_AUTH_HEADER:-}" ]; then + ARGS="${ARGS} --header \"${NVM_AUTH_HEADER}\"" + fi # shellcheck disable=SC2086 eval wget $ARGS fi } +nvm_sanitize_auth_header() { + # Remove potentially dangerous characters + nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -]//g' +} + nvm_has_system_node() { [ "$(nvm deactivate >/dev/null 2>&1 && command -v node)" != '' ] } @@ -4358,7 +4374,7 @@ nvm() { nvm_sanitize_path nvm_has_colors nvm_process_parameters \ nvm_node_version_has_solaris_binary nvm_iojs_version_has_solaris_binary \ nvm_curl_libz_support nvm_command_info nvm_is_zsh nvm_stdout_is_terminal \ - nvm_npmrc_bad_news_bears \ + nvm_npmrc_bad_news_bears nvm_sanitize_auth_header \ nvm_get_colors nvm_set_colors nvm_print_color_code nvm_wrap_with_color_code nvm_format_help_message_colors \ nvm_echo_with_colors nvm_err_with_colors \ nvm_get_artifact_compression nvm_install_binary_extract nvm_extract_tarball \ diff --git a/test/fast/Unit tests/nvm_download b/test/fast/Unit tests/nvm_download index 3afd76c..19e2dd9 100644 --- a/test/fast/Unit tests/nvm_download +++ b/test/fast/Unit tests/nvm_download @@ -1,7 +1,8 @@ #!/bin/sh cleanup () { - unset -f die cleanup + unset -f die cleanup NVM_AUTH_HEADER + docker stop httpbin && docker rm httpbin } die () { echo "$@" ; cleanup ; exit 1; } @@ -15,4 +16,13 @@ nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh" >/de # nvm_download should fail to download wrong_install.sh ! nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/wrong_install.sh" >/dev/null || die "nvm_download should fail to download no existing file" +# nvm_download should pass when calling with auth header +docker pull kennethreitz/httpbin && docker run --shell=bash -d --name httpbin -p 80:80 kennethreitz/httpbin +sleep 1 # wait for httpbin to start +NVM_AUTH_HEADER="Bearer test-token" nvm_download "http://127.0.0.1/bearer" > /dev/null || die 'nvm_download with auth header should send correctly' + +# nvm_download should fail when calling without auth header +nvm_download "http://127.0.0.1/bearer" > /dev/null && die 'nvm_download with no auth header should not send the header and should fail' +docker stop httpbin && docker rm httpbin + cleanup From dd89af53f5cc2423c4c41ff2359f17c38b10f271 Mon Sep 17 00:00:00 2001 From: Ally Summers Date: Fri, 26 Jul 2024 03:35:55 +1000 Subject: [PATCH 05/19] [patch] Fix issue where zsh global aliases would break nvm help Fix issue with the color codes in the nvm help text where zsh global aliases would display an inline error in the nvm help text. --- nvm.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/nvm.sh b/nvm.sh index 4b1cd4b..cd611cd 100644 --- a/nvm.sh +++ b/nvm.sh @@ -497,9 +497,9 @@ additionally, a single bare nvm-recognized version-ish must be present (after st warn_text="non-commented content parsed: ${1}" - nvm_err "$(nvm_wrap_with_color_code r "${error_text}") + nvm_err "$(nvm_wrap_with_color_code 'r' "${error_text}") -$(nvm_wrap_with_color_code y "${warn_text}")" +$(nvm_wrap_with_color_code 'y' "${warn_text}")" } nvm_process_nvmrc() { @@ -3061,16 +3061,16 @@ nvm() { nvm_echo ' nvm cache clear Empty cache directory for nvm' nvm_echo ' nvm set-colors [] Set five text colors using format "yMeBg". Available when supported.' nvm_echo ' Initial colors are:' - nvm_echo_with_colors " $(nvm_wrap_with_color_code b b)$(nvm_wrap_with_color_code y y)$(nvm_wrap_with_color_code g g)$(nvm_wrap_with_color_code r r)$(nvm_wrap_with_color_code e e)" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'b' 'b')$(nvm_wrap_with_color_code 'y' 'y')$(nvm_wrap_with_color_code 'g' 'g')$(nvm_wrap_with_color_code 'r' 'r')$(nvm_wrap_with_color_code 'e' 'e')" nvm_echo ' Color codes:' - nvm_echo_with_colors " $(nvm_wrap_with_color_code r r)/$(nvm_wrap_with_color_code R R) = $(nvm_wrap_with_color_code r red) / $(nvm_wrap_with_color_code R 'bold red')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code g g)/$(nvm_wrap_with_color_code G G) = $(nvm_wrap_with_color_code g green) / $(nvm_wrap_with_color_code G 'bold green')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code b b)/$(nvm_wrap_with_color_code B B) = $(nvm_wrap_with_color_code b blue) / $(nvm_wrap_with_color_code B 'bold blue')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code c c)/$(nvm_wrap_with_color_code C C) = $(nvm_wrap_with_color_code c cyan) / $(nvm_wrap_with_color_code C 'bold cyan')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code m m)/$(nvm_wrap_with_color_code M M) = $(nvm_wrap_with_color_code m magenta) / $(nvm_wrap_with_color_code M 'bold magenta')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code y y)/$(nvm_wrap_with_color_code Y Y) = $(nvm_wrap_with_color_code y yellow) / $(nvm_wrap_with_color_code Y 'bold yellow')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code k k)/$(nvm_wrap_with_color_code K K) = $(nvm_wrap_with_color_code k black) / $(nvm_wrap_with_color_code K 'bold black')" - nvm_echo_with_colors " $(nvm_wrap_with_color_code e e)/$(nvm_wrap_with_color_code W W) = $(nvm_wrap_with_color_code e 'light grey') / $(nvm_wrap_with_color_code W white)" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'r' 'r')/$(nvm_wrap_with_color_code 'R' 'R') = $(nvm_wrap_with_color_code 'r' 'red') / $(nvm_wrap_with_color_code 'R' 'bold red')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'g' 'g')/$(nvm_wrap_with_color_code 'G' 'G') = $(nvm_wrap_with_color_code 'g' 'green') / $(nvm_wrap_with_color_code 'G' 'bold green')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'b' 'b')/$(nvm_wrap_with_color_code 'B' 'B') = $(nvm_wrap_with_color_code 'b' 'blue') / $(nvm_wrap_with_color_code 'B' 'bold blue')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'c' 'c')/$(nvm_wrap_with_color_code 'C' 'C') = $(nvm_wrap_with_color_code 'c' 'cyan') / $(nvm_wrap_with_color_code 'C' 'bold cyan')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'm' 'm')/$(nvm_wrap_with_color_code 'M' 'M') = $(nvm_wrap_with_color_code 'm' 'magenta') / $(nvm_wrap_with_color_code 'M' 'bold magenta')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'y' 'y')/$(nvm_wrap_with_color_code 'Y' 'Y') = $(nvm_wrap_with_color_code 'y' 'yellow') / $(nvm_wrap_with_color_code 'Y' 'bold yellow')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'k' 'k')/$(nvm_wrap_with_color_code 'K' 'K') = $(nvm_wrap_with_color_code 'k' 'black') / $(nvm_wrap_with_color_code 'K' 'bold black')" + nvm_echo_with_colors " $(nvm_wrap_with_color_code 'e' 'e')/$(nvm_wrap_with_color_code 'W' 'W') = $(nvm_wrap_with_color_code 'e' 'light grey') / $(nvm_wrap_with_color_code 'W' 'white')" nvm_echo 'Example:' nvm_echo ' nvm install 8.0.0 Install a specific version number' nvm_echo ' nvm use 8.0 Use the latest available 8.0.x release' From f439acda4af4d22c985d02e75f8bddac1479869b Mon Sep 17 00:00:00 2001 From: Martin <16228305+maartin0@users.noreply.github.com> Date: Mon, 29 Aug 2022 16:01:36 +0100 Subject: [PATCH 06/19] [New] `nvm use`/`nvm install`: add `--save` option Fixes #2849. Co-authored-by: Martin Co-authored-by: Jordan Harband --- .dockerignore | 1 + .gitignore | 1 + nvm.sh | 36 +++++++- ...ng 'nvm install --save' works as expected' | 43 ++++++++++ ...ave' works with a .nvmrc in the parent dir | 57 ++++++++++++ ...e --silent --save' doesn't output anything | 43 ++++++++++ .../Running 'nvm use -w' works as expected' | 62 +++++++++++++ test/fast/Unit tests/nvm_write_nvmrc | 86 +++++++++++++++++++ 8 files changed, 327 insertions(+), 2 deletions(-) mode change 100644 => 100755 nvm.sh create mode 100644 test/fast/Unit tests/Running 'nvm install --save' works as expected' create mode 100644 test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir create mode 100644 test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything create mode 100644 test/fast/Unit tests/Running 'nvm use -w' works as expected' create mode 100644 test/fast/Unit tests/nvm_write_nvmrc diff --git a/.dockerignore b/.dockerignore index fc578cc..52e5428 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,6 +8,7 @@ test/bak .urchin.log .urchin_stdout test/**/test_output +test/**/.nvmrc node_modules/ npm-debug.log diff --git a/.gitignore b/.gitignore index fcf59f8..ec161d4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ test/bak .urchin.log .urchin_stdout test/**/test_output +test/**/.nvmrc node_modules/ npm-debug.log diff --git a/nvm.sh b/nvm.sh old mode 100644 new mode 100755 index cd611cd..f95b95c --- a/nvm.sh +++ b/nvm.sh @@ -2911,6 +2911,23 @@ nvm_is_natural_num() { esac } +nvm_write_nvmrc() { + local VERSION_STRING + VERSION_STRING=$(nvm_version "${1-$VERSION_STRING}") + if [ "$VERSION_STRING" = '∞' ] || [ "$VERSION_STRING" = 'N/A' ]; then + return 1 + fi + echo "$VERSION_STRING" | tee "$PWD"/.nvmrc > /dev/null || { + if [ "${NVM_SILENT:-0}" -ne 1 ]; then + nvm_err "Warning: Unable to write version number ($VERSION_STRING) to .nvmrc" + fi + return 3 + } + if [ "${NVM_SILENT:-0}" -ne 1 ]; then + nvm_echo "Wrote version number ($VERSION_STRING) to .nvmrc" + fi +} + # Check version dir permissions nvm_check_file_permissions() { nvm_is_zsh && setopt local_options nonomatch @@ -3016,6 +3033,7 @@ nvm() { nvm_echo ' --no-progress Disable the progress bar on any downloads' nvm_echo ' --alias= After installing, set the alias specified to the version specified. (same as: nvm alias )' nvm_echo ' --default After installing, set default alias to the version specified. (same as: nvm alias default )' + nvm_echo ' --save After installing, write the specified version to .nvmrc' nvm_echo ' nvm uninstall Uninstall a version' nvm_echo ' nvm uninstall --lts Uninstall using automatic LTS (long-term support) alias `lts/*`, if available.' nvm_echo ' nvm uninstall --lts= Uninstall using automatic alias for provided LTS line, if available.' @@ -3024,6 +3042,7 @@ nvm() { nvm_echo ' --silent Silences stdout/stderr output' nvm_echo ' --lts Uses automatic LTS (long-term support) alias `lts/*`, if available.' nvm_echo ' --lts= Uses automatic alias for provided LTS line, if available.' + nvm_echo ' --save Writes the specified version to .nvmrc.' nvm_echo ' nvm exec [] [] Run on . Uses .nvmrc if available and version is omitted.' nvm_echo ' The following optional arguments, if provided, must appear directly after `nvm exec`:' nvm_echo ' --silent Silences stdout/stderr output' @@ -3236,6 +3255,8 @@ nvm() { local ALIAS local NVM_UPGRADE_NPM NVM_UPGRADE_NPM=0 + local NVM_WRITE_TO_NVMRC + NVM_WRITE_TO_NVMRC=0 local PROVIDED_REINSTALL_PACKAGES_FROM local REINSTALL_PACKAGES_FROM @@ -3334,6 +3355,10 @@ nvm() { SKIP_DEFAULT_PACKAGES=true shift ;; + --save | -w) + NVM_WRITE_TO_NVMRC=1 + shift + ;; *) break # stop parsing args ;; @@ -3570,6 +3595,7 @@ nvm() { else EXIT_CODE=$? fi + return $EXIT_CODE ;; "uninstall") @@ -3721,6 +3747,7 @@ nvm() { --) ;; --lts) NVM_LTS='*' ;; --lts=*) NVM_LTS="${1##--lts=}" ;; + --save | -w) NVM_WRITE_TO_NVMRC=1 ;; --*) ;; *) if [ -n "${1-}" ]; then @@ -3754,6 +3781,10 @@ nvm() { return 127 fi + if [ "${NVM_WRITE_TO_NVMRC:-0}" -eq 1 ]; then + nvm_write_nvmrc "$VERSION" + fi + if [ "_${VERSION}" = '_system' ]; then if nvm_has_system_node && nvm deactivate "${NVM_SILENT_ARG-}" >/dev/null 2>&1; then if [ "${NVM_SILENT:-0}" -ne 1 ]; then @@ -4379,6 +4410,7 @@ nvm() { nvm_echo_with_colors nvm_err_with_colors \ nvm_get_artifact_compression nvm_install_binary_extract nvm_extract_tarball \ nvm_process_nvmrc nvm_nvmrc_invalid_msg \ + nvm_write_nvmrc \ >/dev/null 2>&1 unset NVM_RC_VERSION NVM_NODEJS_ORG_MIRROR NVM_IOJS_ORG_MIRROR NVM_DIR \ NVM_CD_FLAGS NVM_BIN NVM_INC NVM_MAKE_JOBS \ @@ -4515,7 +4547,7 @@ nvm_auto() { local NVM_CURRENT if [ "_${NVM_MODE}" = '_install' ]; then VERSION="$(nvm_alias default 2>/dev/null || nvm_echo)" - if [ -n "${VERSION}" ]; then + if [ -n "${VERSION}" ] && ! [ "_${VERSION}" = '_N/A' ] && nvm_is_valid_version "${VERSION}"; then nvm install "${VERSION}" >/dev/null elif nvm_rc_version >/dev/null 2>&1; then nvm install >/dev/null @@ -4524,7 +4556,7 @@ nvm_auto() { NVM_CURRENT="$(nvm_ls_current)" if [ "_${NVM_CURRENT}" = '_none' ] || [ "_${NVM_CURRENT}" = '_system' ]; then VERSION="$(nvm_resolve_local_alias default 2>/dev/null || nvm_echo)" - if [ -n "${VERSION}" ]; then + if [ -n "${VERSION}" ] && ! [ "_${VERSION}" = '_N/A' ] && nvm_is_valid_version "${VERSION}"; then nvm use --silent "${VERSION}" >/dev/null elif nvm_rc_version >/dev/null 2>&1; then nvm use --silent >/dev/null diff --git a/test/fast/Unit tests/Running 'nvm install --save' works as expected' b/test/fast/Unit tests/Running 'nvm install --save' works as expected' new file mode 100644 index 0000000..7f6c565 --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm install --save' works as expected' @@ -0,0 +1,43 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +cleanup () { + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* .nvmrc + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +nvm install --save "$TEST_VERSION" || die "\`nvm install --save $TEST_VERSION\` failed" +OUTPUT="$(cat .nvmrc)" + +nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm install --save $TEST_VERSION\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" + +cleanup diff --git a/test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir b/test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir new file mode 100644 index 0000000..ef8a25a --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir @@ -0,0 +1,57 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi +if [ -f ../.nvmrc ]; then mv ../.nvmrc ../.nvmrc.orig; fi + +del_nvmrc () { + rm -f .nvmrc ../.nvmrc +} + +cleanup () { + del_nvmrc + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + if [ -f ../.nvmrc.orig ]; then mv ../.nvmrc.orig ../.nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +del_nvmrc +make_fake_node "$TEST_VERSION" + +(cd .. +nvm use --save "$TEST_VERSION" || die "\`nvm use --save $TEST_VERSION\` failed in the parent dir") +nvm use --save || die "\`nvm use --save\` failed" + +[ -f ../.nvmrc ] && [ -f .nvmrc ] || die "expected two .nvmrc files to be generated" + +OUTPUT=$(cat .nvmrc) +EXPECTED_OUTPUT="$(cat ../.nvmrc)" + +[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] \ + || die "invalid \`nvm use --save \` output: expected '$EXPECTED_OUTPUT'; got '$OUTPUT'" + +cleanup diff --git a/test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything b/test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything new file mode 100644 index 0000000..0df4251 --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything @@ -0,0 +1,43 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +cleanup () { + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* .nvmrc + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +OUTPUT=$(nvm use --save --silent "$TEST_VERSION" || die "\`nvm use --save --silent $TEST_VERSION\` failed") +EXPECTED_OUTPUT="" + +[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] \ + || die "\`nvm use --save --silent $TEST_VERSION\` output was not silenced to '$EXPECTED_OUTPUT'; got '$OUTPUT'" + +cleanup diff --git a/test/fast/Unit tests/Running 'nvm use -w' works as expected' b/test/fast/Unit tests/Running 'nvm use -w' works as expected' new file mode 100644 index 0000000..afa5835 --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm use -w' works as expected' @@ -0,0 +1,62 @@ +#!/bin/sh +\. ../../../nvm.sh + +set -e + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +TEST_VERSION="v0.2.4" + +cleanup () { + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* .nvmrc + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +nvm deactivate 2>/dev/null || die 'unable to deactivate' + +\. ../../common.sh + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +# 1. install + +nvm install -w "$TEST_VERSION" || die "\`nvm install -w $TEST_VERSION\` failed" +OUTPUT="$(cat .nvmrc)" + +nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm install -w $TEST_VERSION\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" + +# + +unset OUTPUT + +# 2. use + +nvm use -w "$TEST_VERSION" || die "\`nvm use -w $TEST_VERSION\` failed" +OUTPUT="$(cat .nvmrc)" + +nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm use -w $TEST_VERSION\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" + +# + +cleanup diff --git a/test/fast/Unit tests/nvm_write_nvmrc b/test/fast/Unit tests/nvm_write_nvmrc new file mode 100644 index 0000000..9e0d734 --- /dev/null +++ b/test/fast/Unit tests/nvm_write_nvmrc @@ -0,0 +1,86 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +del_nvmrc () { + rm -f .nvmrc +} + +del_alias () { + nvm unalias test >/dev/null 2>&1 +} + +cleanup () { + del_nvmrc + del_alias + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +test_version () { + del_nvmrc + VERSION_STRING=${1-} + make_fake_node "$VERSION_STRING" + + nvm_write_nvmrc $VERSION_STRING || die "\`nvm_write_nvmrc ${VERSION_STRING}\` failed" + OUTPUT="$(cat .nvmrc)" + + nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm install --save ${VERSION_STRING}\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" +} + +# 1. + +test_version "$TEST_VERSION" || die + +# 2. with an alias +del_alias +nvm alias test "$TEST_VERSION" +test_version test || die + +# 3. fails with invalid permissions +del_nvmrc +touch .nvmrc +chmod 0 .nvmrc +nvm_write_nvmrc $TEST_VERSION 2>/dev/null && die "\`nvm_write_nvmrc $TEST_VERSION\` did not fail with invalid permissions" +del_nvmrc + +# 4. respects NVM_SILENT=1 +export NVM_SILENT=1 +[ "$(nvm_write_nvmrc $TEST_VERSION)" = "" ] || die "\`nvm_write_nvmrc $TEST_VERSION\` was not silenced by NVM_SILENT=1" +unset NVM_SILENT + +# 5. fails with an invalid version number +TEST_VERSION="not_a_node_version" +nvm_write_nvmrc $TEST_VERSION 2>/dev/null && die "\`nvm_write_nvmrc $TEST_VERSION\` did not fail" + +# + +cleanup From 87a709741ff88037d6924408f08698d261ae7ddd Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 28 Jul 2024 10:02:08 -0700 Subject: [PATCH 07/19] [Fix] `nvm_get_default_packages`: use `awk` for more reliable file processing See https://github.com/nvm-sh/nvm/commit/db19450caafb37734a3302b24ac9fe2cde40638d Fixes #3382 --- nvm.sh | 46 +++++++------------ test/fast/Unit tests/nvm_get_default_packages | 2 +- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/nvm.sh b/nvm.sh index f95b95c..27c97f1 100755 --- a/nvm.sh +++ b/nvm.sh @@ -4436,37 +4436,23 @@ nvm() { } nvm_get_default_packages() { - local NVM_DEFAULT_PACKAGE_FILE="${NVM_DIR}/default-packages" + local NVM_DEFAULT_PACKAGE_FILE + NVM_DEFAULT_PACKAGE_FILE="${NVM_DIR}/default-packages" if [ -f "${NVM_DEFAULT_PACKAGE_FILE}" ]; then - local DEFAULT_PACKAGES - DEFAULT_PACKAGES='' - - # Read lines from $NVM_DIR/default-packages - local line - # ensure a trailing newline - WORK=$(mktemp -d) || exit $? - # shellcheck disable=SC2064 - trap "command rm -rf '$WORK'" EXIT - # shellcheck disable=SC1003 - sed -e '$a\' "${NVM_DEFAULT_PACKAGE_FILE}" > "${WORK}/default-packages" - while IFS=' ' read -r line; do - # Skip empty lines. - [ -n "${line-}" ] || continue - - # Skip comment lines that begin with `#`. - [ "$(nvm_echo "${line}" | command cut -c1)" != "#" ] || continue - - # Fail on lines that have multiple space-separated words - case $line in - *\ *) - nvm_err "Only one package per line is allowed in the ${NVM_DIR}/default-packages file. Please remove any lines with multiple space-separated values." - return 1 - ;; - esac - - DEFAULT_PACKAGES="${DEFAULT_PACKAGES}${line} " - done < "${WORK}/default-packages" - echo "${DEFAULT_PACKAGES}" | command xargs + command awk -v filename="${NVM_DEFAULT_PACKAGE_FILE}" ' + /^[[:space:]]*#/ { next } # Skip lines that begin with # + /^[[:space:]]*$/ { next } # Skip empty lines + /[[:space:]]/ && !/^[[:space:]]*#/ { + print "Only one package per line is allowed in `" filename "`. Please remove any lines with multiple space-separated values." > "/dev/stderr" + err = 1 + exit 1 + } + { + if (NR > 1 && !prev_space) printf " " + printf "%s", $0 + prev_space = 0 + } + ' "${NVM_DEFAULT_PACKAGE_FILE}" fi } diff --git a/test/fast/Unit tests/nvm_get_default_packages b/test/fast/Unit tests/nvm_get_default_packages index 0529137..c57ace9 100755 --- a/test/fast/Unit tests/nvm_get_default_packages +++ b/test/fast/Unit tests/nvm_get_default_packages @@ -74,7 +74,7 @@ rimraf EOF DEFAULT_PKGS="$(nvm_get_default_packages 2>&1 >/dev/null)" -EXPECTED_PKGS="Only one package per line is allowed in the $FILE file. Please remove any lines with multiple space-separated values." +EXPECTED_PKGS="Only one package per line is allowed in \`${FILE}\`. Please remove any lines with multiple space-separated values." [ "${DEFAULT_PKGS}" = "${EXPECTED_PKGS}" ] || die "4: expected default packages >${EXPECTED_PKGS}<; got >${DEFAULT_PKGS}<" cleanup From ff1257e8e3059ae01928c4261a41de2260bcd968 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 28 Jul 2024 18:01:14 -0700 Subject: [PATCH 08/19] [Refactor] `nvm_has_colors`: also check the env var --- nvm.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nvm.sh b/nvm.sh index 27c97f1..64c15cd 100755 --- a/nvm.sh +++ b/nvm.sh @@ -83,7 +83,7 @@ nvm_has_colors() { if nvm_has tput; then NVM_NUM_COLORS="$(tput -T "${TERM:-vt100}" colors)" fi - [ "${NVM_NUM_COLORS:--1}" -ge 8 ] + [ "${NVM_NUM_COLORS:--1}" -ge 8 ] && [ "${NVM_NO_COLORS-}" != '--no-colors' ] } nvm_curl_libz_support() { @@ -1094,7 +1094,7 @@ nvm_print_formatted_alias() { fi local ARROW ARROW='->' - if [ -z "${NVM_NO_COLORS}" ] && nvm_has_colors; then + if nvm_has_colors; then ARROW='\033[0;90m->\033[0m' if [ "_${DEFAULT}" = '_true' ]; then NEWLINE=" \033[${DEFAULT_COLOR}(default)\033[0m\n" @@ -1832,7 +1832,7 @@ nvm_print_versions() { DEFAULT_COLOR=$(nvm_get_colors 5) LTS_COLOR=$(nvm_get_colors 6) - if [ -z "${NVM_NO_COLORS-}" ] && nvm_has_colors; then + if nvm_has_colors; then NVM_HAS_COLORS=1 fi From 24deac7ac53a5b435ce592807ff015a9e788a1fa Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 30 Jul 2024 10:08:48 -0700 Subject: [PATCH 09/19] [readme] add OpenJS Ecosystem Sustainability Program partner - https://openjsf.org/ecosystem-sustainability-program --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index cb8c36a..ed87cde 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ - [macOS Troubleshooting](#macos-troubleshooting) - [WSL Troubleshooting](#wsl-troubleshooting) - [Maintainers](#maintainers) +- [Project Support](#project-support) +- [Enterprise Support](#enterprise-support) - [License](#license) - [Copyright notice](#copyright-notice) @@ -1070,6 +1072,16 @@ You can check the contents of the file by running: Currently, the sole maintainer is [@ljharb](https://github.com/ljharb) - more maintainers are quite welcome, and we hope to add folks to the team over time. [Governance](./GOVERNANCE.md) will be re-evaluated as the project evolves. +## Project Support + +Only the latest version (v0.39.7 at this time) is supported. + +## Enterprise Support + +If you are unable to update to the latest version of `nvm`, our [partners](https://openjsf.org/ecosystem-sustainability-program) provide commercial security fixes for all unsupported versions: + + - [HeroDevs Never-Ending Support](https://www.herodevs.com/support?utm_source=OpenJS&utm_medium=Link&utm_campaign=nvm_openjs) + ## License See [LICENSE.md](./LICENSE.md). From b5118ac365cffe8962584359c55c56edf8180409 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 30 Jul 2024 11:35:15 -0700 Subject: [PATCH 10/19] [Dev Deps] update `semver` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0968873..f5d3507 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "eclint": "^2.8.1", "markdown-link-check": "^3.12.2", "replace": "^1.2.2", - "semver": "^7.6.2", + "semver": "^7.6.3", "urchin": "^0.0.5" } } From deac4e0932eb3031656cdcbe12f0a7be2cacb69f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 30 Jul 2024 12:50:18 -0700 Subject: [PATCH 11/19] v0.40.0 --- README.md | 26 +++++++++++++------------- install.sh | 2 +- nvm.sh | 2 +- package.json | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ed87cde..95b6cad 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ -# Node Version Manager [![Build Status](https://app.travis-ci.com/nvm-sh/nvm.svg?branch=master)][3] [![nvm version](https://img.shields.io/badge/version-v0.39.7-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684) +# Node Version Manager [![Build Status](https://app.travis-ci.com/nvm-sh/nvm.svg?branch=master)][3] [![nvm version](https://img.shields.io/badge/version-v0.40.0-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684) @@ -102,10 +102,10 @@ nvm is a version manager for [node.js](https://nodejs.org/en/), designed to be i To **install** or **update** nvm, you should run the [install script][2]. To do that, you may either download and run the script manually, or use the following cURL or Wget command: ```sh -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` ```sh -wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` Running either of the above commands downloads a script and runs it. The script clones the nvm repository to `~/.nvm`, and attempts to add the source lines from the snippet below to the correct profile file (`~/.bash_profile`, `~/.zshrc`, `~/.profile`, or `~/.bashrc`). @@ -127,7 +127,7 @@ Eg: `curl ... | NVM_DIR="path/to/nvm"`. Ensure that the `NVM_DIR` does not conta - The installer can use `git`, `curl`, or `wget` to download `nvm`, whichever is available. -- You can instruct the installer to not edit your shell config (for example if you already get completions via a [zsh nvm plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/nvm)) by setting `PROFILE=/dev/null` before running the `install.sh` script. Here's an example one-line command to do that: `PROFILE=/dev/null bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash'` +- You can instruct the installer to not edit your shell config (for example if you already get completions via a [zsh nvm plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/nvm)) by setting `PROFILE=/dev/null` before running the `install.sh` script. Here's an example one-line command to do that: `PROFILE=/dev/null bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash'` #### Troubleshooting on Linux @@ -175,7 +175,7 @@ You can use a task: ```yaml - name: Install nvm ansible.builtin.shell: > - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash args: creates: "{{ ansible_env.HOME }}/.nvm/nvm.sh" ``` @@ -237,7 +237,7 @@ If you have `git` installed (requires git v1.7.10+): 1. clone this repo in the root of your user profile - `cd ~/` from anywhere then `git clone https://github.com/nvm-sh/nvm.git .nvm` -1. `cd ~/.nvm` and check out the latest version with `git checkout v0.39.7` +1. `cd ~/.nvm` and check out the latest version with `git checkout v0.40.0` 1. activate `nvm` by sourcing it from your shell: `. ./nvm.sh` Now add these lines to your `~/.bashrc`, `~/.profile`, or `~/.zshrc` file to have it automatically sourced upon login: @@ -843,13 +843,13 @@ If installing nvm on Alpine Linux *is* still what you want or need to do, you sh ### Alpine Linux 3.13+ ```sh apk add -U curl bash ca-certificates openssl ncurses coreutils python3 make gcc g++ libgcc linux-headers grep util-linux binutils findutils -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` ### Alpine Linux 3.5 - 3.12 ```sh apk add -U curl bash ca-certificates openssl ncurses coreutils python2 make gcc g++ libgcc linux-headers grep util-linux binutils findutils -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` _Note: Alpine 3.5 can only install NodeJS versions up to v6.9.5, Alpine 3.6 can only install versions up to v6.10.3, Alpine 3.7 installs versions up to v8.9.3, Alpine 3.8 installs versions up to v8.14.0, Alpine 3.9 installs versions up to v10.19.0, Alpine 3.10 installs versions up to v10.24.1, Alpine 3.11 installs versions up to v12.22.6, Alpine 3.12 installs versions up to v12.22.12, Alpine 3.13 & 3.14 install versions up to v14.20.0, Alpine 3.15 & 3.16 install versions up to v16.16.0 (**These are all versions on the main branch**). Alpine 3.5 - 3.12 required the package `python2` to build NodeJS, as they are older versions to build. Alpine 3.13+ requires `python3` to successfully build newer NodeJS versions, but you can use `python2` with Alpine 3.13+ if you need to build versions of node supported in Alpine 3.5 - 3.15, you just need to specify what version of NodeJS you need to install in the package install script._ @@ -952,9 +952,9 @@ You have to make sure that the user directory name in `$HOME` and the user direc To change the user directory and/or account name follow the instructions [here](https://support.apple.com/en-us/HT201548) [1]: https://github.com/nvm-sh/nvm.git -[2]: https://github.com/nvm-sh/nvm/blob/v0.39.7/install.sh +[2]: https://github.com/nvm-sh/nvm/blob/v0.40.0/install.sh [3]: https://app.travis-ci.com/nvm-sh/nvm -[4]: https://github.com/nvm-sh/nvm/releases/tag/v0.39.7 +[4]: https://github.com/nvm-sh/nvm/releases/tag/v0.40.0 [Urchin]: https://git.sdf.org/tlevine/urchin [Fish]: https://fishshell.com @@ -1012,7 +1012,7 @@ Here's what you will need to do: If one of these broken versions is installed on your system, the above step will likely still succeed even if you didn't include the `--shared-zlib` flag. However, later, when you attempt to `npm install` something using your old version of node.js, you will see `incorrect data check` errors. If you want to avoid the possible hassle of dealing with this, include that flag. - For more details, see [this issue](https://github.com/nodejs/node/issues/39313) and [this comment](https://github.com/nodejs/node/issues/39313#issuecomment-90.39.776) + For more details, see [this issue](https://github.com/nodejs/node/issues/39313) and [this comment](https://github.com/nodejs/node/issues/39313#issuecomment-90.40.076) - Exit back to your native shell. @@ -1039,7 +1039,7 @@ Now you should be able to use node as usual. If you've encountered this error on WSL-2: ```sh - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0curl: (6) Could not resolve host: raw.githubusercontent.com @@ -1074,7 +1074,7 @@ Currently, the sole maintainer is [@ljharb](https://github.com/ljharb) - more ma ## Project Support -Only the latest version (v0.39.7 at this time) is supported. +Only the latest version (v0.40.0 at this time) is supported. ## Enterprise Support diff --git a/install.sh b/install.sh index 40c1cdf..7f405ef 100755 --- a/install.sh +++ b/install.sh @@ -33,7 +33,7 @@ nvm_install_dir() { } nvm_latest_version() { - nvm_echo "v0.39.7" + nvm_echo "v0.40.0" } nvm_profile_is_bash_or_zsh() { diff --git a/nvm.sh b/nvm.sh index 64c15cd..82d26c0 100755 --- a/nvm.sh +++ b/nvm.sh @@ -4364,7 +4364,7 @@ nvm() { NVM_VERSION_ONLY=true NVM_LTS="${NVM_LTS-}" nvm_remote_version "${PATTERN:-node}" ;; "--version" | "-v") - nvm_echo '0.39.7' + nvm_echo '0.40.0' ;; "unload") nvm deactivate >/dev/null 2>&1 diff --git a/package.json b/package.json index f5d3507..605ba8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nvm", - "version": "0.39.7", + "version": "0.40.0", "description": "Node Version Manager - Simple bash script to manage multiple active node.js versions", "directories": { "test": "test" From 423ee82b4c3767432ed15df7755da7df647bd836 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 1 Aug 2024 10:22:28 -0700 Subject: [PATCH 12/19] [Tests] fix `nvm ls-remote` unit test --- test/fast/Unit tests/nvm ls-remote | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fast/Unit tests/nvm ls-remote b/test/fast/Unit tests/nvm ls-remote index 683fe92..bb1ac94 100755 --- a/test/fast/Unit tests/nvm ls-remote +++ b/test/fast/Unit tests/nvm ls-remote @@ -6,14 +6,14 @@ die () { echo "$@" ; cleanup ; exit 1; } cleanup() { unset -f nvm_download nvm_ls_remote nvm_ls_remote_iojs - if [ -n TEMP_NVM_COLORS ]; then + if [ -n "${TEMP_NVM_COLORS-}" ]; then export NVM_COLORS=TEMP_NVM_COLORS fi unset TEMP_NVM_COLORS } \. ../../../nvm.sh -if [ -n ${NVM_COLORS} ]; then +if [ -n "${NVM_COLORS-}" ]; then export TEMP_NVM_COLORS=NVM_COLORS unset NVM_COLORS fi From 271720ebfc83a69d53cc63ace1ee3ad648acb20b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 1 Aug 2024 13:57:22 -0700 Subject: [PATCH 13/19] [Fix] `nvm install -b`: when no binary is available, fail and output a clear message --- nvm.sh | 38 +++++++++++++++++------------ test/fast/Unit tests/nvm install -b | 16 ++++++++++++ 2 files changed, 38 insertions(+), 16 deletions(-) create mode 100755 test/fast/Unit tests/nvm install -b diff --git a/nvm.sh b/nvm.sh index 82d26c0..15c8325 100755 --- a/nvm.sh +++ b/nvm.sh @@ -3558,6 +3558,10 @@ nvm() { EXIT_CODE=$? else EXIT_CODE=-1 + if [ $nosource -eq 1 ]; then + nvm_err "Binary download is not available for ${VERSION}" + EXIT_CODE=3 + fi fi if [ $EXIT_CODE -ne 0 ]; then @@ -3575,25 +3579,27 @@ nvm() { fi fi - if [ $EXIT_CODE -eq 0 ] && nvm_use_if_needed "${VERSION}" && nvm_install_npm_if_needed "${VERSION}"; then - if [ -n "${LTS-}" ]; then - nvm_ensure_default_set "lts/${LTS}" + if [ $EXIT_CODE -eq 0 ]; then + if nvm_use_if_needed "${VERSION}" && nvm_install_npm_if_needed "${VERSION}"; then + if [ -n "${LTS-}" ]; then + nvm_ensure_default_set "lts/${LTS}" + else + nvm_ensure_default_set "${provided_version}" + fi + if [ "${NVM_UPGRADE_NPM}" = 1 ]; then + nvm install-latest-npm + EXIT_CODE=$? + fi + if [ $EXIT_CODE -eq 0 ] && [ -z "${SKIP_DEFAULT_PACKAGES-}" ]; then + nvm_install_default_packages + fi + if [ $EXIT_CODE -eq 0 ] && [ -n "${REINSTALL_PACKAGES_FROM-}" ] && [ "_${REINSTALL_PACKAGES_FROM}" != "_N/A" ]; then + nvm reinstall-packages "${REINSTALL_PACKAGES_FROM}" + EXIT_CODE=$? + fi else - nvm_ensure_default_set "${provided_version}" - fi - if [ "${NVM_UPGRADE_NPM}" = 1 ]; then - nvm install-latest-npm EXIT_CODE=$? fi - if [ $EXIT_CODE -eq 0 ] && [ -z "${SKIP_DEFAULT_PACKAGES-}" ]; then - nvm_install_default_packages - fi - if [ $EXIT_CODE -eq 0 ] && [ -n "${REINSTALL_PACKAGES_FROM-}" ] && [ "_${REINSTALL_PACKAGES_FROM}" != "_N/A" ]; then - nvm reinstall-packages "${REINSTALL_PACKAGES_FROM}" - EXIT_CODE=$? - fi - else - EXIT_CODE=$? fi return $EXIT_CODE diff --git a/test/fast/Unit tests/nvm install -b b/test/fast/Unit tests/nvm install -b new file mode 100755 index 0000000..66f6564 --- /dev/null +++ b/test/fast/Unit tests/nvm install -b @@ -0,0 +1,16 @@ +#!/bin/sh + +die () { echo "$@" ; exit 1; } + +\. ../../../nvm.sh + +VERSION="0.7.0" + +EXIT_CODE=$(nvm install -b "${VERSION}" ; echo $?) + +[ $EXIT_CODE -eq 3 ] || die "Expected exit code 3, got ${EXIT_CODE}" + +ACTUAL="$(nvm install -b "${VERSION}" 2>&1)" +EXPECTED="Binary download is not available for v${VERSION}" + +[ "${ACTUAL}" = "${EXPECTED}" ] || die "Expected >${EXPECTED}<, got >${ACTUAL}<" From 14acd3dcdd400fba1e4c2b361a8d3a042aa637e2 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 1 Aug 2024 10:35:37 -0700 Subject: [PATCH 14/19] [Fix] `nvm install -b`: do not attempt to download source on a failed binary download with `-b` Fixes #3399 --- nvm.sh | 4 ++-- test/fast/Unit tests/nvm install -b | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/nvm.sh b/nvm.sh index 15c8325..86aba61 100755 --- a/nvm.sh +++ b/nvm.sh @@ -2437,7 +2437,7 @@ nvm_download_artifact() { nvm_err "Downloading ${TARBALL_URL}..." nvm_download -L -C - "${PROGRESS_BAR}" "${TARBALL_URL}" -o "${TARBALL}" || ( command rm -rf "${TARBALL}" "${tmpdir}" - nvm_err "Binary download from ${TARBALL_URL} failed, trying source." + nvm_err "download from ${TARBALL_URL} failed" return 4 ) @@ -3564,7 +3564,7 @@ nvm() { fi fi - if [ $EXIT_CODE -ne 0 ]; then + if [ $EXIT_CODE -ne 0 ] && [ $nosource -ne 1 ]; then if [ -z "${NVM_MAKE_JOBS-}" ]; then nvm_get_make_jobs fi diff --git a/test/fast/Unit tests/nvm install -b b/test/fast/Unit tests/nvm install -b index 66f6564..20b4b76 100755 --- a/test/fast/Unit tests/nvm install -b +++ b/test/fast/Unit tests/nvm install -b @@ -4,6 +4,10 @@ die () { echo "$@" ; exit 1; } \. ../../../nvm.sh +nvm_install_source() { + exit 42 +} + VERSION="0.7.0" EXIT_CODE=$(nvm install -b "${VERSION}" ; echo $?) From 4beab63631764fc381a0e56273faf8d43b8f9509 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 7 Aug 2024 17:38:37 +1200 Subject: [PATCH 15/19] [Fix] declare an unbound variable Fixes #3402 --- nvm.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nvm.sh b/nvm.sh index 86aba61..8c410df 100755 --- a/nvm.sh +++ b/nvm.sh @@ -503,9 +503,9 @@ $(nvm_wrap_with_color_code 'y' "${warn_text}")" } nvm_process_nvmrc() { - local NVMRC_PATH="$1" + local NVMRC_PATH + NVMRC_PATH="$1" local lines - local unpaired_line lines=$(command sed 's/#.*//' "$NVMRC_PATH" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | nvm_grep -v '^$') @@ -515,8 +515,12 @@ nvm_process_nvmrc() { fi # Initialize key-value storage - local keys='' - local values='' + local keys + keys='' + local values + values='' + local unpaired_line + unpaired_line='' while IFS= read -r line; do if [ -z "${line}" ]; then From 81f18bc4450ec744fa594486f2c4330b109e21a5 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 9 Aug 2024 13:46:16 +1200 Subject: [PATCH 16/19] [patch] `install.sh`: fix node capitalization --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 7f405ef..4203fbf 100755 --- a/install.sh +++ b/install.sh @@ -358,7 +358,7 @@ nvm_check_global_modules() { command printf %s\\n "$NPM_GLOBAL_MODULES" nvm_echo '=> If you wish to uninstall them at a later point (or re-install them under your' # shellcheck disable=SC2016 - nvm_echo '=> `nvm` Nodes), you can remove them from the system Node as follows:' + nvm_echo '=> `nvm` node installs), you can remove them from the system Node as follows:' nvm_echo nvm_echo ' $ nvm use system' nvm_echo ' $ npm uninstall -g a_module' From d5e2c92a254cc10e95cd960a47515bec2d5c5e81 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 20 Aug 2024 09:23:45 -0700 Subject: [PATCH 17/19] [Fix] `nvm_has_colors`: avoid an aliased `tput` Fixes #3413 --- nvm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nvm.sh b/nvm.sh index 8c410df..685e7f2 100755 --- a/nvm.sh +++ b/nvm.sh @@ -81,7 +81,7 @@ nvm_command_info() { nvm_has_colors() { local NVM_NUM_COLORS if nvm_has tput; then - NVM_NUM_COLORS="$(tput -T "${TERM:-vt100}" colors)" + NVM_NUM_COLORS="$(command tput -T "${TERM:-vt100}" colors)" fi [ "${NVM_NUM_COLORS:--1}" -ge 8 ] && [ "${NVM_NO_COLORS-}" != '--no-colors' ] } From a8c418558a6005171f8f7c39f5d1dd3fc57570ef Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 20 Aug 2024 16:21:45 -0700 Subject: [PATCH 18/19] [Refactor] `--save`: clean up some usage --- nvm.sh | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/nvm.sh b/nvm.sh index 685e7f2..e7f97cb 100755 --- a/nvm.sh +++ b/nvm.sh @@ -3360,6 +3360,10 @@ nvm() { shift ;; --save | -w) + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_err '--save and -w may only be provided once' + return 6 + fi NVM_WRITE_TO_NVMRC=1 shift ;; @@ -3511,6 +3515,11 @@ nvm() { nvm_ensure_default_set "${provided_version}" fi + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_write_nvmrc "${VERSION}" + EXIT_CODE=$? + fi + if [ $EXIT_CODE -ne 0 ] && [ -n "${ALIAS-}" ]; then nvm alias "${ALIAS}" "${provided_version}" EXIT_CODE=$? @@ -3746,6 +3755,8 @@ nvm() { local NVM_LTS local IS_VERSION_FROM_NVMRC IS_VERSION_FROM_NVMRC=0 + local NVM_WRITE_TO_NVMRC + NVM_WRITE_TO_NVMRC=0 while [ $# -ne 0 ]; do case "$1" in @@ -3757,7 +3768,13 @@ nvm() { --) ;; --lts) NVM_LTS='*' ;; --lts=*) NVM_LTS="${1##--lts=}" ;; - --save | -w) NVM_WRITE_TO_NVMRC=1 ;; + --save | -w) + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_err '--save and -w may only be provided once' + return 6 + fi + NVM_WRITE_TO_NVMRC=1 + ;; --*) ;; *) if [ -n "${1-}" ]; then @@ -3791,8 +3808,8 @@ nvm() { return 127 fi - if [ "${NVM_WRITE_TO_NVMRC:-0}" -eq 1 ]; then - nvm_write_nvmrc "$VERSION" + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_write_nvmrc "${VERSION}" fi if [ "_${VERSION}" = '_system' ]; then @@ -3810,7 +3827,7 @@ nvm() { nvm_err 'System version of node not found.' fi return 127 - elif [ "_${VERSION}" = "_∞" ]; then + elif [ "_${VERSION}" = '_∞' ]; then if [ "${NVM_SILENT:-0}" -ne 1 ]; then nvm_err "The alias \"${PROVIDED_VERSION}\" leads to an infinite loop. Aborting." fi From c31a867c463bbe2251bd3b996a611f8cdc3007eb Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 10 Aug 2024 15:52:24 +1200 Subject: [PATCH 19/19] [Fix] `--save`: avoid a conflict with `set -e` Fixes #3405. --- .github/workflows/nvm-install-test.yml | 104 +++++++++++++++++++++++++ nvm.sh | 58 ++++++++------ 2 files changed, 138 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/nvm-install-test.yml diff --git a/.github/workflows/nvm-install-test.yml b/.github/workflows/nvm-install-test.yml new file mode 100644 index 0000000..fd82d2b --- /dev/null +++ b/.github/workflows/nvm-install-test.yml @@ -0,0 +1,104 @@ +name: 'Tests: nvm install with set -e' + +on: + pull_request: + push: + workflow_dispatch: + inputs: + ref: + description: 'git ref to use' + required: false + default: 'HEAD' + +jobs: + matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - id: matrix + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ -n "${{ github.event.inputs.ref }}" ]; then + echo "matrix=\"[\"${{ github.event.inputs.ref }}\"]\"" >> $GITHUB_OUTPUT + else + TAGS="$((echo "HEAD" && git tag --sort=-v:refname --merged HEAD --format='%(refname:strip=2) %(creatordate:short)' | grep '^v' | while read tag date; do + if [ "$(uname)" == "Darwin" ]; then + timestamp=$(date -j -f "%Y-%m-%d" "$date" +%s) + threshold=$(date -j -v-4y +%s) + else + timestamp=$(date -d "$date" +%s) + threshold=$(date -d "4 years ago" +%s) + fi + if [ $timestamp -ge $threshold ]; then echo "$tag"; fi + done) | xargs)" + echo $TAGS + TAGS_JSON=$(printf "%s\n" $TAGS | jq -R . | jq -sc .) + echo "matrix=${TAGS_JSON}" >> $GITHUB_OUTPUT + fi + + test: + needs: [matrix] + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.ref == 'v0.40.0' }} # https://github.com/nvm-sh/nvm/issues/3405 + strategy: + fail-fast: false + matrix: + ref: ${{ fromJson(needs.matrix.outputs.matrix) }} + has-nvmrc: + - 'no nvmrc' + - 'nvmrc' + shell-level: + - 1 shlvl + - 2 shlvls + + steps: + - uses: actions/checkout@v4 + - name: resolve HEAD to sha + run: | + if [ '${{ matrix.ref }}' = 'HEAD' ]; then + REF="$(git rev-parse HEAD)" + else + REF="${{ matrix.ref }}" + fi + echo "resolved ref: ${REF}" + echo "ref="$REF"" >> $GITHUB_ENV + - run: echo $- # which options are set + - run: echo node > .nvmrc + if: ${{ matrix.has-nvmrc == 'nvmrc' }} + - run: curl -I --compressed -v https://nodejs.org/dist/ + - name: 'install nvm' + run: | + set -e + export NVM_INSTALL_VERSION="${ref}" + curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/${ref}/install.sh" | bash + - name: nvm --version + run: | + set +e + . $NVM_DIR/nvm.sh && nvm --version + - name: nvm install in 1 shell level, ${{ matrix.has-nvmrc }} + if: ${{ matrix.shell-level == '1 shlvl' }} + run: | + set -ex + . $NVM_DIR/nvm.sh + echo nvm.sh sourced + nvm --version + if [ '${{ matrix.has-nvmrc }}' == 'nvmrc' ]; then + nvm install + fi + - name: nvm install in 2 shell levels, ${{ matrix.has-nvmrc }} + if: ${{ matrix.shell-level == '2 shlvls' }} + run: | + if [ '${{ matrix.has-nvmrc }}' == 'nvmrc' ]; then + bash -c "set -ex && . $NVM_DIR/nvm.sh && echo nvm.sh sourced && nvm --version && nvm install" + else + bash -c "set -ex && . $NVM_DIR/nvm.sh && echo nvm.sh sourced && nvm --version" + fi + + finisher: + runs-on: ubuntu-latest + needs: [test] + steps: + - run: true diff --git a/nvm.sh b/nvm.sh index e7f97cb..cf96950 100755 --- a/nvm.sh +++ b/nvm.sh @@ -4556,31 +4556,41 @@ nvm_supports_xz() { nvm_auto() { local NVM_MODE NVM_MODE="${1-}" - local VERSION - local NVM_CURRENT - if [ "_${NVM_MODE}" = '_install' ]; then - VERSION="$(nvm_alias default 2>/dev/null || nvm_echo)" - if [ -n "${VERSION}" ] && ! [ "_${VERSION}" = '_N/A' ] && nvm_is_valid_version "${VERSION}"; then - nvm install "${VERSION}" >/dev/null - elif nvm_rc_version >/dev/null 2>&1; then - nvm install >/dev/null - fi - elif [ "_$NVM_MODE" = '_use' ]; then - NVM_CURRENT="$(nvm_ls_current)" - if [ "_${NVM_CURRENT}" = '_none' ] || [ "_${NVM_CURRENT}" = '_system' ]; then - VERSION="$(nvm_resolve_local_alias default 2>/dev/null || nvm_echo)" - if [ -n "${VERSION}" ] && ! [ "_${VERSION}" = '_N/A' ] && nvm_is_valid_version "${VERSION}"; then - nvm use --silent "${VERSION}" >/dev/null - elif nvm_rc_version >/dev/null 2>&1; then - nvm use --silent >/dev/null + + case "${NVM_MODE}" in + none) return 0 ;; + use | install) + local VERSION + local NVM_CURRENT + NVM_CURRENT="$(nvm_ls_current)" + if [ "_${NVM_CURRENT}" = '_none' ] || [ "_${NVM_CURRENT}" = '_system' ]; then + VERSION="$(nvm_resolve_local_alias default 2>/dev/null || nvm_echo)" + if [ -n "${VERSION}" ]; then + if [ "_${VERSION}" != '_N/A' ] && nvm_is_valid_version "${VERSION}"; then + if [ "_${NVM_MODE}" = '_install' ]; then + nvm install "${VERSION}" >/dev/null + else + nvm use --silent "${VERSION}" >/dev/null + fi + else + return 0 + fi + elif nvm_rc_version >/dev/null 2>&1; then + if [ "_${NVM_MODE}" = '_install' ]; then + nvm install >/dev/null + else + nvm use --silent >/dev/null + fi + fi + else + nvm use --silent "${NVM_CURRENT}" >/dev/null fi - else - nvm use --silent "${NVM_CURRENT}" >/dev/null - fi - elif [ "_${NVM_MODE}" != '_none' ]; then - nvm_err 'Invalid auto mode supplied.' - return 1 - fi + ;; + *) + nvm_err 'Invalid auto mode supplied.' + return 1 + ;; + esac } nvm_process_parameters() {