From 811c039e2b6fb305e6eb2269d7aa0d21eb067586 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 8 Mar 2024 22:28:53 -0800 Subject: [PATCH 01/19] [actions] finisher tweaks --- .github/workflows/latest-npm.yml | 6 +----- .github/workflows/shellcheck.yml | 2 +- .github/workflows/tests.yml | 2 +- .github/workflows/windows-npm.yml | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/latest-npm.yml b/.github/workflows/latest-npm.yml index b271404..8f3bc18 100644 --- a/.github/workflows/latest-npm.yml +++ b/.github/workflows/latest-npm.yml @@ -75,8 +75,4 @@ jobs: needs: [nodes] runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@v2 - with: - egress-policy: block - - run: 'echo tests completed' + - run: true diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 2327d37..ed0f614 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -56,4 +56,4 @@ jobs: uses: step-security/harden-runner@v2 with: egress-policy: block - - run: 'echo tests completed' + - run: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 07b4356..7480c33 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,4 +53,4 @@ jobs: needs: [tests] runs-on: ubuntu-latest steps: - - run: 'echo tests completed' + - run: true diff --git a/.github/workflows/windows-npm.yml b/.github/workflows/windows-npm.yml index 4c80bb0..6dc3217 100644 --- a/.github/workflows/windows-npm.yml +++ b/.github/workflows/windows-npm.yml @@ -187,4 +187,4 @@ jobs: needs: [wsl_matrix, wsl_matrix_unofficial, cygwin_matrix, msys_matrix, msys_fail_install] runs-on: ubuntu-latest steps: - - run: 'echo tests completed' + - run: true From 97093dc1b310d919b1bcda07e4fc9232989b835f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 30 May 2024 12:36:26 -0700 Subject: [PATCH 02/19] [Dev Deps] update `markdown-link-check`, `semver` --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bc264aa..0968873 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,9 @@ "dockerfile_lint": "^0.3.4", "doctoc": "^2.2.1", "eclint": "^2.8.1", - "markdown-link-check": "^3.11.2", + "markdown-link-check": "^3.12.2", "replace": "^1.2.2", - "semver": "^7.5.4", + "semver": "^7.6.2", "urchin": "^0.0.5" } } From 1750b8d327d1eb9490ffb92e6201a8ec787b5711 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 30 May 2024 12:37:36 -0700 Subject: [PATCH 03/19] [actions] update vampire/setup-wsl action --- .github/workflows/windows-npm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-npm.yml b/.github/workflows/windows-npm.yml index 6dc3217..51234ae 100644 --- a/.github/workflows/windows-npm.yml +++ b/.github/workflows/windows-npm.yml @@ -123,7 +123,7 @@ jobs: - '' - 'script' steps: - - uses: Vampire/setup-wsl@v2 + - uses: Vampire/setup-wsl@v3 with: distribution: ${{ matrix.wsl-distrib }} additional-packages: bash git curl ca-certificates wget @@ -166,7 +166,7 @@ jobs: - '' - 'script' steps: - - uses: Vampire/setup-wsl@v2 + - uses: Vampire/setup-wsl@v3 with: distribution: ${{ matrix.wsl-distrib }} additional-packages: bash git curl ca-certificates wget From 95081f0bc2636b9b37e6890d354591efdd0b551c Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 6 Jun 2024 14:19:11 -0700 Subject: [PATCH 04/19] [readme] update CII badge URLs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e47e01..5f31978 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.coreinfrastructure.org/projects/684/badge)](https://bestpractices.coreinfrastructure.org/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.39.7-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684) From 29dce5edfd0976f9a1728c5746715c24061fd404 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 7 Jun 2024 10:13:00 -0700 Subject: [PATCH 05/19] [New] allow `.nvmrc` files to support comments In theory, `npx nvmrc` can now be used to validate an `.nvmrc` file that `nvm` will support. Allowances have been made for future extensibility, and aliases may no longer contain a `#`. Fixes #3336. Closes #2288. Co-authored-by: Jordan Harband Co-authored-by: Yash Singh --- .editorconfig | 7 ++ .gitmodules | 3 + README.md | 13 ++- nvm.sh | 95 +++++++++++++++- test/common.sh | 102 ++++++++++++++++++ ...ias' should not accept aliases with a hash | 26 +++++ test/fast/Unit tests/nvm_process_nvmrc | 34 ++++++ test/fixtures/nvmrc | 1 + 8 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 .gitmodules create mode 100755 test/fast/Aliases/'nvm alias' should not accept aliases with a hash create mode 100755 test/fast/Unit tests/nvm_process_nvmrc create mode 160000 test/fixtures/nvmrc diff --git a/.editorconfig b/.editorconfig index 70c43d3..bec8105 100644 --- a/.editorconfig +++ b/.editorconfig @@ -26,3 +26,10 @@ insert_final_newline = off [Makefile] indent_style = tab + +[test/fixtures/nvmrc/**] +indent_style = off +insert_final_newline = off + +[test/fixtures/actual/alias/empty] +insert_final_newline = off diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8503510 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test/fixtures/nvmrc"] + path = test/fixtures/nvmrc + url = git@github.com:nvm-sh/nvmrc.git diff --git a/README.md b/README.md index 5f31978..cc021e6 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,13 @@ To install a specific version of node: nvm install 14.7.0 # or 16.3.0, 12.22.1, etc ``` +To set an alias: + +```sh +nvm alias my_alias v14.4.0 +``` +Make sure that your alias does not contain any spaces or slashes. + The first version installed becomes the default. New shells will start with the default version of node (e.g., `nvm alias default`). You can list available versions using `ls-remote`: @@ -563,7 +570,11 @@ Now using node v5.9.1 (npm v3.7.3) `nvm use` et. al. will traverse directory structure upwards from the current directory looking for the `.nvmrc` file. In other words, running `nvm use` et. al. in any subdirectory of a directory with an `.nvmrc` will result in that `.nvmrc` being utilized. -The contents of a `.nvmrc` file **must** be the `` (as described by `nvm --help`) followed by a newline. No trailing spaces are allowed, and the trailing newline is required. +The contents of a `.nvmrc` file **must** contain precisely one `` (as described by `nvm --help`) followed by a newline. `.nvmrc` files may also have comments. The comment delimiter is `#`, and it and any text after it, as well as blank lines, and leading and trailing white space, will be ignored when parsing. + +Key/value pairs using `=` are also allowed and ignored, but are reserved for future use, and may cause validation errors in the future. + +Run [`npx nvmrc`](https://npmjs.com/nvmrc) to validate an `.nvmrc` file. If that tool’s results do not agree with nvm, one or the other has a bug - please file an issue. ### Deeper Shell Integration diff --git a/nvm.sh b/nvm.sh index 2e4378f..6dc779e 100644 --- a/nvm.sh +++ b/nvm.sh @@ -467,7 +467,89 @@ nvm_find_nvmrc() { fi } -# Obtain nvm version from rc file +nvm_nvmrc_invalid_msg() { + local error_text + error_text="invalid .nvmrc! +all non-commented content (anything after # is a comment) must be either: + - a single bare nvm-recognized version-ish + - or, multiple distinct key-value pairs, each key/value separated by a single equals sign (=) + +additionally, a single bare nvm-recognized version-ish must be present (after stripping comments)." + + local warn_text + warn_text="non-commented content parsed: +${1}" + + nvm_err "$(nvm_wrap_with_color_code r "${error_text}") + +$(nvm_wrap_with_color_code y "${warn_text}")" +} + +nvm_process_nvmrc() { + local NVMRC_PATH="$1" + local lines + local unpaired_line + + lines=$(command sed 's/#.*//' "$NVMRC_PATH" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | nvm_grep -v '^$') + + if [ -z "$lines" ]; then + nvm_nvmrc_invalid_msg "${lines}" + return 1 + fi + + # Initialize key-value storage + local keys='' + local values='' + + while IFS= read -r line; do + if [ -z "${line}" ]; then + continue + elif [ -z "${line%%=*}" ]; then + if [ -n "${unpaired_line}" ]; then + nvm_nvmrc_invalid_msg "${lines}" + return 1 + fi + unpaired_line="${line}" + elif case "$line" in *'='*) true;; *) false;; esac; then + key="${line%%=*}" + value="${line#*=}" + + # Trim whitespace around key and value + key=$(nvm_echo "${key}" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + value=$(nvm_echo "${value}" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + # Check for invalid key "node" + if [ "${key}" = 'node' ]; then + nvm_nvmrc_invalid_msg "${lines}" + return 1 + fi + + # Check for duplicate keys + if nvm_echo "${keys}" | nvm_grep -q -E "(^| )${key}( |$)"; then + nvm_nvmrc_invalid_msg "${lines}" + return 1 + fi + keys="${keys} ${key}" + values="${values} ${value}" + else + if [ -n "${unpaired_line}" ]; then + nvm_nvmrc_invalid_msg "${lines}" + return 1 + fi + unpaired_line="${line}" + fi + done </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 \ diff --git a/test/common.sh b/test/common.sh index beadafa..3fccea1 100644 --- a/test/common.sh +++ b/test/common.sh @@ -101,3 +101,105 @@ watch() { kill %2; return $EXIT_CODE } + +parse_json() { + local json + json="$1" + local key + key="" + local value + value="" + local output + output="" + local in_key + in_key=0 + local in_value + in_value=0 + local in_string + in_string=0 + local escaped + escaped=0 + local buffer + buffer="" + local char + local len + len=${#json} + local arr_index + arr_index=0 + local in_array + in_array=0 + + for ((i = 0; i < len; i++)); do + char="${json:i:1}" + + if [ "$in_string" -eq 1 ]; then + if [ "$escaped" -eq 1 ]; then + buffer="$buffer$char" + escaped=0 + elif [ "$char" = "\\" ]; then + escaped=1 + elif [ "$char" = "\"" ]; then + in_string=0 + if [ "$in_key" -eq 1 ]; then + key="$buffer" + buffer="" + in_key=0 + elif [ "$in_value" -eq 1 ]; then + value="$buffer" + buffer="" + output="$output$key=\"$value\"\n" + in_value=0 + elif [ "$in_array" -eq 1 ]; then + value="$buffer" + buffer="" + output="$output$arr_index=\"$value\"\n" + arr_index=$((arr_index + 1)) + fi + else + buffer="$buffer$char" + fi + continue + fi + + case "$char" in + "\"") + in_string=1 + buffer="" + if [ "$in_value" -eq 0 ] && [ "$in_array" -eq 0 ]; then + in_key=1 + fi + ;; + ":") + in_value=1 + ;; + ",") + if [ "$in_value" -eq 1 ]; then + in_value=0 + fi + ;; + "[") + in_array=1 + ;; + "]") + in_array=0 + ;; + "{" | "}") + ;; + *) + if [ "$in_value" -eq 1 ] && [ "$char" != " " ] && [ "$char" != "\n" ] && [ "$char" != "\t" ]; then + buffer="$buffer$char" + fi + ;; + esac + done + + printf "%b" "$output" +} + +extract_value() { + local key + key="$1" + local parsed + parsed="$2" + echo "$parsed" | grep "^$key=" | cut -d'=' -f2 | tr -d '"' +} diff --git a/test/fast/Aliases/'nvm alias' should not accept aliases with a hash b/test/fast/Aliases/'nvm alias' should not accept aliases with a hash new file mode 100755 index 0000000..3922ea7 --- /dev/null +++ b/test/fast/Aliases/'nvm alias' should not accept aliases with a hash @@ -0,0 +1,26 @@ +#!/bin/sh + +\. ../../../nvm.sh + +die () { echo "$@" ; exit 1; } + +OUTPUT="$(nvm alias foo#bar baz 2>&1)" +EXPECTED_OUTPUT="Aliases with a comment delimiter (#) are not supported." +[ "$OUTPUT" = "$EXPECTED_OUTPUT" ] || die "trying to create an alias with a hash should fail with '$EXPECTED_OUTPUT', got '$OUTPUT'" + +EXIT_CODE="$(nvm alias foo#bar baz >/dev/null 2>&1 ; echo $?)" +[ "$EXIT_CODE" = "1" ] || die "trying to create an alias with a hash should fail with code 1, got '$EXIT_CODE'" + +OUTPUT="$(nvm alias foo# baz 2>&1)" +EXPECTED_OUTPUT="Aliases with a comment delimiter (#) are not supported." +[ "$OUTPUT" = "$EXPECTED_OUTPUT" ] || die "trying to create an alias ending with a hash should fail with '$EXPECTED_OUTPUT', got '$OUTPUT'" + +EXIT_CODE="$(nvm alias foo# baz >/dev/null 2>&1 ; echo $?)" +[ "$EXIT_CODE" = "1" ] || die "trying to create an alias ending with a hash should fail with code 1, got '$EXIT_CODE'" + +OUTPUT="$(nvm alias \#bar baz 2>&1)" +EXPECTED_OUTPUT="Aliases with a comment delimiter (#) are not supported." +[ "$OUTPUT" = "$EXPECTED_OUTPUT" ] || die "trying to create an alias starting with a hash should fail with '$EXPECTED_OUTPUT', got '$OUTPUT'" + +EXIT_CODE="$(nvm alias \#bar baz >/dev/null 2>&1 ; echo $?)" +[ "$EXIT_CODE" = "1" ] || die "trying to create an alias starting with a hash should fail with code 1, got '$EXIT_CODE'" diff --git a/test/fast/Unit tests/nvm_process_nvmrc b/test/fast/Unit tests/nvm_process_nvmrc new file mode 100755 index 0000000..65a8751 --- /dev/null +++ b/test/fast/Unit tests/nvm_process_nvmrc @@ -0,0 +1,34 @@ +#!/bin/sh + +die () { echo "$@" ; cleanup ; exit 1; } + +cleanup() { + echo 'cleaned up' +} + +\. ../../../nvm.sh + +\. ../../common.sh + +for f in ../../../test/fixtures/nvmrc/test/fixtures/valid/*; do + STDOUT="$(nvm_process_nvmrc $f/.nvmrc 2>/dev/null)" + EXIT_CODE="$(nvm_process_nvmrc $f/.nvmrc >/dev/null 2>/dev/null; echo $?)" + + EXPECTED="$(extract_value node "$(parse_json "$(cat "$f/expected.json")")")" + + [ "${EXIT_CODE}" = "0" ] || die "$(basename "${f}"): expected exit code of 0 but got ${EXIT_CODE}" + + [ "${STDOUT}" = "${EXPECTED}" ] || die "$(basename "${f}"): expected STDOUT of \`${EXPECTED}\` but got \`${STDOUT}\`" +done + +for f in ../../../test/fixtures/nvmrc/test/fixtures/invalid/*; do + STDOUT="$(nvm_process_nvmrc $f/.nvmrc 2>/dev/null)" + STDERR="$(nvm_process_nvmrc $f/.nvmrc 2>&1 >/dev/null | awk '{if(NR > 8) print $0}' | strip_colors)" + EXIT_CODE="$(nvm_process_nvmrc $f/.nvmrc >/dev/null 2>/dev/null; echo $?)" + + EXPECTED="$(parse_json "$(cat "$f/expected.json")" | sed 's/^[0-9]*="//;s/"$//')" + + [ "${EXIT_CODE}" != "0" ] || die "$(basename "${f}"): expected exit code of 'not 0' but got ${EXIT_CODE}" + + [ "${STDERR}" = "${EXPECTED}" ] || die "$(basename "${f}"): expected STDERR of \`${EXPECTED}\` but got \`${STDERR}\`" +done diff --git a/test/fixtures/nvmrc b/test/fixtures/nvmrc new file mode 160000 index 0000000..0d325aa --- /dev/null +++ b/test/fixtures/nvmrc @@ -0,0 +1 @@ +Subproject commit 0d325aa903893072cb07daf43ae04b491e104d6c From c20db2ab86bdc0bd2f2ccd3e95100949bd2c4124 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 10 Jun 2024 08:59:48 -0700 Subject: [PATCH 06/19] [actions] improve default action permissions --- .github/workflows/latest-npm.yml | 3 +++ .github/workflows/lint.yml | 11 +++-------- .github/workflows/rebase.yml | 3 +++ .github/workflows/release.yml | 5 +++-- .github/workflows/require-allow-edits.yml | 3 +++ .github/workflows/shellcheck.yml | 9 +++------ .github/workflows/tests.yml | 5 +++++ .github/workflows/toc.yml | 3 +++ .github/workflows/windows-npm.yml | 3 +++ 9 files changed, 29 insertions(+), 16 deletions(-) diff --git a/.github/workflows/latest-npm.yml b/.github/workflows/latest-npm.yml index 8f3bc18..b368080 100644 --- a/.github/workflows/latest-npm.yml +++ b/.github/workflows/latest-npm.yml @@ -2,6 +2,9 @@ name: 'Tests: `nvm install-latest-npm`' on: [pull_request, push] +permissions: + contents: read + jobs: matrix: runs-on: ubuntu-latest diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b0a61f6..3e915ba 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,10 +2,11 @@ name: 'Tests: linting' on: [pull_request, push] +permissions: + contents: read + jobs: eclint: - permissions: - contents: read runs-on: ubuntu-latest steps: - uses: step-security/harden-runner@v2 @@ -23,8 +24,6 @@ jobs: - run: npm run eclint dockerfile_lint: - permissions: - contents: read runs-on: ubuntu-latest steps: - uses: step-security/harden-runner@v2 @@ -44,8 +43,6 @@ jobs: - run: npm run dockerfile_lint doctoc: - permissions: - contents: read runs-on: ubuntu-latest steps: - uses: step-security/harden-runner@v2 @@ -63,8 +60,6 @@ jobs: - run: npm run doctoc:check test_naming: - permissions: - contents: read runs-on: ubuntu-latest steps: - uses: step-security/harden-runner@v2 diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml index e7724ae..5cfc9c4 100644 --- a/.github/workflows/rebase.yml +++ b/.github/workflows/rebase.yml @@ -2,6 +2,9 @@ name: Automatic Rebase on: [pull_request_target] +permissions: + contents: read + jobs: _: permissions: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 346a184..84fe2d8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,10 +2,11 @@ name: 'Tests: release process' on: [pull_request, push] +permissions: + contents: read + jobs: release: - permissions: - contents: read runs-on: ubuntu-latest steps: - name: Harden Runner diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml index efb6c49..13cafee 100644 --- a/.github/workflows/require-allow-edits.yml +++ b/.github/workflows/require-allow-edits.yml @@ -2,6 +2,9 @@ name: Require “Allow Edits” on: [pull_request_target] +permissions: + contents: read + jobs: _: permissions: diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index ed0f614..3534809 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -2,10 +2,11 @@ name: 'Tests: shellcheck' on: [pull_request, push] +permissions: + contents: read + jobs: shellcheck_matrix: - permissions: - contents: read runs-on: ubuntu-latest strategy: fail-fast: false @@ -52,8 +53,4 @@ jobs: needs: [shellcheck_matrix] runs-on: ubuntu-latest steps: - - name: Harden Runner - uses: step-security/harden-runner@v2 - with: - egress-policy: block - run: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7480c33..60f7c05 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,6 +2,9 @@ name: urchin tests on: [push] +permissions: + contents: read + jobs: tests: permissions: @@ -49,6 +52,8 @@ jobs: - run: make TERM=xterm-256color TEST_SUITE="${{ matrix.suite }}" SHELL="${{ matrix.shell }}" URCHIN="$(npx which urchin)" test-${{ matrix.shell }} nvm: + permissions: + contents: none name: 'all test suites, all shells' needs: [tests] runs-on: ubuntu-latest diff --git a/.github/workflows/toc.yml b/.github/workflows/toc.yml index 94c8f0d..8772bcc 100644 --- a/.github/workflows/toc.yml +++ b/.github/workflows/toc.yml @@ -2,6 +2,9 @@ name: update readme TOC on: [push] +permissions: + contents: read + jobs: _: permissions: diff --git a/.github/workflows/windows-npm.yml b/.github/workflows/windows-npm.yml index 51234ae..6119f79 100644 --- a/.github/workflows/windows-npm.yml +++ b/.github/workflows/windows-npm.yml @@ -2,6 +2,9 @@ name: 'Tests on Windows: `nvm install`' on: [pull_request, push] +permissions: + contents: read + env: NVM_INSTALL_GITHUB_REPO: ${{ github.repository }} NVM_INSTALL_VERSION: ${{ github.sha }} From aa427ad396b45fb06e421899073fea8221194414 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 10 Jun 2024 09:15:16 -0700 Subject: [PATCH 07/19] [Tests] ensure travis can access public repo submodules --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index a4a774f..d07ba1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,10 @@ addons: # - gcc-4.8 # - g++-4.8 +# https://gist.github.com/iedemam/9830045 +git: + submodules: false + cache: ccache: true directories: @@ -16,6 +20,11 @@ cache: before_install: - sudo sed -i 's/mozilla\/DST_Root_CA_X3.crt/!mozilla\/DST_Root_CA_X3.crt/g' /etc/ca-certificates.conf - sudo update-ca-certificates -f + + # https://gist.github.com/iedemam/9830045 + - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules + - git submodule update --init --recursive + - $SHELL --version 2> /dev/null || dpkg -s $SHELL 2> /dev/null || which $SHELL - curl --version - wget --version From e597bb208efe942f30139df88b5ef74e78c15925 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 10 Jun 2024 11:33:12 -0700 Subject: [PATCH 08/19] [Tests] use a better JSON parsing implementation --- test/common.sh | 236 +++++++++++++++---------- test/fast/Unit tests/nvm_process_nvmrc | 4 +- 2 files changed, 141 insertions(+), 99 deletions(-) diff --git a/test/common.sh b/test/common.sh index 3fccea1..f5bf6ff 100644 --- a/test/common.sh +++ b/test/common.sh @@ -102,104 +102,146 @@ watch() { return $EXIT_CODE } -parse_json() { - local json - json="$1" - local key - key="" - local value - value="" - local output - output="" - local in_key - in_key=0 - local in_value - in_value=0 - local in_string - in_string=0 - local escaped - escaped=0 - local buffer - buffer="" - local char - local len - len=${#json} - local arr_index - arr_index=0 - local in_array - in_array=0 - for ((i = 0; i < len; i++)); do - char="${json:i:1}" - - if [ "$in_string" -eq 1 ]; then - if [ "$escaped" -eq 1 ]; then - buffer="$buffer$char" - escaped=0 - elif [ "$char" = "\\" ]; then - escaped=1 - elif [ "$char" = "\"" ]; then - in_string=0 - if [ "$in_key" -eq 1 ]; then - key="$buffer" - buffer="" - in_key=0 - elif [ "$in_value" -eq 1 ]; then - value="$buffer" - buffer="" - output="$output$key=\"$value\"\n" - in_value=0 - elif [ "$in_array" -eq 1 ]; then - value="$buffer" - buffer="" - output="$output$arr_index=\"$value\"\n" - arr_index=$((arr_index + 1)) - fi - else - buffer="$buffer$char" - fi - continue - fi - - case "$char" in - "\"") - in_string=1 - buffer="" - if [ "$in_value" -eq 0 ] && [ "$in_array" -eq 0 ]; then - in_key=1 - fi - ;; - ":") - in_value=1 - ;; - ",") - if [ "$in_value" -eq 1 ]; then - in_value=0 - fi - ;; - "[") - in_array=1 - ;; - "]") - in_array=0 - ;; - "{" | "}") - ;; - *) - if [ "$in_value" -eq 1 ] && [ "$char" != " " ] && [ "$char" != "\n" ] && [ "$char" != "\t" ]; then - buffer="$buffer$char" - fi - ;; - esac - done - - printf "%b" "$output" +# JSON parsing from https://gist.github.com/assaf/ee377a186371e2e269a7 +nvm_json_throw() { + nvm_err "$*" + exit 1 } -extract_value() { - local key - key="$1" - local parsed - parsed="$2" - echo "$parsed" | grep "^$key=" | cut -d'=' -f2 | tr -d '"' +nvm_json_awk_egrep() { + local pattern_string + pattern_string="${1}" + + awk '{ + while ($0) { + start=match($0, pattern); + token=substr($0, start, RLENGTH); + print token; + $0=substr($0, start+RLENGTH); + } + }' "pattern=${pattern_string}" +} + +nvm_json_tokenize() { + local GREP + GREP='grep -Eao' + + local ESCAPE + local CHAR + + # if echo "test string" | grep -Eo "test" > /dev/null 2>&1; then + # ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' + # CHAR='[^[:cntrl:]"\\]' + # else + GREP=nvm_json_awk_egrep + ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' + CHAR='[^[:cntrl:]"\\\\]' + # fi + + local STRING + STRING="\"${CHAR}*(${ESCAPE}${CHAR}*)*\"" + local NUMBER + NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?' + local KEYWORD + KEYWORD='null|false|true' + local SPACE + SPACE='[[:space:]]+' + + $GREP "${STRING}|${NUMBER}|${KEYWORD}|${SPACE}|." | TERM=dumb grep -Ev "^${SPACE}$" +} + +_json_parse_array() { + local index=0 + local ary='' + read -r token + case "$token" in + ']') ;; + *) + while :; do + _json_parse_value "${1}" "${index}" + index=$((index+1)) + ary="${ary}${value}" + read -r token + case "${token}" in + ']') break ;; + ',') ary="${ary}," ;; + *) nvm_json_throw "EXPECTED , or ] GOT ${token:-EOF}" ;; + esac + read -r token + done + ;; + esac + : +} + +_json_parse_object() { + local key + local obj='' + read -r token + case "$token" in + '}') ;; + *) + while :; do + case "${token}" in + '"'*'"') key="${token}" ;; + *) nvm_json_throw "EXPECTED string GOT ${token:-EOF}" ;; + esac + read -r token + case "${token}" in + ':') ;; + *) nvm_json_throw "EXPECTED : GOT ${token:-EOF}" ;; + esac + read -r token + _json_parse_value "${1}" "${key}" + obj="${obj}${key}:${value}" + read -r token + case "${token}" in + '}') break ;; + ',') obj="${obj}," ;; + *) nvm_json_throw "EXPECTED , or } GOT ${token:-EOF}" ;; + esac + read -r token + done + ;; + esac + : +} + +_json_parse_value() { + local jpath="${1:+$1,}$2" + local isleaf=0 + local isempty=0 + local print=0 + + case "$token" in + '{') _json_parse_object "${jpath}" ;; + '[') _json_parse_array "${jpath}" ;; + # At this point, the only valid single-character tokens are digits. + ''|[!0-9]) nvm_json_throw "EXPECTED value GOT >${token:-EOF}<" ;; + *) + value=$token + isleaf=1 + [ "${value}" = '""' ] && isempty=1 + ;; + esac + + [ "${value}" = '' ] && return + [ "${isleaf}" -eq 1 ] && [ $isempty -eq 0 ] && print=1 + [ "${print}" -eq 1 ] && printf "[%s]\t%s\n" "${jpath}" "${value}" + : +} + +_json_parse() { + read -r token + _json_parse_value + read -r token + case "${token}" in + '') ;; + *) nvm_json_throw "EXPECTED EOF GOT >${token}<" ;; + esac +} + +nvm_json_extract() { + nvm_json_tokenize | _json_parse | grep -e "${1}" | awk '{print $2 $3}' } diff --git a/test/fast/Unit tests/nvm_process_nvmrc b/test/fast/Unit tests/nvm_process_nvmrc index 65a8751..5102c57 100755 --- a/test/fast/Unit tests/nvm_process_nvmrc +++ b/test/fast/Unit tests/nvm_process_nvmrc @@ -14,7 +14,7 @@ for f in ../../../test/fixtures/nvmrc/test/fixtures/valid/*; do STDOUT="$(nvm_process_nvmrc $f/.nvmrc 2>/dev/null)" EXIT_CODE="$(nvm_process_nvmrc $f/.nvmrc >/dev/null 2>/dev/null; echo $?)" - EXPECTED="$(extract_value node "$(parse_json "$(cat "$f/expected.json")")")" + EXPECTED="$(nvm_json_extract node < "${f}/expected.json" | tr -d '"')" [ "${EXIT_CODE}" = "0" ] || die "$(basename "${f}"): expected exit code of 0 but got ${EXIT_CODE}" @@ -26,7 +26,7 @@ for f in ../../../test/fixtures/nvmrc/test/fixtures/invalid/*; do STDERR="$(nvm_process_nvmrc $f/.nvmrc 2>&1 >/dev/null | awk '{if(NR > 8) print $0}' | strip_colors)" EXIT_CODE="$(nvm_process_nvmrc $f/.nvmrc >/dev/null 2>/dev/null; echo $?)" - EXPECTED="$(parse_json "$(cat "$f/expected.json")" | sed 's/^[0-9]*="//;s/"$//')" + EXPECTED="$(nvm_json_extract < "${f}/expected.json" | tr -d '"')" [ "${EXIT_CODE}" != "0" ] || die "$(basename "${f}"): expected exit code of 'not 0' but got ${EXIT_CODE}" From 762f9ef9d17623b45095e8ca1a996c8928f3f424 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 6 Jul 2024 10:29:55 -0500 Subject: [PATCH 09/19] [Tests] only install python 2.7 if not already installed See ee6f7667 / #3067 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d07ba1f..effbd86 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ before_install: - zsh --version - dpkg -s dash | grep ^Version | awk '{print $2}' # install python - - pyenv install 2.7.18 + - pyenv local 2.7.18 || pyenv install 2.7.18 - pyenv local 2.7.18 || echo 'pyenv failed' - python -V install: From 93277112aeb967743d367455ce62a7485420a0b5 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Jul 2024 09:16:03 -0700 Subject: [PATCH 10/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 11/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 12/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 13/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 14/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 15/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 16/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 17/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 18/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 05feeaa92709eb89ab0184808d4e634a1230d720 Mon Sep 17 00:00:00 2001 From: Bark Date: Wed, 6 Mar 2024 16:03:10 +0200 Subject: [PATCH 19/19] [Fix] `nvm exec`: Do a version check on `nvm-exec` This check would display a message in case the `.nvmrc` version is not installed, and would not alter the output otherwise. --- nvm-exec | 1 + ...-exec' should display required node version | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100755 test/fast/Running 'nvm-exec' should display required node version diff --git a/nvm-exec b/nvm-exec index 44d5ddb..c082f8f 100755 --- a/nvm-exec +++ b/nvm-exec @@ -7,6 +7,7 @@ unset NVM_CD_FLAGS # shellcheck disable=SC1090,SC1091 \. "$DIR/nvm.sh" --no-use +nvm_rc_version > /dev/null && nvm_ensure_version_installed "$NVM_RC_VERSION"; if [ -n "$NODE_VERSION" ]; then nvm use "$NODE_VERSION" > /dev/null || exit 127 elif ! nvm use >/dev/null 2>&1; then diff --git a/test/fast/Running 'nvm-exec' should display required node version b/test/fast/Running 'nvm-exec' should display required node version new file mode 100755 index 0000000..df5ace7 --- /dev/null +++ b/test/fast/Running 'nvm-exec' should display required node version @@ -0,0 +1,18 @@ +#!/bin/bash + +set -x +\. ../../nvm.sh + +NVM_TEST_VERSION=v0.42 + +# Write it to nvmrc +echo "$NVM_TEST_VERSION" > .nvmrc + +OUTPUT="$(../../nvm-exec 2>&1)"; +EXPECTED="N/A: version \"${NVM_TEST_VERSION}\" is not yet installed. + +You need to run \`nvm install ${NVM_TEST_VERSION}\` to install and use it. +No NODE_VERSION provided; no .nvmrc file found"; + +# Skip install, we want to test the error message +diff <(echo "${EXPECTED}") <(echo "${OUTPUT}")