Compare commits

...
46 Commits
Author SHA1 Message Date
Jordan HarbandandElan Ruusamäe b1b3a0038c [Fix] nvm_cd: bypass a user-defined cd function
Code scanning - action / CodeQL-Build (push) Waiting to run
Tests: `nvm install-latest-npm` / matrix (push) Waiting to run
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Blocked by required conditions
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Blocked by required conditions
Tests: linting / eclint (push) Waiting to run
Tests: linting / dockerfile_lint (push) Waiting to run
Tests: linting / doctoc (push) Waiting to run
Tests: linting / test_naming (push) Waiting to run
Tests: linting / check_exec (push) Waiting to run
Tests: linting / all linting (push) Blocked by required conditions
Tests: nvm install with set -e / matrix (push) Waiting to run
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Blocked by required conditions
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Blocked by required conditions
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Blocked by required conditions
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Blocked by required conditions
Tests: nvm install with set -e / finisher (push) Blocked by required conditions
Tests: release process / release (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Waiting to run
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Waiting to run
Tests: shellcheck / shellcheck (push) Blocked by required conditions
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Waiting to run
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Waiting to run
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Waiting to run
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Waiting to run
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Waiting to run
Tests: alpine / all alpine tests (push) Blocked by required conditions
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3, bash) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3, dash) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3, sh) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3, bash) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3, dash) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3, sh) (push) Waiting to run
Tests: alpine / fast x64 (alpine 3, zsh) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Waiting to run
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Waiting to run
Tests: fast / fast (bash, gawk) (push) Waiting to run
Tests: fast / fast (dash, gawk) (push) Waiting to run
Tests: fast / fast (sh, gawk) (push) Waiting to run
Tests: fast / fast (zsh, gawk) (push) Waiting to run
Tests: fast / fast (bash, mawk) (push) Waiting to run
Tests: fast / fast (dash, mawk) (push) Waiting to run
Tests: fast / fast (sh, mawk) (push) Waiting to run
Tests: fast / fast (zsh, mawk) (push) Waiting to run
Tests: fast / fast (macOS, bash) (push) Waiting to run
Tests: fast / fast (macOS, dash) (push) Waiting to run
Tests: fast / fast (macOS, sh) (push) Waiting to run
Tests: fast / fast (macOS, zsh) (push) Waiting to run
Tests: fast / fast (WSL Ubuntu-24.04, bash) (push) Waiting to run
Tests: fast / fast (WSL Ubuntu-24.04, dash) (push) Waiting to run
Tests: fast / fast (WSL Ubuntu-24.04, sh) (push) Waiting to run
Tests: fast / fast (WSL Ubuntu-24.04, zsh) (push) Waiting to run
Tests: fast / all fast tests (push) Blocked by required conditions
Tests: installation_iojs / installation_iojs without curl (bash) (push) Waiting to run
Tests: installation_iojs / installation_iojs without curl (dash) (push) Waiting to run
Tests: installation_iojs / installation_iojs without curl (sh) (push) Waiting to run
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Waiting to run
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Waiting to run
Tests: installation_iojs / all installation_iojs tests (push) Blocked by required conditions
Tests: installation_node / installation_node (bash) (push) Waiting to run
Tests: installation_node / installation_node (bash, without curl) (push) Waiting to run
Tests: installation_node / installation_node (dash) (push) Waiting to run
Tests: installation_node / installation_node (dash, without curl) (push) Waiting to run
Tests: installation_node / installation_node (sh) (push) Waiting to run
Tests: installation_node / installation_node (sh, without curl) (push) Waiting to run
Tests: installation_node / installation_node (zsh) (push) Waiting to run
Tests: installation_node / installation_node (zsh, without curl) (push) Waiting to run
Tests: installation_node / all installation_node tests (push) Blocked by required conditions
Tests: xenial / xenial (bash) (push) Waiting to run
Tests: xenial / xenial (dash) (push) Waiting to run
Tests: xenial / xenial (sh) (push) Waiting to run
Tests: xenial / xenial (zsh) (push) Waiting to run
Tests: xenial / all xenial tests (push) Blocked by required conditions
urchin tests / tests (bash, install_script) (push) Waiting to run
urchin tests / tests (bash, installation_iojs) (push) Waiting to run
urchin tests / tests (bash, slow) (push) Waiting to run
urchin tests / tests (bash, sourcing) (push) Waiting to run
urchin tests / tests (dash, installation_iojs) (push) Waiting to run
urchin tests / tests (dash, slow) (push) Waiting to run
urchin tests / tests (dash, sourcing) (push) Waiting to run
urchin tests / tests (sh, installation_iojs) (push) Waiting to run
urchin tests / tests (sh, slow) (push) Waiting to run
urchin tests / tests (sh, sourcing) (push) Waiting to run
urchin tests / tests (zsh, installation_iojs) (push) Waiting to run
urchin tests / tests (zsh, slow) (push) Waiting to run
urchin tests / tests (zsh, sourcing) (push) Waiting to run
urchin tests / all test suites, all shells (push) Blocked by required conditions
update readme TOC / update readme TOC (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / tests, on windows (push) Blocked by required conditions
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Waiting to run
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Waiting to run
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Waiting to run
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Waiting to run
Tests on Windows: `nvm install` / Cygwin nvm install (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-12) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-13) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-24.04) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.23) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.17) (push) Waiting to run
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.23) (push) Waiting to run
`\cd` only bypasses aliases, so a user-defined `cd` function (eg, cdhist's) still ran,
and broke `NVM_DIR` auto-detection when it rejected zsh's `-q`.

Use `command cd`, which skips functions in POSIX shells.
zsh's `command` runs `/usr/bin/cd` instead of the builtin,
so use `builtin cd` there, as `nvm_echo` does for `printf`.
`nvm_die_on_prefix` also now uses `nvm_cd` instead of a bare `cd`.

Fixes #3835. See #3836.

Co-authored-by: Elan Ruusamäe <glen@delfi.ee>
2026-10-09 21:16:17 -07:00
clifennelandJordan Harband 6dc3765f6b [readme] Fix a Docker warning from using Docker installation instructions
Fix a LegacyKeyValueFormat warning when building a Docker image using the 'Installing In Docker' instructions.

The warning fixed is: `LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format`

See: [LegacyKeyValueFormat](https://docs.docker.com/reference/build-checks/legacy-key-value-format/)

Co-authored-by: clifennel <li.chr+github@northeastern.edu>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
2026-09-15 21:28:51 -07:00
Jordan Harband 5c05fb659c [actions] cache container images, verified against digests looked up live
Each container job now looks up the image's index, manifest,
and config digests from the registry,
keys an `actions/cache` entry on the config digest,
and only uses a cached image if its ID matches one of those digests;
otherwise it is discarded and the image is pulled (with retries) instead.
A poisoned or stale cache entry can therefore never be used,
and a cache hit needs only a couple of small manifest requests,
so this scales regardless of pull rate limits.
2026-10-09 14:14:20 -07:00
Jordan Harband 37be73f11d [actions] pull container images through Google's Docker Hub mirror
DockerHub's anonymous pull rate limit applies per IP for hours,
so retrying cannot ride it out on shared runners;
`mirror.gcr.io` serves the same official images without that limit,
as the io.js source-install job already does.
2026-10-09 14:04:54 -07:00
Saadanjum0 906fb605bc [Fix] nvm use: handle regex-special characters in $NVM_DIR
nvm_change_path interpolated `$NVM_DIR` and the new version dir unescaped into grep and sed expressions,
so a path containing `&`, `#`, `[`, `*`, etc. corrupted `$PATH` (or made sed fail) when switching versions.
Escape them before use.
2026-10-01 16:35:00 +05:00
lazerg e45c2df7c0 [Fix] install.sh: start a new line before appending to a profile that does not end with one
Fixes #3951
2026-10-08 18:50:50 +05:00
Cassidy Marble d55a55c387 [Perf] nvm_version_greater, nvm_version_greater_than_or_equal_to: avoid awk where possible 2026-10-07 15:30:01 -03:00
Cassidy Marble 9c8cac4a2e [Perf] nvm_is_valid_version, nvm_validate_implicit_alias: avoid forks 2026-10-06 18:01:38 -03:00
Cassidy Marble 66640e6000 [Perf] nvm_echo: use the printf shell builtin under zsh
In zsh, `command printf` skips the builtin and forks `/usr/bin/printf`.
2026-10-06 17:54:48 -03:00
Cassidy Marble 1dd1d8c82e [Perf] nvm_get_os: read /etc/os-release instead of forking uname -a
The file is read, not sourced. An `ID` with no OS of its own is only taken as Linux when the kernel's `ostype` says so; otherwise `uname -a` decides.
2026-10-06 14:23:02 -03:00
Cassidy Marble c28f2b70db [Perf] nvm_npmrc_bad_news_bears: scan npmrc files without forking grep 2026-10-06 14:01:11 -03:00
Cassidy Marble f296b8d210 [Perf] nvm_die_on_prefix: detect the OS only when it is needed 2026-10-06 14:00:46 -03:00
Cassidy Marble c7ba8d2106 [Perf] nvm_version: resolve an exact, installed version without nvm_ls
An alias of the same name still takes precedence, as it does in `nvm_ls`.
2026-10-06 12:43:22 -03:00
Cassidy Marble d211d5fdb8 [Perf] nvm_is_version_installed: check the modern layout's path before the full lookup 2026-10-06 12:43:22 -03:00
Hridhin Varkey Joseph 913b8cb625 [Perf] nvm_resolve_local_alias: skip nvm_version for an exact, installed version
See #3416
2026-10-04 02:22:58 +05:30
Hridhin Varkey Joseph f1f3d463ab [Perf] nvm use: skip re-resolving an exact, installed version
When `nvm use` is given an exact `vX.Y.Z` that is already installed,
and no alias with that exact name exists,
use it directly instead of re-resolving it through
`nvm_match_version` and `nvm_ensure_version_installed`,
both of which call `nvm_version`.

`nvm_auto` takes this path on every shell startup with an already-resolved version,
so this removes ~95ms from each new shell
(~330ms -> ~235ms in a clean environment on macOS/zsh).

Fixes #3930
2026-10-01 09:51:16 +05:30
Jordan Harband 077156e88f [actions] never let an apt install wait on a prompt
Moving WSL package installs out of `setup-wsl`'s `additional-packages` lost its non-interactive setup:
on Ubuntu 18.04, upgrading `libssl1.1` asks whether to restart services,
and the job waited on that dialog until it was cancelled.
Set `DEBIAN_FRONTEND=noninteractive`,
keep existing config files without asking, and give apt no stdin.
2026-10-08 11:10:27 -07:00
Jordan Harband 50e73c4cd5 [actions] retry apt package installs through Ubuntu mirror outages
Mirror outages have outlasted the existing retries,
which covered only `apt-get update` (and not the WSL `additional-packages` install).
Installs now go through `.github/scripts/apt-install.sh`,
which retries each request within apt and retries the whole update+install with backoff for about 10 minutes.
2026-10-07 15:10:36 -07:00
Hridhin Varkey Joseph ed1b96f5db [readme] explain the misleading npm install error from npm run test/fast 2026-10-04 00:49:18 +05:30
Shrikant 5326eaab9d [Tests] add unit coverage for nvm_version_greater_than_or_equal_to 2026-10-03 12:49:00 +05:30
Hridhin Varkey Joseph a27fb0bd78 [Tests] add unit tests for nvm_version_greater_than_or_equal_to 2026-10-03 11:51:31 +05:30
Mingyang Wu cb96d2a56a [Fix] Handle filesystem identity when checking path containment
Fixes #1049.

Assisted-by: OpenAI GPT-6 <noreply@openai.com>
2026-09-11 16:49:46 +08:00
Jordan Harband 46ca42f939 [Tests] nvm install --reinstall-packages-from: mock the remote version instead of fetching it 2026-10-05 10:52:19 -07:00
Jordan Harband 52a1e55574 [actions] run the fast suite on macOS and WSL too
macOS covers a case-insensitive filesystem and bash 3.2
(`/bin/sh`, `/bin/bash`);
WSL covers Windows.
Both run it as the Linux jobs do:
without a system node, with a PTY,
and on WSL as a non-root user with passwordless sudo.
2026-09-30 16:12:14 +09:00
Jordan Harband 79bc9b90dd [Tests] make the fast suite pass on macOS
- `nvm_get_arch`: the unmocked smartos cases fall through to the host, so only run them on x86_64
- `nvm_get_arch_unofficial`: the chroot checks need x86_64 glibc Linux
- `nvm_install_no_progress_bar`: derive the tarball slug and checksum tool instead of assuming linux-x64 and `sha256sum`
2026-09-30 16:09:09 +09:00
Jordan Harband e2f57b733f [Fix] nvm alias: do not drop output from background jobs on bash 3.2
bash 3.2 (macOS `/bin/bash` and `/bin/sh`) exec-optimizes a trailing `command` call inside a function run as a background job,
which silently drops the output of nested command substitutions;
in `nvm alias` that lost installed-alias colors and some default aliases,
Running each job in an explicit subshell avoids it.
2026-09-30 15:56:49 +09:00
Jordan Harband 0add6b8555 [Fix] nvm: do not change or export the caller's IFS
`IFS=... nvm "$@"` is a prefix assignment to a function call, which bash's POSIX mode (macOS `/bin/sh`) keeps after the call returns, and exports.
2026-09-30 15:50:38 +09:00
Jordan Harband 3bfc2b4a9a [actions] rename windows-npm workflow to windows-nvm, since it tests nvm install 2026-09-30 15:25:38 +09:00
Jordan Harband 04ac3f2a83 [Fix] nvm install: do not remove the caller's TMPDIR after a failed download
`nvm_install_binary` and `nvm_install_source` declared `local TMPDIR` without initializing it, and remove it with `rm -rf` on failure. dash's `local` keeps the caller's value, as does bash's when `TMPDIR` is passed as a prefix assignment (`TMPDIR=… nvm install`), so a failed download removed the caller's temp directory; on macOS, `tar` instead blocked reading the archive from the terminal.
2026-10-05 10:02:48 -07:00
Ben YounesandJordan Harband a8bb497400 [New] nvm ls-remote: annotate versions with the node alias and local aliases
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-13) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.17) (push) Canceled after 0s
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: nvm install with set -e / matrix (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
update readme TOC / update readme TOC (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.17) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.23) (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests: nvm install with set -e / finisher (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.23) (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
Fixes #2786.

Ben Younes added the alias annotations to bare `nvm ls-remote`, with their regression tests;
Jordan Harband moved `(Latest: node)` onto the newest node release, gave each kind of annotation a fixed column so the output can be sliced with `cut`, matched aliases to versions in one pass, and kept local aliases out of the mocks and tests.

Co-authored-by: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
2026-09-23 21:35:43 +00:00
Jordan Harband 04fbd9570c [New] add nvm_has_italics, to detect terminal italics support via terminfo 2026-09-29 17:08:36 +09:00
Jordan Harband 09822033d2 [Fix] nvm exec/nvm run: do not treat filenames with digits as versions
update readme TOC / update readme TOC (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-24.04) (push) Canceled after 0s
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-12) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
Tests: nvm install with set -e / matrix (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.23) (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests: nvm install with set -e / finisher (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
`nvm_is_valid_version` accepted strings like `123.js`, `v1.js`, and `1.2.3.4.5.6.js`, because `nvm_version_greater_than_or_equal_to` exits as soon as the first number is greater than zero, without looking at the rest.
So `nvm run 123.js` failed with `N/A: version "v123.js" is not yet installed` instead of running the file.

It now checks the shape first: one to three dot-separated numbers, optionally with a trailing dot, and a prerelease suffix (rc, nightly, v8-canary, test builds) only after a full `x.y.z`.
A suffix with a dot followed by a non-digit, like a file extension, is rejected, so names like `1.2.3-foo.js` are treated as files too.
Every version listed in the nodejs.org and iojs.org `index.tab` files is still accepted, so shell startup keeps using a `default` alias that resolves to an installed prerelease.

Names that are also valid versions, like `123` or `v1`, are still treated as versions; `nvm run current 123` runs such a file.

Refs #1166. See #3931.
2026-09-28 15:05:28 +09:00
Jordan Harband a885b885fe v0.40.8
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-13) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-12) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-13) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests: nvm install with set -e / matrix (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
update readme TOC / update readme TOC (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.23) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.17) (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.23) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests: nvm install with set -e / finisher (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
Bug Fixes

 - `nvm_alias`, `nvm_version_path`: reject `..` path components
 - `nvm_get_make_jobs`: count cores on platforms the `case` does not name
 - `nvm-exec`: improve the no-version failure message
 - `nvm use`: do not clobber `man`'s default search path (#3890)
 - `nvm_err`, `nvm_err_with_colors`: do not fail when stderr is closed (#3907)
 - `nvm_hash_reset`: only run `hash -r` where the shell supports it
 - `nvm_alias`: unset zsh's `extendedglob` while reading an alias file (#3891)
 - zsh: restore `nomatch` and `markdirs` rather than clobbering them
 - `nvm --help`: render the set-colors legend in color (#3915)
 - `nvm unload`: drop the undefined `nvm_format_help_message_colors`
 - `nvm_get_mirror`: allow ports, userinfo, IPv6 hosts, and percent-encoding
 - `nvm_sanitize_auth_header`: allow `~`, completing RFC 7235 `token68` (#3751)

Refactors

 - `nvm --help`: extract the set-colors legend into `nvm_print_color_legend`

Performance

 - Optimize nvm_tree_contains_path with in-memory POSIX parent-walk (#3912)

Docs

 - [readme] document platforms with no official node binaries
 - `install.sh`: Fix missing words in bash/zsh completion message (#3887)
 - Remove stray closing HTML tag (#3919)

Misc

 - [meta] remove CLAUDE.md symlink in favor of AGENTS.md (#3928)
 - [meta] add `release-notes.sh`, the release notes generator

Tests

 - homebrew/actions changed their default branch
 - [actions] WSL: pin every distribution, and test the newest of each line
 - `nvm_print_color_legend`: look up the function with `PATH` emptied
 - `nvm_print_color_legend`: check for the function, not a same-named file
 - `nvm_print_color_legend`: fix the `fast` suite on GNU userlands
 - [actions] `release.yml`: provide `GH_TOKEN` so release-notes PR lookup can run
2026-09-21 10:23:47 +08:00
Jordan Harband 072622c748 [Fix] nvm_alias, nvm_version_path: reject .. path components
`nvm_alias` concatenated the requested name onto `$NVM_DIR/alias` and read whatever that resolved to,
so a name with a `..` component escaped the alias dir
- under the default layout, `../../.npmrc` reaches `$HOME/.npmrc`.
`nvm_print_alias_file` echoes every non-comment line of what it opens,
and `nvm use` reports the first one in its "is not yet installed" error,
so an untrusted `.nvmrc` could disclose any file the invoking user can read.

The write side already rejected `..` in an alias name (9275c5ba);
apply the same check on the read side, and to `nvm_version_path`,
which composes a version into a path with no check of its own.

Slashes stay legal, since `lts/iron` and the `lts/*` alias file depend on them.
2026-09-21 10:01:34 +08:00
Jarren San Jose 60a8da7a8e [meta] remove CLAUDE.md symlink in favor of AGENTS.md
Claude Code now reads AGENTS.md directly when a project has no CLAUDE.md,
so the root CLAUDE.md symlink pointing at AGENTS.md is redundant.
2026-09-18 16:33:51 -07:00
Jordan Harband 5267556406 [Tests] homebrew/actions changed their default branch 2026-09-21 09:17:45 +08:00
Jordan Harband a4f801ed72 [Fix] nvm_get_make_jobs: count cores on platforms the case does not name
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
Tests: nvm install with set -e / matrix (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-24.04) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
update readme TOC / update readme TOC (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.23) (push) Canceled after 0s
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests: nvm install with set -e / finisher (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
`nvm_get_os` also returns `win` (Cygwin/MSYS/MinGW) and the empty string,
neither of which had an arm,
so `NVM_CPU_CORES` went unassigned
and nvm asked the user to report a gap it already knew about.
On an unrecognized `uname` that also meant a single-threaded source build;
`win` refuses source builds a few lines later either way.

`NUMBER_OF_PROCESSORS` comes last because Windows scopes it to the calling process' processor group.

Assigning `NVM_CPU_CORES` in every arm also keeps the
`nvm_is_natural_num` check below from aborting dash and ksh under `set -u`.
2026-09-10 17:08:50 -07:00
Jordan Harband 7fc22fc9c7 [readme] document platforms with no official node binaries
The README never said which platforms nvm can detect but nodejs.org does not build for,
so a user on one of them only finds out from a slow, silent, source-build fallback.

Also corrects the Alpine section:
nvm remaps Alpine to a musl arch itself now,
and nodejs.org has published `linux-x64-musl` since v24.20.0,
so both the "no concrete plans" and the "does not exist errors" claims are out of date.

Coverage bounds are stated per release line rather than per patch,
since the newest of them are still shipping.
2026-09-10 17:11:20 -07:00
Hashim Khan b6d7823bce [Docs] install.sh: Fix missing words in bash/zsh completion message
When profile detection fails, the completion hint omitted "correct file"
between "to the" and "if you are using".

Fixes #3528
2026-07-23 08:24:46 +05:00
dajiaohuang 3fb99c652b [Docs] Remove stray closing HTML tag 2026-09-10 03:58:50 +08:00
Jordan Harband 74bb42ee23 [Fix] nvm-exec: improve the no-version failure message
The message claimed "no .nvmrc file found" even when one was found and its version simply was not installed,
and it never mentioned that `NODE_VERSION=default` selects the `default` alias.

Refs #3810
2026-09-08 23:47:09 -07:00
Thanniru Sai Teja cd84623ab2 [Perf] Optimize nvm_tree_contains_path with in-memory POSIX parent-walk
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-24.04) (push) Canceled after 0s
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
Tests: nvm install with set -e / matrix (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
update readme TOC / update readme TOC (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-12) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian-13) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-24.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine-3.23) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.17) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine-3.23) (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests: nvm install with set -e / finisher (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
Replace looping subshell process forks (dirname)
in nvm_tree_contains_path with case-guarded in-memory POSIX parameter expansion () and exact string equality comparisons.

Ensures literal string matching for glob metacharacters (*, ?, [])
and full zsh compatibility across all platforms.
2026-09-03 12:24:16 +05:30
Jordan Harband e361b93e4b [Fix] nvm use: do not clobber man's default search path
`man` consults its own configured search path only when MANPATH holds an empty entry;
a list without one replaces the default outright.
`nvm use` produced exactly that,
so activating a version could hide every system man page.

Contribute the empty entry as a trailing one,
so that nvm's directory keeps precedence over the system's,
and only when the list has none already,
so that repeated `nvm use` calls are idempotent and an empty entry the user placed stays where they put it.

The `$(manpath)` snapshot this replaces went stale the moment man's configuration changed,
and cost a subprocess per `nvm use`.
It was also dead: `local MANPATH` scoped the assignment to `nvm()`,
so `export` did not outlive the call and MANPATH went untouched whenever it started out unset.
Only ksh, where `local` is not a builtin, ever ran it.

`nvm deactivate` now unsets MANPATH where nvm's was the only real entry,
rather than leaving a bare `:` behind.

Reported and diagnosed by @al0ksar in #3890, which used a leading empty entry instead.
That one accrues one more colon on every `nvm use`,
which `nvm deactivate` then leaves behind,
and it loses to the system's man pages wherever nvm's bin directory is not first on PATH.

Supersedes #2077.

Refs #3890
Refs #2077
2026-09-08 11:01:03 -07:00
Jordan Harband a5ff3a32f4 [actions] WSL: pin every distribution, and test the newest of each line
The Ubuntu entries were pinned but `Debian` and `Alpine` were floating
aliases, so what those jobs tested drifted whenever the action updated.

Every line now carries a pin and the newest release setup-wsl offers for
it: Debian 12 and 13, Ubuntu 18.04, 20.04 and 24.04, Alpine 3.17 and 3.23.
`Alpine-3.17` is the image the unofficial jobs already ran, named
explicitly. Debian's pin is 12 rather than 11 because `Debian` and
`Debian-11` share a floating `aka.ms/wsl-debian-gnulinux` redirect and so
cannot be held still at all, where `Debian-12` is an immutable
salsa.debian.org artifact. The Debian-only steps key off `startsWith`, so
both Debian entries take the same path and moving a pin will not strand them.

There is no floating "newest" name to use instead: `kali-linux` is the only
unversioned distribution left, and setup-wsl's own CI disables
`additional-packages` on it. The newest only moves when the action's major
does, so the `uses:` ref is the thing to keep current.

Which is the other half of this: move that ref from v6 to v7. v6 is a dead
major, five months stale at v6.1.0 with no v6.2.0 and v7.0.0 tagged the next
day, so new distributions will only ever appear on v7 and later. v7's only
removals are the deprecated bare `Debian` and `Alpine`, which pinning has
already stopped using, and every name here is valid on both. It also drops
the Node.js 20 deprecation warning each WSL job currently emits, and it
tightens two pins that v6 left floating: Ubuntu 20.04 moves from
`aka.ms/wslubuntu2004` to a 20.04.6 image on releases.ubuntu.com, and 24.04
to a 24.04.4 one. Six of the seven platforms are now immutable artifacts;
Ubuntu 18.04 predates the format and still redirects through aka.ms.

Choosing a supported Debian also settles the 404s that had been failing
every Debian job: bullseye left LTS on 2026-08-31 and its security suite is
between homes, with `security.debian.org` still publishing an index whose
pool is being pruned and `archive.debian.org` carrying no `debian-security`
for bullseye yet. bookworm is on live mirrors, so `ca-certificates` is
current again, which matters for a job whose whole purpose is to fetch nvm
and node over TLS.

To keep a pin working once its release ages out in turn, derive sources.list
from the image's own codename and list every layout a release passes through:
main and security move to the archive on separate schedules, and the security
suite is renamed to `<codename>/updates` on the way. `apt-get update`
discards whichever entries 404, and where an index outlives its pool we fall
back once to main alone. Debian 13 moved to deb822, so clear both formats
first and leave what we write as the only thing apt reads.

Drop the blanket `apt-get upgrade` with it: it fetched 77 packages the test
never uses, and `apt-get install` already takes the newest version any
working mirror offers.
2026-09-08 11:01:02 -07:00
Lazizbek Ergashev ccb49e5cd0 [Fix] nvm_err, nvm_err_with_colors: do not fail when stderr is closed
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
Tests: nvm install with set -e / matrix (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
update readme TOC / update readme TOC (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine) (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
latest-npm.yml / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (no nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 1 shlvl) (push) Canceled after 0s
nvm-install-test.yml / test (nvmrc, ${{ fromJson(needs.matrix.outputs.matrix) }}, 2 shlvls) (push) Canceled after 0s
Tests: nvm install with set -e / finisher (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
Fixes #3906
2026-09-04 14:08:01 -07:00
Jordan Harband aeace4606f [Fix] nvm_hash_reset: only run hash -r where the shell supports it
Under bash's `set +h`, `hash -r` errors with "hash: hashing disabled",
which is then printed on every `nvm use`, including the one at shell startup.

Guarding on `$-` alone would be wrong:
`zsh` never puts `h` in `$-` - there `h` is `HIST_IGNORE_DUPS` -
and `dash` has no `h` flag at all,
so it would skip the call in 3 of the 4 shells the fast suite runs.

Gate on the shell instead, and skip only where the call fails:
bash under `set +h`, and `ksh93`, whose `hash` takes no `-r` and whose
usage error aborts `nvm use` before it can export `NVM_BIN`.
`ksh` is detected by probing rather than by version,
so `mksh` and `pdksh`, which do accept `-r`, keep getting the call.

The `${-#*h}` test is from #3910.

Refs #2065
Refs #3247
2026-09-04 09:16:10 -07:00
57 changed files with 2724 additions and 240 deletions
+52
View File
@@ -0,0 +1,52 @@
#!/bin/sh
# Install apt packages, riding out Ubuntu/Debian mirror outages: apt itself
# retries each request, and the whole update+install is retried with backoff
# for about 10 minutes, since outages have lasted longer than apt's own retries.
#
# usage: sh .github/scripts/apt-install.sh <package>...
# Runs apt-get through sudo when not root.
set -u
if [ "$#" -eq 0 ]; then
echo 'usage: apt-install.sh <package>...' >&2
exit 2
fi
SUDO=''
if [ "$(id -u)" != '0' ]; then
SUDO='sudo'
fi
apt_get() {
# never prompt: an upgrade (e.g. libssl asking to restart services) would wait forever
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get \
-o Acquire::Retries=5 \
-o Acquire::http::Timeout=30 \
-o Acquire::https::Timeout=30 \
-o Dpkg::Options::=--force-confdef \
-o Dpkg::Options::=--force-confold \
"$@" < /dev/null
}
ATTEMPT=1
MAX_ATTEMPTS=8
DELAY=15
while :; do
apt_get update || echo "apt-get update failed (attempt ${ATTEMPT}/${MAX_ATTEMPTS})" >&2
if apt_get install -y "$@"; then
exit 0
fi
if [ "${ATTEMPT}" -ge "${MAX_ATTEMPTS}" ]; then
echo "apt-get install failed after ${MAX_ATTEMPTS} attempts: $*" >&2
exit 1
fi
echo "apt-get install failed (attempt ${ATTEMPT}/${MAX_ATTEMPTS}); retrying in ${DELAY}s" >&2
sleep "${DELAY}"
ATTEMPT=$((ATTEMPT + 1))
DELAY=$((DELAY * 2))
if [ "${DELAY}" -gt 120 ]; then
DELAY=120
fi
done
+114
View File
@@ -0,0 +1,114 @@
#!/bin/sh
# Cache a container image as a tarball, keyed by digests looked up live from the registry: a cached
# image is only used if it is exactly what the registry serves now, so a poisoned cache entry is never used.
#
# usage:
# sh .github/scripts/docker-image.sh resolve <image>
# prints `key=<config digest>` and `digests=<index, manifest, and config digests>`, for $GITHUB_OUTPUT
# DIGESTS='<digests>' sh .github/scripts/docker-image.sh ensure <image> <tarball>
# loads <tarball> if it holds one of $DIGESTS; otherwise pulls <image>, checks it, and saves it to <tarball>
set -eu
ACCEPT='application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.v2+json'
sha256_of() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1"
else
shasum -a 256 "$1"
fi | cut -d ' ' -f 1
}
# fetches a manifest into a file; digests are computed from its exact bytes
registry_get() {
curl -fsSL --retry 5 --retry-all-errors -H "Accept: ${ACCEPT}" -o "$2" "$1"
}
resolve() {
IMAGE="$1"
HOST="${IMAGE%%/*}"
REST="${IMAGE#*/}"
REPO="${REST%:*}"
TAG="${REST##*:}"
OS="$(docker version --format '{{.Server.Os}}')"
ARCH="$(docker version --format '{{.Server.Arch}}')"
WORK="$(mktemp -d)"
trap 'rm -rf "${WORK}"' EXIT
registry_get "https://${HOST}/v2/${REPO}/manifests/${TAG}" "${WORK}/index.json"
INDEX_DIGEST="sha256:$(sha256_of "${WORK}/index.json")"
if jq -e '.manifests' "${WORK}/index.json" >/dev/null; then
MANIFEST_DIGEST="$(jq -r --arg os "${OS}" --arg arch "${ARCH}" '[.manifests[] | select(.platform.os == $os and .platform.architecture == $arch)][0].digest // empty' "${WORK}/index.json")"
if [ -z "${MANIFEST_DIGEST}" ]; then
echo "${IMAGE} has no ${OS}/${ARCH} image" >&2
exit 1
fi
registry_get "https://${HOST}/v2/${REPO}/manifests/${MANIFEST_DIGEST}" "${WORK}/manifest.json"
if [ "sha256:$(sha256_of "${WORK}/manifest.json")" != "${MANIFEST_DIGEST}" ]; then
echo "the ${OS}/${ARCH} manifest of ${IMAGE} does not match its digest" >&2
exit 1
fi
else
MANIFEST_DIGEST="${INDEX_DIGEST}"
cp "${WORK}/index.json" "${WORK}/manifest.json"
fi
CONFIG_DIGEST="$(jq -r '.config.digest' "${WORK}/manifest.json")"
echo "key=${CONFIG_DIGEST}"
echo "digests=${INDEX_DIGEST} ${MANIFEST_DIGEST} ${CONFIG_DIGEST}"
}
# an image's ID is its config digest (or, with the containerd image store, its manifest or index digest)
image_matches() {
ID="$(docker image inspect --format '{{.Id}}' "$1" 2>/dev/null)" || return 1
case " ${DIGESTS} " in
*" ${ID} "*) return 0 ;;
esac
return 1
}
ensure() {
IMAGE="$1"
TARBALL="$2"
if [ -f "${TARBALL}" ]; then
if docker load -i "${TARBALL}" && image_matches "${IMAGE}"; then
echo "loaded ${IMAGE} from the cache"
return 0
fi
echo "::warning::the cached ${IMAGE} does not match the registry's digests; pulling it instead"
docker image rm -f "${IMAGE}" >/dev/null 2>&1 || true
rm -f "${TARBALL}"
fi
ATTEMPT=1
until docker pull "${IMAGE}"; do
if [ "${ATTEMPT}" -ge 5 ]; then
echo "docker pull ${IMAGE} failed after ${ATTEMPT} attempts" >&2
return 1
fi
echo "docker pull failed, attempt ${ATTEMPT}/5"
sleep $((ATTEMPT * 5))
ATTEMPT=$((ATTEMPT + 1))
done
# the tag can move between `resolve` and the pull; then this run uses the image, but does not cache it
if image_matches "${IMAGE}"; then
docker save -o "${TARBALL}" "${IMAGE}"
else
echo "::warning::the pulled ${IMAGE} no longer matches the digests looked up earlier; not caching it"
fi
}
case "${1-}" in
resolve) resolve "${2-}" ;;
ensure) ensure "${2-}" "${3-}" ;;
*)
echo 'usage: docker-image.sh resolve <image> | ensure <image> <tarball>' >&2
exit 2
;;
esac
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
formulae.brew.sh:443
- uses: actions/checkout@v6
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
uses: Homebrew/actions/setup-homebrew@HEAD
- name: Install latest shellcheck
run: brew install shellcheck
env:
+32 -10
View File
@@ -46,6 +46,7 @@ jobs:
dl-cdn.alpinelinux.org:80
registry-1.docker.io:443
auth.docker.io:443
mirror.gcr.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
- uses: actions/checkout@v6
@@ -66,19 +67,29 @@ jobs:
node-version: 'lts/*'
skip-ls-check: true
- run: npm ls urchin
# Pull through Google's Docker Hub mirror, which is not subject to Docker Hub's
# anonymous pull rate limits, and cache the image; a cached image is only used
# if it matches the digests the registry serves now
- name: 'Resolve the alpine:${{ matrix.alpine }} image digests'
id: image
run: sh .github/scripts/docker-image.sh resolve mirror.gcr.io/library/alpine:${{ matrix.alpine }} >> "$GITHUB_OUTPUT"
- uses: actions/cache@v6
with:
path: ${{ runner.temp }}/docker-image.tar
key: docker-image-${{ runner.arch }}-${{ steps.image.outputs.key }}
- name: 'Load or pull the alpine:${{ matrix.alpine }} image'
env:
DIGESTS: ${{ steps.image.outputs.digests }}
run: sh .github/scripts/docker-image.sh ensure mirror.gcr.io/library/alpine:${{ matrix.alpine }} "${RUNNER_TEMP}/docker-image.tar"
- name: 'Run fast tests on Alpine ${{ matrix.alpine }} (${{ matrix.arch }})'
run: |
for i in 1 2 3 4 5; do
docker pull alpine:${{ matrix.alpine }} && break
echo "docker pull failed, attempt $i/5"; sleep $((i * 5))
done
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
-e "TEST_SHELL=${{ matrix.shell }}" \
-e "TERM=xterm-256color" \
-e "GITHUB_ACTIONS=true" \
alpine:${{ matrix.alpine }} \
mirror.gcr.io/library/alpine:${{ matrix.alpine }} \
sh -c '
set -ex
cat /etc/alpine-release; uname -m
@@ -142,23 +153,34 @@ jobs:
dl-cdn.alpinelinux.org:80
registry-1.docker.io:443
auth.docker.io:443
mirror.gcr.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
- uses: actions/checkout@v6
with:
submodules: false
# Pull through Google's Docker Hub mirror, which is not subject to Docker Hub's
# anonymous pull rate limits, and cache the image; a cached image is only used
# if it matches the digests the registry serves now
- name: 'Resolve the alpine:${{ matrix.alpine }} image digests'
id: image
run: sh .github/scripts/docker-image.sh resolve mirror.gcr.io/library/alpine:${{ matrix.alpine }} >> "$GITHUB_OUTPUT"
- uses: actions/cache@v6
with:
path: ${{ runner.temp }}/docker-image.tar
key: docker-image-${{ runner.arch }}-${{ steps.image.outputs.key }}
- name: 'Load or pull the alpine:${{ matrix.alpine }} image'
env:
DIGESTS: ${{ steps.image.outputs.digests }}
run: sh .github/scripts/docker-image.sh ensure mirror.gcr.io/library/alpine:${{ matrix.alpine }} "${RUNNER_TEMP}/docker-image.tar"
- name: 'Install node ${{ matrix.node }} from a musl binary on Alpine ${{ matrix.alpine }}'
run: |
for i in 1 2 3 4 5; do
docker pull alpine:${{ matrix.alpine }} && break
echo "docker pull failed, attempt $i/5"; sleep $((i * 5))
done
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
-e "NODE_VERSION=${{ matrix.node }}" \
-e "TERM=xterm-256color" \
alpine:${{ matrix.alpine }} \
mirror.gcr.io/library/alpine:${{ matrix.alpine }} \
sh -c '
set -ex
cat /etc/alpine-release; uname -m
+134 -5
View File
@@ -6,7 +6,7 @@ permissions:
contents: read
jobs:
fast:
fast-linux:
permissions:
contents: read
@@ -60,11 +60,11 @@ jobs:
git submodule update --init --recursive
- name: Install zsh, additional shells, and awk variant
run: |
sudo apt-get update
sudo apt-get install -y zsh ${{ matrix.awk }}
PACKAGES="zsh ${{ matrix.awk }}"
if [ "${{ matrix.shell }}" != "sh" ] && [ "${{ matrix.shell }}" != "bash" ] && [ "${{ matrix.shell }}" != "zsh" ]; then
sudo apt-get install -y ${{ matrix.shell }}
PACKAGES="${PACKAGES} ${{ matrix.shell }}"
fi
sh .github/scripts/apt-install.sh ${PACKAGES}
# Set the selected awk as the default
sudo update-alternatives --set awk /usr/bin/${{ matrix.awk }}
shell: bash
@@ -101,11 +101,140 @@ jobs:
if [ -f /usr/local/bin/npx.bak ]; then sudo mv /usr/local/bin/npx.bak /usr/local/bin/npx; fi
shell: bash
fast-macos:
permissions:
contents: read
# APFS is case-insensitive, and /bin/sh and /bin/bash are bash 3.2
name: 'fast (macOS, ${{ matrix.shell }})'
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
shell:
- sh
- bash
- dash
- zsh
steps:
- uses: actions/checkout@v6
id: checkout
continue-on-error: true
with:
submodules: true
- name: 'nvmrc submodule fallback (forks without their own nvmrc)'
if: steps.checkout.outcome == 'failure'
shell: bash
run: |
git submodule set-url test/fixtures/nvmrc https://github.com/nvm-sh/nvmrc.git
git submodule sync --recursive
git submodule update --init --recursive
- run: sw_vers; uname -m; which ${{ matrix.shell }}
- name: Ensure wget is installed
run: command -v wget || brew install wget
- run: wget --version
- uses: ljharb/actions/node/install@main
name: 'npm install && version checks'
with:
node-version: 'lts/*'
skip-ls-check: true
- run: npm ls urchin
- name: Hide system node
shell: bash
run: |
export PATH="$(echo "$PATH" | tr ':' '\n' | grep -v '\.nvm' | grep -v 'toolcache' | tr '\n' ':')"
for bin in node npm npx; do
while found="$(command -v "${bin}")"; do
sudo mv "${found}" "${found}.bak" || break
echo "${found}" >> "${RUNNER_TEMP}/hidden-node"
hash -r
done
done
- name: Run fast tests
shell: bash
run: |
unset NVM_CD_FLAGS NVM_BIN NVM_INC
export NVM_DIR="${{ github.workspace }}"
export PATH="$(echo "$PATH" | tr ':' '\n' | grep -v '\.nvm' | grep -v 'toolcache' | tr '\n' ':')"
script -q /dev/null make TERM=xterm-256color TEST_SUITE="fast" SHELL="${{ matrix.shell }}" URCHIN="${{ github.workspace }}/node_modules/.bin/urchin" test-${{ matrix.shell }} < /dev/null
- name: Restore system node
if: always()
shell: bash
run: |
if [ -f "${RUNNER_TEMP}/hidden-node" ]; then
while IFS= read -r found; do sudo mv "${found}.bak" "${found}"; done < "${RUNNER_TEMP}/hidden-node"
fi
fast-windows:
permissions:
contents: read
# GitHub's Windows runners provide WSL1
name: 'fast (WSL ${{ matrix.wsl-distrib }}, ${{ matrix.shell }})'
runs-on: windows-latest
defaults:
run:
shell: wsl-bash {0}
strategy:
fail-fast: false
matrix:
wsl-distrib:
- Ubuntu-24.04
shell:
- sh
- bash
- dash
- zsh
steps:
- uses: actions/checkout@v6
- uses: Vampire/setup-wsl@v7
with:
distribution: ${{ matrix.wsl-distrib }}
- name: Install packages with retries
# the Windows checkout has CRLF line endings
run: |
tr -d '\r' < "$(wslpath "${{ github.workspace }}")/.github/scripts/apt-install.sh" > /tmp/apt-install.sh
sh /tmp/apt-install.sh git make zsh dash sudo curl wget ca-certificates nodejs npm
- name: 'Clone into the WSL filesystem as a non-root user'
# the Windows checkout shows every file as executable, which urchin would run as tests
run: |
set -ex
useradd -m tester
echo 'tester ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/tester
chmod 0440 /etc/sudoers.d/tester
su tester -c '
set -ex
git config --global --add safe.directory "*"
git clone "$(wslpath "${{ github.workspace }}")" ~/nvm
cd ~/nvm
git submodule set-url test/fixtures/nvmrc https://github.com/nvm-sh/nvmrc.git
git submodule update --init --recursive
npm install
npm ls urchin
'
- name: Hide system node
run: |
for bin in node npm npx; do
if [ -e "/usr/bin/${bin}" ]; then mv "/usr/bin/${bin}" "/usr/bin/${bin}.bak"; fi
done
- name: Run fast tests
run: |
su tester -c '
cd ~/nvm
unset NVM_CD_FLAGS NVM_BIN NVM_INC
export NVM_DIR="${HOME}/nvm" GITHUB_ACTIONS=true TERM=xterm-256color
script -q -e -c "make TEST_SUITE=fast SHELL=${{ matrix.shell }} URCHIN=${HOME}/nvm/node_modules/.bin/urchin test-${{ matrix.shell }}" /dev/null
'
all:
permissions:
contents: none
name: 'all fast tests'
needs: [fast]
needs: [fast-linux, fast-macos, fast-windows]
runs-on: ubuntu-latest
steps:
- run: true
@@ -52,11 +52,11 @@ jobs:
git submodule update --init --recursive
- name: Install zsh and additional shells
run: |
sudo apt-get update
sudo apt-get install -y zsh
PACKAGES='zsh'
if [ "${{ matrix.shell }}" != "sh" ] && [ "${{ matrix.shell }}" != "bash" ] && [ "${{ matrix.shell }}" != "zsh" ]; then
sudo apt-get install -y ${{ matrix.shell }}
PACKAGES="${PACKAGES} ${{ matrix.shell }}"
fi
sh .github/scripts/apt-install.sh ${PACKAGES}
shell: bash
- run: sudo ${{ matrix.shell }} --version 2> /dev/null || dpkg -s ${{ matrix.shell }} 2> /dev/null || which ${{ matrix.shell }}
- run: wget --version
@@ -95,7 +95,7 @@ jobs:
shell: bash
- name: Restore curl
if: always()
run: sudo apt-get install curl -y
run: sh .github/scripts/apt-install.sh curl
shell: bash
installation_iojs_source_compile:
+18 -21
View File
@@ -44,6 +44,7 @@ jobs:
production.cloudfront.docker.com:443
registry-1.docker.io:443
auth.docker.io:443
mirror.gcr.io:443
- uses: actions/checkout@v6
id: checkout
continue-on-error: true
@@ -63,14 +64,22 @@ jobs:
skip-ls-check: true
- run: npm ls urchin
- run: npx which urchin
# Pull through Google's Docker Hub mirror, which is not subject to Docker Hub's
# anonymous pull rate limits, and cache the image; a cached image is only used
# if it matches the digests the registry serves now
- name: Resolve the ubuntu:16.04 image digests
id: image
run: sh .github/scripts/docker-image.sh resolve mirror.gcr.io/library/ubuntu:16.04 >> "$GITHUB_OUTPUT"
- uses: actions/cache@v6
with:
path: ${{ runner.temp }}/docker-image.tar
key: docker-image-${{ runner.arch }}-${{ steps.image.outputs.key }}
- name: Load or pull the ubuntu:16.04 image
env:
DIGESTS: ${{ steps.image.outputs.digests }}
run: sh .github/scripts/docker-image.sh ensure mirror.gcr.io/library/ubuntu:16.04 "${RUNNER_TEMP}/docker-image.tar"
- name: Run installation_node tests in container
run: |
# Retry the image pull to tolerate transient Docker registry failures
for i in 1 2 3 4 5; do
docker pull ubuntu:16.04 && break
echo "docker pull failed, attempt $i/5"
sleep $((i * 5))
done
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
@@ -79,25 +88,13 @@ jobs:
-e "DEBIAN_FRONTEND=noninteractive" \
-e "GITHUB_ACTIONS=true" \
-e "WITHOUT_CURL=${{ matrix.without_curl }}" \
ubuntu:16.04 \
mirror.gcr.io/library/ubuntu:16.04 \
bash -c '
set -ex
# Retry apt-get update up to 5 times due to flaky Ubuntu mirrors
# apt-get update can return 0 even with partial failures, so check for warnings
for i in 1 2 3 4 5; do
if apt-get update 2>&1 | tee /tmp/apt-update.log | grep -qE "^(W:|E:|Err:)"; then
echo "apt-get update had warnings/errors, attempt $i/5"
cat /tmp/apt-update.log
sleep $((i * 5))
else
break
fi
done
apt-get install -y git curl wget make build-essential python zsh libssl-dev
sh /workspace/.github/scripts/apt-install.sh git curl wget make build-essential python zsh libssl-dev
if [ "$TEST_SHELL" != "sh" ] && [ "$TEST_SHELL" != "bash" ]; then
apt-get install -y $TEST_SHELL || true
sh /workspace/.github/scripts/apt-install.sh $TEST_SHELL || true
fi
# Use nvm to install Node.js for running urchin
+18 -21
View File
@@ -41,6 +41,7 @@ jobs:
production.cloudfront.docker.com:443
registry-1.docker.io:443
auth.docker.io:443
mirror.gcr.io:443
- uses: actions/checkout@v6
id: checkout
continue-on-error: true
@@ -60,14 +61,22 @@ jobs:
skip-ls-check: true
- run: npm ls urchin
- run: npx which urchin
# Pull through Google's Docker Hub mirror, which is not subject to Docker Hub's
# anonymous pull rate limits, and cache the image; a cached image is only used
# if it matches the digests the registry serves now
- name: Resolve the ubuntu:16.04 image digests
id: image
run: sh .github/scripts/docker-image.sh resolve mirror.gcr.io/library/ubuntu:16.04 >> "$GITHUB_OUTPUT"
- uses: actions/cache@v6
with:
path: ${{ runner.temp }}/docker-image.tar
key: docker-image-${{ runner.arch }}-${{ steps.image.outputs.key }}
- name: Load or pull the ubuntu:16.04 image
env:
DIGESTS: ${{ steps.image.outputs.digests }}
run: sh .github/scripts/docker-image.sh ensure mirror.gcr.io/library/ubuntu:16.04 "${RUNNER_TEMP}/docker-image.tar"
- name: Run xenial tests in container
run: |
# Retry the image pull to tolerate transient Docker registry failures
for i in 1 2 3 4 5; do
docker pull ubuntu:16.04 && break
echo "docker pull failed, attempt $i/5"
sleep $((i * 5))
done
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
@@ -75,25 +84,13 @@ jobs:
-e "TERM=xterm-256color" \
-e "DEBIAN_FRONTEND=noninteractive" \
-e "GITHUB_ACTIONS=true" \
ubuntu:16.04 \
mirror.gcr.io/library/ubuntu:16.04 \
bash -c '
set -ex
# Retry apt-get update up to 5 times due to flaky Ubuntu mirrors
# apt-get update can return 0 even with partial failures, so check for warnings
for i in 1 2 3 4 5; do
if apt-get update 2>&1 | tee /tmp/apt-update.log | grep -qE "^(W:|E:|Err:)"; then
echo "apt-get update had warnings/errors, attempt $i/5"
cat /tmp/apt-update.log
sleep $((i * 5))
else
break
fi
done
apt-get install -y git curl wget make build-essential python zsh libssl-dev
sh /workspace/.github/scripts/apt-install.sh git curl wget make build-essential python zsh libssl-dev
if [ "$TEST_SHELL" != "sh" ] && [ "$TEST_SHELL" != "bash" ]; then
apt-get install -y $TEST_SHELL || true
sh /workspace/.github/scripts/apt-install.sh $TEST_SHELL || true
fi
# Use nvm to install Node.js for running urchin
+1 -1
View File
@@ -54,7 +54,7 @@ jobs:
azure.archive.ubuntu.com:80
packages.microsoft.com:443
- uses: actions/checkout@v6
- run: sudo apt-get update; sudo apt-get install ${{ matrix.shell }}
- run: sh .github/scripts/apt-install.sh ${{ matrix.shell }}
if: matrix.shell == 'zsh' || matrix.shell == 'ksh'
# zsh (https://github.com/actions/runner-images/issues/264) and ksh are not in the ubuntu image
shell: bash
@@ -107,10 +107,15 @@ jobs:
strategy:
fail-fast: false
matrix:
# each line gets a pin, plus the newest setup-wsl offers for it; the
# newest only moves when the action's major does, so bumping the `uses:`
# ref below is what keeps this current
wsl-distrib:
- Debian
# - Alpine # fails
- Debian-12
- Debian-13
# - Alpine-3.17 # fails
- Ubuntu-20.04
- Ubuntu-24.04
- Ubuntu-18.04
npm-node-version:
- '--lts'
@@ -128,31 +133,82 @@ jobs:
- wsl-distrib: Ubuntu-18.04
npm-node-version: '18'
# node v24+ doesn't work on WSL1 (exec format error)
- wsl-distrib: Debian
- wsl-distrib: Debian-12
npm-node-version: '--lts'
- wsl-distrib: Debian-13
npm-node-version: '--lts'
- wsl-distrib: Ubuntu-20.04
npm-node-version: '--lts'
- wsl-distrib: Ubuntu-24.04
npm-node-version: '--lts'
method:
- ''
- 'script'
steps:
# For Ubuntu: install with packages directly
- if: matrix.wsl-distrib != 'Debian'
uses: Vampire/setup-wsl@v6
# For Ubuntu: `additional-packages` can't retry, so install in a separate step
- if: ${{ !startsWith(matrix.wsl-distrib, 'Debian') }}
uses: Vampire/setup-wsl@v7
with:
distribution: ${{ matrix.wsl-distrib }}
additional-packages: bash git curl ca-certificates wget
# For Debian: install without packages first (apt-get update fails due to stale sources.list)
# see https://github.com/Vampire/setup-wsl/issues/76
- if: matrix.wsl-distrib == 'Debian'
uses: Vampire/setup-wsl@v6
with:
distribution: ${{ matrix.wsl-distrib }}
- if: matrix.wsl-distrib == 'Debian'
# mirror outages can outlast apt's own retries, so retry update+install with
# backoff for about 10 minutes (as .github/scripts/apt-install.sh does; this
# job has no checkout)
- if: ${{ !startsWith(matrix.wsl-distrib, 'Debian') }}
name: 'Install packages with retries'
shell: 'wsl-bash {0}'
run: 'sed -i s/ftp.debian.org/archive.debian.org/ /etc/apt/sources.list'
- if: matrix.wsl-distrib == 'Debian'
run: |
# never prompt: an upgrade (e.g. libssl asking to restart services) would wait forever
export DEBIAN_FRONTEND=noninteractive
attempt=1
delay=15
while true; do
apt-get -o Acquire::Retries=5 update < /dev/null || true
if apt-get -o Acquire::Retries=5 -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold install --yes bash git curl ca-certificates wget < /dev/null; then
break
fi
if [ "${attempt}" -ge 8 ]; then
echo "apt-get install failed after ${attempt} attempts" >&2
exit 1
fi
echo "apt-get install failed (attempt ${attempt}/8); retrying in ${delay}s" >&2
sleep "${delay}"
attempt=$((attempt + 1))
delay=$((delay * 2))
if [ "${delay}" -gt 120 ]; then delay=120; fi
done
# For Debian, install without packages: `additional-packages` would run
# `apt-get update` before we get to fix up sources.list
# see https://github.com/Vampire/setup-wsl/issues/76
- if: ${{ startsWith(matrix.wsl-distrib, 'Debian') }}
uses: Vampire/setup-wsl@v7
with:
distribution: ${{ matrix.wsl-distrib }}
# Debian's mirror layout shifts as a release ages out of LTS: main moves to
# archive.debian.org, and the security suite is both renamed and moved, on
# its own schedule. Offer every layout and let `apt-get update` discard the
# ones that 404, so this needs no edits as the image's release ages.
- if: ${{ startsWith(matrix.wsl-distrib, 'Debian') }}
name: 'Point apt at whichever mirrors still carry this release'
shell: 'wsl-bash {0}'
run: |
codename="$(. /etc/os-release && printf '%s' "${VERSION_CODENAME-}")"
if [ -z "${codename}" ]; then
echo 'no VERSION_CODENAME in /etc/os-release' >&2
exit 1
fi
# Debian 13 moved to deb822; drop both formats so what we write is the
# only thing apt reads, whichever release is pinned
rm -f /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources
{
echo "deb http://deb.debian.org/debian ${codename} main"
echo "deb http://archive.debian.org/debian ${codename} main"
echo "deb http://security.debian.org/debian-security ${codename}-security main"
echo "deb http://archive.debian.org/debian-security ${codename}-security main"
echo "deb http://archive.debian.org/debian-security ${codename}/updates main"
} >/etc/apt/sources.list
cat /etc/apt/sources.list
- if: ${{ startsWith(matrix.wsl-distrib, 'Debian') }}
name: 'Install packages with retries'
shell: 'wsl-bash {0}'
run: |
@@ -173,9 +229,18 @@ jobs:
}
done
}
retry apt-get update
retry apt-get upgrade --yes
retry apt-get install --yes bash git curl ca-certificates wget
# never prompt: an upgrade (e.g. libssl asking to restart services) would wait forever
export DEBIAN_FRONTEND=noninteractive
packages=(bash git curl ca-certificates wget)
install_options=(-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold install --yes)
retry apt-get update < /dev/null || true
if ! retry apt-get "${install_options[@]}" "${packages[@]}" < /dev/null; then
# a security index can outlive the pool objects it advertises, which
# no retry resolves; main is complete once a release is archived
sed -i '/debian-security/d' /etc/apt/sources.list
retry apt-get update < /dev/null || true
retry apt-get "${install_options[@]}" "${packages[@]}" < /dev/null
fi
- name: Retrieve nvm on WSL
run: |
@@ -204,7 +269,8 @@ jobs:
fail-fast: false
matrix:
wsl-distrib:
- Alpine
- Alpine-3.17
- Alpine-3.23
npm-node-version:
- '--lts'
- '21'
@@ -218,7 +284,7 @@ jobs:
- ''
- 'script'
steps:
- uses: Vampire/setup-wsl@v6
- uses: Vampire/setup-wsl@v7
with:
distribution: ${{ matrix.wsl-distrib }}
additional-packages: bash git curl ca-certificates wget
-1
View File
@@ -1 +0,0 @@
AGENTS.md
+3 -3
View File
@@ -15,14 +15,14 @@ LABEL version="latest"
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Prevent dialog during apt install
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive
# ShellCheck version
ENV SHELLCHECK_VERSION=0.7.0
# Pick a Ubuntu apt mirror site for better speed
# ref: https://launchpad.net/ubuntu/+archivemirrors
ENV UBUNTU_APT_SITE ubuntu.cs.utah.edu
ENV UBUNTU_APT_SITE=ubuntu.cs.utah.edu
# Replace origin apt package site with the mirror site
RUN sed -E -i "s/([a-z]+.)?archive.ubuntu.com/$UBUNTU_APT_SITE/g" /etc/apt/sources.list
@@ -92,7 +92,7 @@ RUN echo 'nvm ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
USER nvm
# Create a script file sourced by both interactive and non-interactive bash shells
ENV BASH_ENV /home/nvm/.bash_env
ENV BASH_ENV=/home/nvm/.bash_env
RUN touch "$BASH_ENV"
RUN echo '. "$BASH_ENV"' >> "$HOME/.bashrc"
+64 -21
View File
@@ -6,7 +6,7 @@
</a>
# Node Version Manager [![Tests](https://github.com/nvm-sh/nvm/actions/workflows/tests-fast.yml/badge.svg?branch=master)][3] [![nvm version](https://img.shields.io/badge/version-v0.40.7-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684)
# Node Version Manager [![Tests](https://github.com/nvm-sh/nvm/actions/workflows/tests-fast.yml/badge.svg?branch=master)][3] [![nvm version](https://img.shields.io/badge/version-v0.40.8-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684)
<!-- To update this table of contents, ensure you have run `npm install` then `npm run doctoc` -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
@@ -44,6 +44,7 @@
- [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)
- [Platforms without official binaries](#platforms-without-official-binaries)
- [.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)
@@ -106,10 +107,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](https://curl.se) or [Wget](https://www.gnu.org/software/wget/) command:
```sh
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
```
```sh
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/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 (`~/.bashrc`, `~/.bash_profile`, `~/.zshrc`, or `~/.profile`). If you find the install script is updating the wrong profile file, set the `$PROFILE` env var to the profile file’s path, and then rerun the installation script.
@@ -122,7 +123,7 @@ export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || pr
#### Additional Notes
- If the environment variable `$XDG_CONFIG_HOME` is present, it will place the `nvm` files there.</sub>
- If the environment variable `$XDG_CONFIG_HOME` is present, it will place the `nvm` files there.
- You can add `--no-use` to the end of the above script to postpone using `nvm` until you manually [`use`](#usage) it:
@@ -136,7 +137,7 @@ Eg: `curl ... | NVM_DIR="path/to/nvm"`. Ensure that the `NVM_DIR` does not conta
- The installer can use [`git`](https://git-scm.com/), `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.40.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.8/install.sh | bash'`
#### Installing in Docker
@@ -147,12 +148,12 @@ When invoking bash as a non-interactive shell, like in a [Docker](https://www.do
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Create a script file sourced by both interactive and non-interactive bash shells
ENV BASH_ENV "${HOME}/.bash_env"
ENV BASH_ENV="${HOME:-/root}/.bash_env"
RUN touch "${BASH_ENV}"
RUN echo '. "${BASH_ENV}"' >> ~/.bashrc
# Download and install nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | PROFILE="${BASH_ENV}" bash
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | PROFILE="${BASH_ENV}" bash
RUN echo node > .nvmrc
RUN nvm install
```
@@ -170,10 +171,10 @@ ARG NODE_VERSION=20
RUN apt update && apt install curl -y
# install nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
# set env
ENV NVM_DIR=/root/.nvm
ENV NVM_DIR="${HOME:-/root}/.nvm"
# install node
RUN bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION"
@@ -196,7 +197,7 @@ After creation of the image you can start container interactively and run comman
docker run --rm -it nvmimage
root@0a6b5a237c14:/# nvm -v
0.40.7
0.40.8
root@0a6b5a237c14:/# node -v
v19.9.0
@@ -259,7 +260,7 @@ You can use a task:
```yaml
- name: Install nvm
ansible.builtin.shell: >
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
args:
creates: "{{ ansible_env.HOME }}/.nvm/nvm.sh"
```
@@ -321,7 +322,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.40.7`
1. `cd ~/.nvm` and check out the latest version with `git checkout v0.40.8`
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:
@@ -400,6 +401,15 @@ You can list available versions using `ls-remote`:
nvm ls-remote
```
When no version or `--lts` filter is given, the list also marks the version the `node` alias would install, and every version that one of your own aliases would resolve to. Each kind of annotation always starts in the same column, so the output can be sliced with `cut -c` or similar tools:
```
v20.9.0 (Latest LTS: Iron) (Aliases: work)
v21.0.0
v21.1.0
v21.2.0 (Latest: node) (Aliases: default)
```
And then in any new shell just use the installed version:
```sh
@@ -646,6 +656,8 @@ nvm install iojs-v1.0.3
NVM_IOJS_ORG_MIRROR=https://iojs.org/dist nvm install iojs-v1.0.3
```
Some platforms and architectures have no binary on the default host at all; see [Platforms without official binaries](#platforms-without-official-binaries).
`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
@@ -655,6 +667,31 @@ To pass an Authorization header through to the mirror url, set `$NVM_AUTH_HEADER
NVM_AUTH_HEADER="Bearer secret-token" nvm install node
```
### Platforms without official binaries
nodejs.org does not publish a binary for every platform and architecture nvm can detect. Where it does not, `nvm install` falls back by default to compiling from source, which is slow and needs a C++ toolchain (see [Important Notes](#important-notes)); set `$NVM_NO_SOURCE_FALLBACK` to `1` to make a missing binary an error instead.
[unofficial-builds.nodejs.org](https://unofficial-builds.nodejs.org/download/release/) ([nodejs/unofficial-builds](https://github.com/nodejs/unofficial-builds)) publishes binaries for platforms the Node.js project does not officially support. To use them, point [`$NVM_NODEJS_ORG_MIRROR`](#use-a-mirror-of-node-binaries) at it:
```sh
export NVM_NODEJS_ORG_MIRROR=https://unofficial-builds.nodejs.org/download/release
```
| platform | binaries on nodejs.org | binaries on unofficial-builds |
| --- | --- | --- |
| `freebsd`, `openbsd` (any arch) | none | none |
| `sunos` (Solaris, illumos) | v13.x and earlier | none |
| `linux-x86` (32-bit) | v9.x and earlier | v8.16.0 through v21.x |
| `linux-armv6l` | v11.x and earlier | v8.16.0 through v22.x |
| `linux-armv7l` | v23.x and earlier | none |
| `linux-x64-musl` (Alpine) | v24.20.0+ and v26.8.0+ only | v8.16.0 and later |
| `linux-arm64-musl` (Alpine) | none | v20.20.1 and later |
| `linux-loong64` | none | v18.18.0 and later |
| `linux-riscv64` | none | v17.7.1 through v26.0.0 |
| `win-x86` (32-bit) | v22.x and earlier | none |
Neither host is gapless, and both change over time; the `index.tab` at the root of each is authoritative. Where neither has a binary, `nvm install` compiles from source, except on non-WSL Windows, which nvm cannot build on; on FreeBSD and OpenBSD it skips the download and goes straight to source. Alpine has its own section: [Installing nvm on Alpine Linux](#installing-nvm-on-alpine-linux).
### .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).
@@ -858,6 +895,12 @@ Run all of the tests like this:
npm test
`npm run test/fast` runs `make` inside a clean environment (`env -i ... bash -lc`), so `node` must be on the `PATH` of a fresh login `bash` shell.
If `node` is only available through `nvm` in your current shell, it fails with "Did you forget to run `npm install` after cloning the repo?", even after a successful `npm install`.
In that case, run `make` directly from the root of the nvm git repository, choosing the test suite and shell:
make TEST_SUITE=fast test-zsh
Nota bene: Avoid running nvm while the tests are running.
## Environment variables
@@ -870,7 +913,7 @@ nvm exposes the following environment variables:
- `NVM_CD_FLAGS` - used to maintain compatibility with zsh.
- `NVM_RC_VERSION` - version from .nvmrc file if being used.
Additionally, nvm modifies `PATH`, and, if present, `MANPATH` and `NODE_PATH` when changing versions.
Additionally, nvm modifies `PATH` when changing versions, along with `MANPATH` wherever a `manpath` command exists, and `NODE_PATH`, if present.
The following environment variables can be set to configure `nvm install`:
@@ -957,7 +1000,7 @@ set -e
In order to provide the best performance (and other optimizations), nvm will download and install pre-compiled binaries for Node (and npm) when you run `nvm install X`. The Node project compiles, tests and hosts/provides these pre-compiled binaries which are built for mainstream/traditional Linux distributions (such as Debian, Ubuntu, [CentOS](https://www.centos.org), [RedHat](https://www.redhat.com) et al).
[Alpine Linux](https://www.alpinelinux.org), unlike mainstream/traditional Linux distributions, is based on [BusyBox](https://www.busybox.net/), a very compact (~5MB) Linux distribution. BusyBox (and thus Alpine Linux) uses a different C/C++ stack to most mainstream/traditional Linux distributions - [musl](https://www.musl-libc.org/). This makes binary programs built for such mainstream/traditional incompatible with Alpine Linux, thus we cannot simply `nvm install X` on Alpine Linux and expect the downloaded binary to run correctly - you'll likely see "...does not exist" errors if you try that.
[Alpine Linux](https://www.alpinelinux.org), unlike mainstream/traditional Linux distributions, is based on [BusyBox](https://www.busybox.net/), a very compact (~5MB) Linux distribution. BusyBox (and thus Alpine Linux) uses a different C/C++ stack to most mainstream/traditional Linux distributions - [musl](https://www.musl-libc.org/). This makes binary programs built for such mainstream/traditional distributions incompatible with Alpine Linux, so on `x64` and `arm64` nvm requests a `musl` build instead. nodejs.org publishes those only for some recent `x64` releases, so for anything else the download 404s and `nvm install X` falls back to compiling from source, unless you point it at a mirror that has one (see [Platforms without official binaries](#platforms-without-official-binaries)).
There is a `-s` flag for `nvm install` which requests nvm download Node source and compile it locally.
@@ -966,18 +1009,18 @@ 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.40.7/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/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.40.7/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/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`](https://www.python.org/) 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._
The Node project has some desire but no concrete plans (due to the overheads of building, testing and support) to offer Alpine-compatible binaries.
The Node project now publishes an official `linux-x64-musl` binary for some recent releases (v24.20.0+ and v26.8.0+; no v25 release has one). There is no official `arm64` musl binary.
As a potential alternative, [@mhart](https://github.com/mhart) (a Node contributor) has some [Docker images for Alpine Linux with Node and optionally, npm, pre-installed](https://github.com/mhart/alpine-node).
@@ -1072,9 +1115,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.40.7/install.sh
[2]: https://github.com/nvm-sh/nvm/blob/v0.40.8/install.sh
[3]: https://github.com/nvm-sh/nvm/actions/workflows/tests-fast.yml
[4]: https://github.com/nvm-sh/nvm/releases/tag/v0.40.7
[4]: https://github.com/nvm-sh/nvm/releases/tag/v0.40.8
[Urchin]: https://git.sdf.org/tlevine/urchin
[Fish]: https://fishshell.com
@@ -1159,7 +1202,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.40.7/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/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
@@ -1194,7 +1237,7 @@ Currently, the sole maintainer is [@ljharb](https://github.com/ljharb) - more ma
## Project Support
Only the latest version (v0.40.7 at this time) is supported.
Only the latest version (v0.40.8 at this time) is supported.
## Enterprise Support
+5 -2
View File
@@ -45,7 +45,7 @@ nvm_install_dir() {
}
nvm_latest_version() {
nvm_echo "v0.40.7"
nvm_echo "v0.40.8"
}
nvm_profile_is_bash_or_zsh() {
@@ -490,13 +490,16 @@ nvm_do_install() {
# shellcheck disable=SC2016
if ${BASH_OR_ZSH} && ! command grep -qc '$NVM_DIR/bash_completion' "$NVM_PROFILE"; then
nvm_echo "=> Appending bash_completion source string to $NVM_PROFILE"
if [ -n "$(command tail -c 1 "$NVM_PROFILE")" ]; then
nvm_echo >> "$NVM_PROFILE"
fi
command printf '%b' "$COMPLETION_STR" >> "$NVM_PROFILE"
else
nvm_echo "=> bash_completion source string already in ${NVM_PROFILE}"
fi
fi
if ${BASH_OR_ZSH} && [ -z "${NVM_PROFILE-}" ] ; then
nvm_echo "=> Please also append the following lines to the if you are using bash/zsh shell:"
nvm_echo "=> Please also append the following lines to the correct file if you are using bash/zsh shell:"
command printf "${COMPLETION_STR}"
fi
+3 -1
View File
@@ -12,7 +12,9 @@ if [ -n "$NODE_VERSION" ]; then
else
{ NVM_RC_VERSION="$(nvm_rc_version 3>&1 1>&4)"; } 4>&1 && nvm_ensure_version_installed "$NVM_RC_VERSION";
if ! nvm use >/dev/null 2>&1; then
echo "No NODE_VERSION provided; no .nvmrc file found" >&2
nvm_err 'nvm-exec: unable to select a node version'
# shellcheck disable=SC2016
nvm_err ' Set `NODE_VERSION` (e.g. `NODE_VERSION=default`), or add an `.nvmrc` file.'
exit 127
fi
fi
+598 -113
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "nvm",
"version": "0.40.7",
"version": "0.40.8",
"description": "Node Version Manager - Simple bash script to manage multiple active node.js versions",
"directories": {
"test": "test"
@@ -0,0 +1,20 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
nvm_version() {
echo 'nvm_version was called' >&2
return 42
}
EXACT="$(nvm_resolve_local_alias test-stable-1)"
[ "_$EXACT" = "_v0.0.1" ] || die "'nvm_resolve_local_alias test-stable-1' was not v0.0.1; got $EXACT"
echo v0.0.99 > ../../../alias/test-not-installed
NOT_INSTALLED="$(nvm_resolve_local_alias test-not-installed 2>/dev/null)"
EXIT_CODE=$?
rm -f ../../../alias/test-not-installed
[ "_$EXIT_CODE" = "_42" ] || die "an exact version that is not installed should still go through nvm_version; got exit code $EXIT_CODE"
@@ -0,0 +1,66 @@
#!/bin/sh
set -ex
die () { echo "$@" ; cleanup ; exit 1; }
cleanup() {
cd "${ORIG_PWD}" 2>/dev/null || true
[ -n "${TMP_DIR-}" ] && rm -rf "${TMP_DIR}"
}
export NVM_DIR="$(cd ../.. && pwd)"
: nvm.sh
\. ../../nvm.sh
\. ../common.sh
ORIG_PWD="$(pwd)"
# Run from a fresh, empty directory so no ambient .nvmrc above the test dir
# can satisfy the lookup and mask the warning.
TMP_DIR="$(mktemp -d)"
cd "${TMP_DIR}" || die "could not cd to temp dir"
EXEC_WARNING='WARNING: `nvm exec` was invoked without a version argument and without an .nvmrc file.'
RUN_WARNING='WARNING: `nvm run` was invoked without a version argument and without an .nvmrc file.'
for FILE in 123.js v1.23.js 1.2.3.js; do
set +ex # needed for stderr
RUN_STDERR="$(nvm run "${FILE}" </dev/null 2>&1 1>/dev/null)"
set -ex
case "${RUN_STDERR}" in
*"N/A: version \"v${FILE#v}\""*) die "'nvm run ${FILE}' treated the file as a version; got >${RUN_STDERR}<" ;;
*"${RUN_WARNING}"*) ;;
*) die "'nvm run ${FILE}' did not fall back with a warning; got >${RUN_STDERR}<" ;;
esac
done
set +ex # needed for stderr
EXEC_STDERR="$(nvm exec 1.2.3.js </dev/null 2>&1 1>/dev/null)"
set -ex
case "${EXEC_STDERR}" in
*'N/A: version "v1.2.3.js"'*) die "'nvm exec 1.2.3.js' treated the command as a version; got >${EXEC_STDERR}<" ;;
*"${EXEC_WARNING}"*) ;;
*) die "'nvm exec 1.2.3.js' did not fall back with a warning; got >${EXEC_STDERR}<" ;;
esac
# an uninstalled prerelease is still a version, not a file
set +ex # needed for stderr
RUN_RC_STDERR="$(nvm run v999.0.0-rc.1 app.js </dev/null 2>&1 1>/dev/null)"
set -ex
case "${RUN_RC_STDERR}" in
*'N/A: version "v999.0.0-rc.1" is not yet installed.'*) ;;
*) die "'nvm run v999.0.0-rc.1' did not report the prerelease as not installed; got >${RUN_RC_STDERR}<" ;;
esac
set +ex # needed for stderr
EXEC_RC_STDERR="$(nvm exec v999.0.0-rc.1 node </dev/null 2>&1 1>/dev/null)"
set -ex
case "${EXEC_RC_STDERR}" in
*'N/A: version "v999.0.0-rc.1" is not yet installed.'*) ;;
*) die "'nvm exec v999.0.0-rc.1' did not report the prerelease as not installed; got >${EXEC_RC_STDERR}<" ;;
esac
cleanup
@@ -5,6 +5,7 @@ set -ex
die () { echo "$@" ; cleanup ; exit 1; }
cleanup () {
rm -rf "${NVM_DIR}/v0.10.4"
unset -f nvm_remote_version
}
export NVM_DIR="$(cd ../.. && pwd)"
@@ -13,6 +14,8 @@ export NVM_DIR="$(cd ../.. && pwd)"
\. ../../nvm.sh
\. ../common.sh
nvm_remote_version() { nvm_echo "${1-}"; }
make_fake_node v0.10.4
nvm deactivate >/dev/null 2>&1
@@ -0,0 +1,45 @@
#!/bin/bash
# the `bash` shebang is deliberate: only bash can exhibit the bug, so pinning
# it keeps this meaningful in every job of the shell matrix
die () { echo "$@" ; cleanup ; exit 1; }
cleanup () {
set -h
rm -f "${OUTPUT_FILE-}"
}
export NVM_DIR="$(cd ../.. && pwd)"
: nvm.sh
\. ../../nvm.sh
\. ../common.sh
make_fake_node v0.2.3 || die 'unable to make fake node'
OUTPUT_FILE="$(mktemp)"
set +h
# not in a command substitution, so the `PATH` it sets survives to `nvm deactivate`
nvm use --delete-prefix v0.2.3 > "${OUTPUT_FILE}" 2>&1
OUTPUT="$(cat "${OUTPUT_FILE}")"
case "${OUTPUT}" in
*'hash: '*) die "nvm use complained about hashing: ${OUTPUT}" ;;
esac
case "${OUTPUT}" in
*'Now using node v0.2.3'*) ;;
*) die "nvm use did not activate v0.2.3: ${OUTPUT}" ;;
esac
nvm deactivate > "${OUTPUT_FILE}" 2>&1
OUTPUT="$(cat "${OUTPUT_FILE}")"
case "${OUTPUT}" in
*'hash: '*) die "nvm deactivate complained about hashing: ${OUTPUT}" ;;
esac
case "${OUTPUT}" in
*'removed from ${PATH}'*) ;;
*) die "nvm deactivate did not strip the nvm bin dir: ${OUTPUT}" ;;
esac
cleanup
@@ -0,0 +1,29 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
export NVM_DIR="$(cd ../.. && pwd)"
: nvm.sh
\. ../../nvm.sh
\. ../common.sh
make_fake_node v0.2.3 || die 'unable to make fake node v0.2.3'
make_fake_node v0.10.1 || die 'unable to make fake node v0.10.1'
nvm use --delete-prefix v0.2.3 >/dev/null 2>&1 || die 'failed to activate v0.2.3'
# run `node` from this shell, so that the shell caches where it found it
node >/dev/null 2>&1 || die 'fake node v0.2.3 is not runnable'
nvm use --delete-prefix v0.10.1 >/dev/null 2>&1 || die 'failed to activate v0.10.1'
ACTUAL="$(node)"
[ "${ACTUAL}" = 'v0.10.1' ] || die "expected node v0.10.1 after switching versions, got '${ACTUAL}'"
nvm deactivate >/dev/null 2>&1 || die 'failed to deactivate'
RESOLVED="$(command -v node || true)"
case "${RESOLVED}" in
"${NVM_DIR}"/*) die "after deactivating, node still resolves inside \${NVM_DIR}: ${RESOLVED}" ;;
esac
@@ -0,0 +1,68 @@
#!/bin/sh
set -e
die () { echo "$@" ; exit 1; }
export NVM_DIR="$(cd ../.. && pwd)"
# `--delete-prefix` covers only the npmrc files, so an inherited prefix in the
# environment would still abort `nvm use`
unset PREFIX npm_config_prefix NPM_CONFIG_PREFIX
: nvm.sh
\. ../../nvm.sh
\. ../common.sh
# the block under test is gated on `nvm_has manpath`, and the Alpine CI images
# ship no `manpath`; the output is recognizable so that a reintroduced
# `$(manpath)` call fails the assertions instead of passing vacuously
manpath() {
echo '/usr/share/man'
}
make_fake_node v0.10.2
make_fake_node v0.10.3
MAN_2="$(nvm_version_path v0.10.2)/share/man"
MAN_3="$(nvm_version_path v0.10.3)/share/man"
# nvm has to contribute the empty entry itself when there is nothing to preserve
unset MANPATH
nvm use --delete-prefix v0.10.2 --silent || die "Failed to activate v0.10.2"
[ "${MANPATH}" = "${MAN_2}:" ] || die "MANPATH should be '${MAN_2}:'; got '${MANPATH}'"
nvm deactivate --silent || die "Failed to deactivate v0.10.2"
[ -z "${MANPATH-}" ] || die "MANPATH should be unset again; got '${MANPATH}'"
# nvm's entry first, the empty entry last: the reverse of what a leading empty
# entry produces
MANPATH='/opt/foo/man'
nvm use --delete-prefix v0.10.2 --silent || die "Failed to activate v0.10.2"
[ "${MANPATH}" = "${MAN_2}:/opt/foo/man:" ] || die "MANPATH should be '${MAN_2}:/opt/foo/man:'; got '${MANPATH}'"
# switching versions replaces nvm's entry without accruing more empty ones
nvm use --delete-prefix v0.10.3 --silent || die "Failed to activate v0.10.3"
[ "${MANPATH}" = "${MAN_3}:/opt/foo/man:" ] || die "MANPATH should be '${MAN_3}:/opt/foo/man:'; got '${MANPATH}'"
nvm use --delete-prefix v0.10.2 --silent || die "Failed to reactivate v0.10.2"
[ "${MANPATH}" = "${MAN_2}:/opt/foo/man:" ] || die "MANPATH should be '${MAN_2}:/opt/foo/man:'; got '${MANPATH}'"
nvm deactivate --silent || die "Failed to deactivate v0.10.2"
[ "${MANPATH}" = '/opt/foo/man:' ] || die "MANPATH should be '/opt/foo/man:'; got '${MANPATH}'"
# a value with no empty entry at all still deactivates to nothing
MANPATH="${MAN_2}"
nvm deactivate --silent || die "Failed to deactivate v0.10.2"
[ -z "${MANPATH-}" ] || die "MANPATH should be unset again; got '${MANPATH}'"
# an empty entry the user placed themselves stays where they put it
for TEST_MANPATH in ':/opt/foo/man' '/opt/foo/man:' '/a/man::/b/man'; do
MANPATH="${TEST_MANPATH}"
nvm use --delete-prefix v0.10.2 --silent || die "Failed to activate v0.10.2 with MANPATH '${TEST_MANPATH}'"
[ "${MANPATH}" = "${MAN_2}:${TEST_MANPATH}" ] || die "MANPATH should be '${MAN_2}:${TEST_MANPATH}'; got '${MANPATH}'"
nvm deactivate --silent || die "Failed to deactivate v0.10.2 with MANPATH '${TEST_MANPATH}'"
[ "${MANPATH}" = "${TEST_MANPATH}" ] || die "MANPATH should be '${TEST_MANPATH}'; got '${MANPATH}'"
done
@@ -0,0 +1,19 @@
#!/bin/sh
die () { IFS=' '; echo "$@" ; exit 1; }
: nvm.sh
\. ../../nvm.sh
IFS=':'
nvm --version >/dev/null
[ "${IFS}" = ':' ] || die "nvm changed the caller's IFS; got >${IFS}<"
set -e
nvm --version >/dev/null
set +e
[ "${IFS}" = ':' ] || die "nvm changed the caller's IFS under set -e; got >${IFS}<"
! env | grep -q '^IFS=' || die 'nvm exported IFS'
IFS=' '
@@ -1,14 +1,28 @@
#!/bin/bash
set -x
export NVM_DIR="$(cd ../.. && pwd)"
# an ambient value would send nvm-exec down its `NODE_VERSION` branch
unset NODE_VERSION
: nvm.sh
\. ../../nvm.sh
cleanup() { rm -f .nvmrc; }
ORIG_PWD="$(pwd)"
cleanup() {
cd "${ORIG_PWD}" 2>/dev/null || true
rm -f .nvmrc
[ -n "${TMP_DIR-}" ] && rm -rf "${TMP_DIR}"
}
die () { echo "$@" ; cleanup ; exit 1; }
NVM_TEST_VERSION=v0.42
HINT="nvm-exec: unable to select a node version
Set \`NODE_VERSION\` (e.g. \`NODE_VERSION=default\`), or add an \`.nvmrc\` file."
# Write it to nvmrc
echo "$NVM_TEST_VERSION" > .nvmrc
@@ -17,9 +31,26 @@ EXPECTED="Found '$(pwd)/.nvmrc' with version <${NVM_TEST_VERSION}>
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";
${HINT}";
# Skip install, we want to test the error message
[ "${EXPECTED}" = "${OUTPUT}" ] || die "expected >${EXPECTED}<, got >${OUTPUT}<"
rm -f .nvmrc
NVM_EXEC="$(cd ../.. && pwd)/nvm-exec"
# Run from a fresh, empty directory so no ambient .nvmrc above the test dir
# can satisfy the lookup and mask the hint.
TMP_DIR="$(mktemp -d)"
cd "${TMP_DIR}" || die "could not cd to temp dir"
OUTPUT="$("${NVM_EXEC}" node </dev/null 2>&1)";
EXIT_CODE=$?
EXPECTED="No version provided and no .nvmrc file found
${HINT}";
[ "${EXPECTED}" = "${OUTPUT}" ] || die "expected >${EXPECTED}<, got >${OUTPUT}<"
[ "${EXIT_CODE}" = 127 ] || die "expected exit code 127, got >${EXIT_CODE}<"
cleanup
+1 -1
View File
@@ -797,4 +797,4 @@
v22.10.0
v22.11.0  (Latest LTS: Jod)
v23.0.0
v23.1.0
v23.1.0  (Latest: node)
+4 -1
View File
@@ -3,7 +3,7 @@
die () { echo "$@" ; cleanup ; exit 1; }
cleanup() {
unset -f nvm_download nvm_ls_remote nvm_ls_remote_iojs
unset -f nvm_download nvm_ls_remote nvm_ls_remote_iojs nvm_get_remote_aliases nvm_has_italics
if [ -n "${TEMP_NVM_COLORS-}" ]; then
export NVM_COLORS=TEMP_NVM_COLORS
fi
@@ -87,6 +87,9 @@ REMOTE_IOJS="${PWD}/mocks/nvm_ls_remote_iojs.txt"
nvm_ls_remote_iojs() {
cat "${REMOTE_IOJS}"
}
# the mock must not depend on whatever local aliases exist in $NVM_DIR
nvm_get_remote_aliases() { :; }
nvm_has_italics() { return 0; }
EXPECTED_OUTPUT_PATH="${MOCKS_DIR}/nvm ls-remote.txt"
OUTPUT="$(nvm ls-remote | sed 's/[ \t]*$//')"
+126
View File
@@ -0,0 +1,126 @@
#!/bin/sh
WORK="${PWD}/nvm-ls-remote-aliases-work.$$"
export HOME="${WORK}/home"
export NVM_DIR="${HOME}/.nvm"
cleanup() {
command rm -rf "${WORK}"
unset -f cleanup die nvm_has_colors nvm_has_italics nvm_remote_versions expected_row
}
die () { echo "$@" ; cleanup ; exit 1; }
command mkdir -p "${NVM_DIR}/alias/lts" "${NVM_DIR}/versions/node/v1.5.0"
: nvm.sh
\. ../../../nvm.sh
nvm_has_colors() { return 1; }
nvm_remote_versions() {
if [ -n "${NVM_LTS-}" ] || [ -n "${1-}" ]; then
command printf '%s\n' 'v2.0.0'
else
# io.js sorts last here, so the latest node release is not the last row
command printf '%s\n' 'v0.11.16' 'v0.12.18' 'v1.0.0 Argon' 'v1.5.0' 'v2.0.0 Iron *' 'iojs-v3.3.1'
fi
return "${NVM_REMOTE_STATUS-0}"
}
nvm_make_alias 'project' '1' >/dev/null
nvm_make_alias 'argon-project' '1.0' >/dev/null
nvm_make_alias 'lts/iron' 'v2.0.0' >/dev/null
nvm_make_alias 'iron-project' 'lts/iron' >/dev/null
nvm_make_alias 'latest-project' 'node' >/dev/null
nvm_make_alias 'stable-project' 'stable' >/dev/null
nvm_make_alias 'unstable-project' 'unstable' >/dev/null
nvm_make_alias 'io-project' 'iojs' >/dev/null
nvm_make_alias '.hidden-project' '1' >/dev/null
command printf '%s\n' '[' > "${NVM_DIR}/alias/invalid-pattern"
command printf '%s\n' '1' > "${NVM_DIR}/alias/$(command printf 'control\rname')"
# the version cell is 17 wide (`%15s` plus the ` *` installed marker or two spaces), then LTS, Latest, and Aliases columns
expected_row() {
command printf '%-17s%-19s %-15s %s\n' "$1" "$2" "$3" "$4" | command sed 's/[[:space:]]*$//'
}
EXPECTED_OUTPUT="$(
expected_row ' v0.11.16' '' '' ' (Aliases: unstable-project)'
expected_row ' v0.12.18'
expected_row ' v1.0.0' ' (LTS: Argon)' '' ' (Aliases: argon-project)'
expected_row ' v1.5.0 *' '' '' ' (Aliases: project)'
expected_row ' v2.0.0' ' (Latest LTS: Iron)' ' (Latest: node)' ' (Aliases: iron-project, latest-project, stable-project)'
expected_row ' iojs-v3.3.1' '' '' ' (Aliases: io-project)'
)"
REMOTE_ERROR="${WORK}/remote-error"
OUTPUT="$(NVM_REMOTE_LATEST_ALIAS='injected' NVM_REMOTE_NAMED_ALIASES="$(command printf 'v0.12.18\tinjected')" nvm ls-remote --no-colors 2>"${REMOTE_ERROR}")"
[ ! -s "${REMOTE_ERROR}" ] \
|| die "bare nvm ls-remote emitted an error; got >$(command cat "${REMOTE_ERROR}")<"
[ "_${OUTPUT}" = "_${EXPECTED_OUTPUT}" ] \
|| die "bare nvm ls-remote did not annotate aliases in stable columns; got >${OUTPUT}< expected >${EXPECTED_OUTPUT}<"
ALIASES_COLUMN="$(command printf '%s\n' "${OUTPUT}" | command cut -c56-65 | command sort -u)"
[ "_${ALIASES_COLUMN}" = "_$(command printf '\n (Aliases:')" ] \
|| die "bare nvm ls-remote did not start every Aliases annotation in the same column; got >${ALIASES_COLUMN}<"
case "${OUTPUT}" in
*'node, stable'* | *unstable,* | *hidden* | *invalid* | *control* | *injected*)
die "bare nvm ls-remote showed an alias it should omit; got >${OUTPUT}<"
;;
esac
EXPECTED_FILTERED_OUTPUT='v2.0.0'
OUTPUT="$(nvm ls-remote 2 --no-colors | command sed 's/^[[:space:]]*//')"
[ "_${OUTPUT}" = "_${EXPECTED_FILTERED_OUTPUT}" ] \
|| die "filtered nvm ls-remote annotated aliases; got >${OUTPUT}< expected >${EXPECTED_FILTERED_OUTPUT}<"
OUTPUT="$(nvm ls-remote --lts --no-colors | command sed 's/^[[:space:]]*//')"
[ "_${OUTPUT}" = "_${EXPECTED_FILTERED_OUTPUT}" ] \
|| die "LTS nvm ls-remote annotated aliases; got >${OUTPUT}< expected >${EXPECTED_FILTERED_OUTPUT}<"
NVM_REMOTE_STATUS=1
OUTPUT="$(nvm ls-remote --no-colors 2>/dev/null)"
COMMAND_STATUS=$?
NVM_REMOTE_STATUS=0
[ "${COMMAND_STATUS}" -eq 1 ] \
|| die "failed nvm ls-remote returned ${COMMAND_STATUS}; expected 1"
case "${OUTPUT}" in
*Latest:* | *Aliases:*) die "failed nvm ls-remote annotated aliases; got >${OUTPUT}<" ;;
esac
nvm_has_colors() { return 0; }
nvm_has_italics() { return 0; }
ESC="$(command printf '\033')"
OUTPUT="$(nvm ls-remote)"
EXPECTED_LATEST_ROW="$(command printf ' v2.0.0 \033[1;32m (Latest LTS: Iron)\033[0m \033[0;32m (Latest: \033[3mnode\033[23m)\033[0m \033[0;32m (Aliases: \033[3miron-project\033[23m, \033[3mlatest-project\033[23m, \033[3mstable-project\033[23m)\033[0m')"
case "${OUTPUT}" in
*"${EXPECTED_LATEST_ROW}"*) ;;
*) die "colored nvm ls-remote did not use an unbolded color and italic names for aliases; got >${OUTPUT}<" ;;
esac
nvm_has_italics() { return 1; }
NO_ITALICS_OUTPUT="$(nvm ls-remote)"
nvm_has_italics() { return 0; }
EXPECTED_LATEST_ROW="$(command printf ' v2.0.0 \033[1;32m (Latest LTS: Iron)\033[0m \033[0;32m (Latest: node)\033[0m \033[0;32m (Aliases: iron-project, latest-project, stable-project)\033[0m')"
case "${NO_ITALICS_OUTPUT}" in
*"${EXPECTED_LATEST_ROW}"*) ;;
*) die "colored nvm ls-remote used italics on a terminal without italics support; got >${NO_ITALICS_OUTPUT}<" ;;
esac
OUTPUT="$(command printf '%s\n' "${OUTPUT}" | command sed "s/${ESC}\[[0-9;]*m//g")"
EXPECTED_OUTPUT="$(command printf '%s\n' "${EXPECTED_OUTPUT}" | command sed 's/^\( v1\.5\.0\) \*/\1 /')"
[ "_${OUTPUT}" = "_${EXPECTED_OUTPUT}" ] \
|| die "colored nvm ls-remote did not keep annotation columns aligned; got >${OUTPUT}< expected >${EXPECTED_OUTPUT}<"
nvm_has_colors() { return 1; }
nvm_remote_versions() {
command printf '%s\n' 'v2.0.0-nightly20240101abcdef0123 Iron *' 'v3.0.0-nightly2024020201234567890abc'
}
nvm_make_alias 'nightly-project' 'v2.0.0-nightly20240101abcdef0123' >/dev/null
OUTPUT="$(nvm ls-remote --no-colors)"
ALIASES_COLUMNS="$(command printf '%s\n' "${OUTPUT}" | command awk 'index($0, "(Aliases:") { print index($0, "(Aliases:") }' | command sort -u)"
[ "$(command printf '%s\n' "${ALIASES_COLUMNS}" | command wc -l | command tr -d ' ')" = 1 ] \
|| die "versions wider than the version column did not keep Aliases annotations in one column; got >${OUTPUT}<"
cleanup
@@ -0,0 +1,31 @@
#!/bin/sh
cleanup () {
rm -rf "$NVM_DIR"
unset -f die cleanup nvm_version
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
NVM_DIR="$(mktemp -d)"
NODE_BIN="$NVM_DIR/versions/node/v12.0.0/bin"
mkdir -p "$NODE_BIN"
printf '#!/bin/sh\necho v12.0.0\n' > "$NODE_BIN/node"
chmod +x "$NODE_BIN/node"
# the slow path resolves through nvm_version; make it fail so only the fast path can succeed
nvm_version() {
return 42
}
nvm use --silent v12.0.0 || die 'nvm use with an exact, installed version should not need nvm_version'
case ":${PATH}:" in
*":${NODE_BIN}:"*) ;;
*) die "nvm use did not put ${NODE_BIN} on PATH; got ${PATH}" ;;
esac
! nvm use --silent v12 2>/dev/null || die 'nvm use with a partial version should still resolve it through nvm_version'
cleanup
+67
View File
@@ -0,0 +1,67 @@
#!/bin/sh
ORIG_NVM_DIR="${NVM_DIR}"
TMP_DIR=''
cleanup () {
case "${TMP_DIR}" in
/*) rm -rf "${TMP_DIR}" ;;
esac
NVM_DIR="${ORIG_NVM_DIR}"
export NVM_DIR
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
TMP_DIR="$(mktemp -d)"
NVM_DIR="${TMP_DIR}/nvm"
export NVM_DIR
mkdir -p "${NVM_DIR}/alias/lts" || die 'could not create the scratch alias dir'
# a file outside $NVM_DIR that alias resolution must never reach
printf '%s\n' 'SECRET_OUTSIDE_NVM_DIR' > "${TMP_DIR}/outside"
# legitimate aliases, to prove the guard does not reject the names nvm uses
printf '%s\n' 'v1.2.3' > "${NVM_DIR}/alias/default"
printf '%s\n' 'v4.5.6' > "${NVM_DIR}/alias/lts/iron"
for TRAVERSAL in '../../outside' 'lts/../../../outside' '..' 'lts/..' 'a/../../outside'; do
OUTPUT="$(nvm_alias "${TRAVERSAL}" 2>/dev/null)"
EXIT_CODE=$?
[ "_${EXIT_CODE}" = '_3' ] || die "'nvm_alias ${TRAVERSAL}' exited with ${EXIT_CODE}, expected 3"
[ -z "${OUTPUT}" ] || die "'nvm_alias ${TRAVERSAL}' produced output: ${OUTPUT}"
# capture stderr through a file, and match rather than compare: ksh 93u+ has
# no `local`, so it interleaves its own noise with anything nvm.sh writes
nvm_alias "${TRAVERSAL}" >/dev/null 2>"${TMP_DIR}/stderr"
grep -qF "invalid alias name: ${TRAVERSAL}" "${TMP_DIR}/stderr" \
|| die "'nvm_alias ${TRAVERSAL}' produced stderr: $(cat "${TMP_DIR}/stderr")"
done
# the disclosure path the advisory reports: resolution must not echo the file
for TRAVERSAL in '../../outside' 'lts/../../../outside'; do
OUTPUT="$(nvm_resolve_alias "${TRAVERSAL}" 2>&1)"
case "${OUTPUT}" in
*SECRET_OUTSIDE_NVM_DIR*) die "'nvm_resolve_alias ${TRAVERSAL}' leaked a file outside \$NVM_DIR" ;;
esac
done
OUTPUT="$(nvm_alias default)"
[ "_${OUTPUT}" = '_v1.2.3' ] || die "'nvm_alias default' produced \"${OUTPUT}\", expected v1.2.3"
OUTPUT="$(nvm_alias lts/iron)"
[ "_${OUTPUT}" = '_v4.5.6' ] || die "'nvm_alias lts/iron' produced \"${OUTPUT}\", expected v4.5.6"
for BAD_VERSION in '../../outside' 'v1.2.3/../../..' '..'; do
OUTPUT="$(nvm_version_path "${BAD_VERSION}" 2>/dev/null)"
EXIT_CODE=$?
[ "_${EXIT_CODE}" = '_3' ] || die "'nvm_version_path ${BAD_VERSION}' exited with ${EXIT_CODE}, expected 3"
[ -z "${OUTPUT}" ] || die "'nvm_version_path ${BAD_VERSION}' produced output: ${OUTPUT}"
done
OUTPUT="$(nvm_version_path v18.0.0)"
[ "_${OUTPUT}" = "_${NVM_DIR}/versions/node/v18.0.0" ] || die "'nvm_version_path v18.0.0' produced \"${OUTPUT}\""
cleanup
@@ -0,0 +1,39 @@
#!/bin/sh
ORIG_NVM_DIR="${NVM_DIR}"
TMP_DIR=''
cleanup () {
case "${TMP_DIR}" in
/*) rm -rf "${TMP_DIR}" ;;
esac
NVM_DIR="${ORIG_NVM_DIR}"
export NVM_DIR
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
\. ../../common.sh
TMP_DIR="$(mktemp -d)"
NVM_DIR="${TMP_DIR}/nvm"
export NVM_DIR
mkdir -p "${NVM_DIR}/alias" || die 'could not create alias dir'
RELEASE='v998.0.0'
NIGHTLY='v999.0.0-nightly20241031996708042b'
make_fake_node "${RELEASE}" || die "fake node ${RELEASE} could not be made"
make_fake_node "${NIGHTLY}" || die "fake node ${NIGHTLY} could not be made"
for TARGET in "${NIGHTLY}" node; do
nvm_make_alias default "${TARGET}" || die "could not alias default to ${TARGET}"
nvm deactivate >/dev/null 2>&1
nvm_auto use || die "nvm_auto use failed with default -> ${TARGET}"
CURRENT="$(nvm current)"
[ "${CURRENT}" = "${NIGHTLY}" ] || die "with default -> ${TARGET}, nvm_auto use left 'nvm current' as >${CURRENT}<, expected >${NIGHTLY}<"
done
cleanup
+23
View File
@@ -0,0 +1,23 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
EXPECTED="$(\cd .. && pwd)"
# a user-defined `cd` function that rejects nvm's arguments, like cdhist's (#3835)
cd() {
echo 'user-defined cd function was called' >&2
return 1
}
OUTPUT="$(nvm_cd .. 2>&1 && pwd)"
[ "${OUTPUT}" = "${EXPECTED}" ] || die "expected '${EXPECTED}', got '${OUTPUT}'"
# shellcheck disable=SC2086
OUTPUT="$(nvm_cd ${NVM_CD_FLAGS} .. 2>&1 && pwd)"
[ "${OUTPUT}" = "${EXPECTED}" ] || die "with NVM_CD_FLAGS '${NVM_CD_FLAGS}', expected '${EXPECTED}', got '${OUTPUT}'"
unset -f cd
+14
View File
@@ -44,6 +44,20 @@ NEW_PATH=`nvm_change_path "$EMPTY_PATH" "/bin" "$NVM_DIR/v0.1.2"`
[ "$NEW_PATH" = "$NVM_DIR/v0.1.2/bin" ] || die "Not correctly prepended: $NEW_PATH "
# empty entries select `man`'s own search path, so they have to survive intact
MAN_PATH_WITH_EMPTY_ENTRIES=/opt/foo/man::/opt/bar/man:
# New version dir
NEW_PATH=`nvm_change_path "$MAN_PATH_WITH_EMPTY_ENTRIES" "/share/man" "$NVM_DIR/versions/node/v7.1.0"`
[ "$NEW_PATH" = "$NVM_DIR/versions/node/v7.1.0/share/man:$MAN_PATH_WITH_EMPTY_ENTRIES" ] || die "Not correctly prepended: $NEW_PATH "
# Replacing an existing version dir
NEW_PATH=`nvm_change_path "$NVM_DIR/versions/node/v4.5.0/share/man::/opt/bar/man:" "/share/man" "$NVM_DIR/versions/node/v7.1.0"`
[ "$NEW_PATH" = "$NVM_DIR/versions/node/v7.1.0/share/man::/opt/bar/man:" ] || die "Not correctly changed: $NEW_PATH "
# https://github.com/nvm-sh/nvm/issues/1652#issuecomment-342571223
MAC_OS_NESTED_SESSION_PATH=/usr/bin:/usr/local/bin:$NVM_DIR/versions/node/v4.5.0/bin
+37
View File
@@ -0,0 +1,37 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
for DIR in '/tmp/a&b/.nvm' '/tmp/a#b/.nvm' '/tmp/a[1]/.nvm' '/tmp/a*b/.nvm' '/tmp/a+(b)/.nvm' '/tmp/a.b/.nvm' '/tmp/a\b/.nvm' '/tmp/a$b/.nvm' '/tmp/a|b/.nvm'; do
NVM_DIR="${DIR}"
TEST_PATH="/opt/bin:${NVM_DIR}/versions/node/v4.5.0/bin:/usr/bin"
# replace branch
NEW_PATH="$(nvm_change_path "${TEST_PATH}" "/bin" "${NVM_DIR}/versions/node/v7.1.0")"
EXPECTED="/opt/bin:${NVM_DIR}/versions/node/v7.1.0/bin:/usr/bin"
[ "${NEW_PATH}" = "${EXPECTED}" ] || die "NVM_DIR=${DIR}: expected >${EXPECTED}<, got >${NEW_PATH}<"
# system path precedes the nvm path: prepend instead of replacing
SYSTEM_FIRST_PATH="/usr/bin:${NVM_DIR}/versions/node/v4.5.0/bin"
NEW_PATH="$(nvm_change_path "${SYSTEM_FIRST_PATH}" "/bin" "${NVM_DIR}/versions/node/v7.1.0")"
EXPECTED="${NVM_DIR}/versions/node/v7.1.0/bin:${SYSTEM_FIRST_PATH}"
[ "${NEW_PATH}" = "${EXPECTED}" ] || die "NVM_DIR=${DIR} (system path first): expected >${EXPECTED}<, got >${NEW_PATH}<"
# MANPATH call
TEST_MANPATH="/opt/share/man:${NVM_DIR}/versions/node/v4.5.0/share/man:/usr/share/man"
NEW_PATH="$(nvm_change_path "${TEST_MANPATH}" "/share/man" "${NVM_DIR}/versions/node/v7.1.0")"
EXPECTED="/opt/share/man:${NVM_DIR}/versions/node/v7.1.0/share/man:/usr/share/man"
[ "${NEW_PATH}" = "${EXPECTED}" ] || die "NVM_DIR=${DIR} (MANPATH): expected >${EXPECTED}<, got >${NEW_PATH}<"
done
# `.` in NVM_DIR must be escaped so it matches itself only, not "any character":
# an unrelated path entry that merely looks similar (some other char where the
# `.` is) must be left alone, not mistaken for an nvm path and rewritten.
NVM_DIR="/tmp/a.b/.nvm"
UNRELATED_PATH="/opt/bin:/tmp/aXb/.nvm/versions/node/v4.5.0/bin:/usr/bin"
NEW_PATH="$(nvm_change_path "${UNRELATED_PATH}" "/bin" "${NVM_DIR}/versions/node/v7.1.0")"
EXPECTED="${NVM_DIR}/versions/node/v7.1.0/bin:${UNRELATED_PATH}"
[ "${NEW_PATH}" = "${EXPECTED}" ] || die "unrelated PATH entry /tmp/aXb/.nvm/... should not be touched by NVM_DIR=${NVM_DIR}: expected >${EXPECTED}<, got >${NEW_PATH}<"
@@ -54,4 +54,6 @@ EXPECTED_OUTPUT='Checksums matched!'
[ "${CAPTURED_STDERR}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${CAPTURED_STDERR}<"
[ "${CAPTURED_EXIT_CODE}" = 0 ] || die "expected to exit with code 0, got ${CAPTURED_EXIT_CODE}"
(set +x; nvm_compare_checksum ../../../nvm.sh checksum 2>&-) || die "with stderr closed, expected to exit with code 0, got $?"
cleanup
+65
View File
@@ -49,6 +49,20 @@ nvm_has() { return 0; }
OUTPUT="$(nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' was not a noop when prefix is good; got '$OUTPUT'"
# `nvm_get_os` runs `uname`; it is only needed when an `NPM_CONFIG_PREFIX`
# variable is set, so with none set it must not run at all
MOCK_BIN="${TEST_DIR}/bin"
mkdir -p "${MOCK_BIN}"
{
echo '#!/bin/sh'
echo 'echo "uname was called" >&2'
echo 'exit 1'
} > "${MOCK_BIN}/uname"
chmod +x "${MOCK_BIN}/uname"
unset NPM_CONFIG_PREFIX npm_config_prefix npm_CONFIG_PREFIX
OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' detected the OS (ran uname) when no NPM_CONFIG_PREFIX was set; got '$OUTPUT'"
mkdir -p "$(nvm_version_dir new)"
ln -s "$(nvm_version_dir new)" "$TEST_DIR/node"
@@ -187,4 +201,55 @@ Run \`foo\` to unset it."
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has globalconfig did not exit with 10; got '$CAPTURED_EXIT_CODE'"
)
# nvm_npmrc_bad_news_bears matches `^(prefix|globalconfig) *=`
NPMRC="${TEST_DIR}/bad-news.npmrc"
printf 'prefix=x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix=x should be bad news'
printf 'prefix =x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix =x should be bad news'
printf 'prefix =x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix =x should be bad news'
printf 'prefix =\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix = should be bad news'
printf 'foo=1\nprefix = y\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a matching line after a non-matching line should be bad news'
printf 'prefix=x' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix=x without a trailing newline should be bad news'
printf 'globalconfig=x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'globalconfig=x should be bad news'
printf 'globalconfig = x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'globalconfig = x should be bad news'
printf 'prefixfoo=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefixfoo=x should not be bad news'
printf 'globalconfigfoo=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'globalconfigfoo=x should not be bad news'
printf 'prefix x=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix x=x should not be bad news'
printf 'prefix\t=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a tab before = should not be bad news'
printf ' prefix=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a leading space should not be bad news'
printf 'Prefix=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'an uppercase key should not be bad news'
printf 'prefix\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a bare prefix should not be bad news'
printf 'prefix \n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'trailing spaces without = should not be bad news'
: > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'an empty npmrc should not be bad news'
! nvm_npmrc_bad_news_bears || die 'a missing argument should not be bad news'
! nvm_npmrc_bad_news_bears "${TEST_DIR}/nonexistent.npmrc" || die 'a missing file should not be bad news'
# the npmrc scan must not fork `grep`
(
rm -f "${TEST_DIR}/grep-was-called"
nvm_grep() { : > "${TEST_DIR}/grep-was-called"; return 1; }
printf 'globalconfig = nope\n' > "${TEST_DIR}/probe.npmrc"
NVM_PROBE_EXIT=0
nvm_npmrc_bad_news_bears "${TEST_DIR}/probe.npmrc" || NVM_PROBE_EXIT=$?
[ ! -e "${TEST_DIR}/grep-was-called" ] || exit 10
[ "${NVM_PROBE_EXIT}" = 0 ] || exit 11
) || die 'nvm_npmrc_bad_news_bears must read npmrc files without calling nvm_grep'
cleanup
+38
View File
@@ -0,0 +1,38 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
cleanup() {
rm -rf "${TEST_DIR}"
}
: nvm.sh
\. ../../../nvm.sh
TEST_DIR="$(pwd)/nvm_echo_tmp"
[ ! -e "${TEST_DIR}" ] && mkdir "${TEST_DIR}"
# a `printf` that reports that it ran: `nvm_echo` must use a shell builtin
# rather than resolving `printf` through `PATH` (zsh's `command` skips the
# builtin and runs `/usr/bin/printf` on every call)
MOCK_BIN="${TEST_DIR}/bin"
mkdir -p "${MOCK_BIN}"
{
echo '#!/bin/sh'
echo "echo 'MOCKED-PRINTF'"
} > "${MOCK_BIN}/printf"
chmod +x "${MOCK_BIN}/printf"
OUTPUT="$(nvm_echo 'hello world')"
[ "${OUTPUT}" = 'hello world' ] || die "expected 'hello world', got '${OUTPUT}'"
OUTPUT="$(nvm_echo)"
[ -z "${OUTPUT}" ] || die "expected no output, got '${OUTPUT}'"
OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_echo 'no fork, please' 2>&1)"
[ "${OUTPUT}" = 'no fork, please' ] || die "for nvm_echo, expected 'no fork, please', got '${OUTPUT}'"
OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_echo_with_colors 'no fork, please' 2>&1)"
[ "${OUTPUT}" = 'no fork, please' ] || die "for nvm_echo_with_colors, expected 'no fork, please', got '${OUTPUT}'"
cleanup
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
\. ../../common.sh
try_err nvm_err 'an error'
EXPECTED_OUTPUT='an error'
[ "${CAPTURED_STDERR}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${CAPTURED_STDERR}<"
[ "${CAPTURED_EXIT_CODE}" = 0 ] || die "expected to exit with code 0, got ${CAPTURED_EXIT_CODE}"
try_err nvm_err_with_colors 'an error'
EXPECTED_OUTPUT='an error'
[ "${CAPTURED_STDERR}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${CAPTURED_STDERR}<"
[ "${CAPTURED_EXIT_CODE}" = 0 ] || die "expected to exit with code 0, got ${CAPTURED_EXIT_CODE}"
nvm_err 'an error' 2>&- || die "nvm_err with stderr closed exited with code $?"
nvm_err_with_colors 'an error' 2>&- || die "nvm_err_with_colors with stderr closed exited with code $?"
+8 -4
View File
@@ -21,6 +21,10 @@ MOCKS_DIR="$(pwd)/../../mocks"
# binaries
export PATH=".:${PATH}"
# `nvm_get_os` reads `/etc/os-release` where it is available; this test drives
# the OS through the mocked `uname`, so point it at a file that does not exist
export NVM_OS_RELEASE="${MOCKS_DIR}/nonexistent-os-release"
# Setups mock binaries for a given OS and arch that mimic
# the output of the real binaries used by nvm_get_arch to guess
# the architecture of a given system.
@@ -90,10 +94,10 @@ run_test amd64 smartos x64 no_pkg_info
run_test x86 osx x86
run_test amd64 osx x64
# These smartos cases have no arch-specific uname mock, so nvm_get_os falls
# through to the real host; on Alpine that host is linux and picks up the musl
# suffix, which these non-musl assertions do not expect. Skip them there.
if [ ! -f "/etc/alpine-release" ]; then
# These smartos cases have no arch-specific uname mock, so they fall through to
# the real host: they only hold on an x86_64 host, and not on Alpine, where the
# host picks up the musl suffix these non-musl assertions do not expect.
if [ ! -f "/etc/alpine-release" ] && [ "$(command uname -m)" = 'x86_64' ]; then
run_test arm64 smartos x64
run_test armv8l smartos x64
fi
+4
View File
@@ -15,6 +15,10 @@ die () { cleanup; echo "$@" ; exit 1; }
MOCKS_DIR="$(pwd)/../../mocks"
export PATH=".:${PATH}"
# `nvm_get_os` reads `/etc/os-release` where it is available; this test drives
# the OS through the mocked `uname`, so point it at a file that does not exist
export NVM_OS_RELEASE="${MOCKS_DIR}/nonexistent-os-release"
# On Alpine (where /etc/alpine-release exists), both x64 and arm64 should get
# the -musl suffix, since unofficial-builds publishes musl binaries for both.
# On non-Alpine, neither should get -musl.
@@ -63,6 +63,8 @@ setup_chroot() {
# test, so skip the chroot checks there and still run the ls-remote checks.
if [ -f "/etc/alpine-release" ]; then
echo "on Alpine; skipping chroot arch checks (covered by 'nvm_get_arch alpine')"
elif [ "$(command uname -s)" != 'Linux' ] || [ "$(command uname -m)" != 'x86_64' ] || [ ! -e /lib64/ld-linux-x86-64.so.2 ]; then
echo "not on x86_64 glibc Linux; skipping chroot arch checks"
else
setup_chroot "${CHROOT_WITH_ALPINE}"
setup_chroot "${CHROOT_WITHOUT_ALPINE}"
+147
View File
@@ -0,0 +1,147 @@
#!/bin/sh
# `nvm_get_make_jobs` sets the global `NVM_MAKE_JOBS` instead of echoing it, so
# every case runs it in this shell, with its output captured to files.
ORIG_PATH="${PATH}"
TMP_DIR="$(mktemp -d)"
# the probe shims live under `mktemp -d` rather than `.`, because this directory
# is shared with every other unit test and a leaked `getconf` would poison them
SHIMS="${TMP_DIR}/bin"
OUT="${TMP_DIR}/out"
ERR="${TMP_DIR}/err"
cleanup () {
export PATH="${ORIG_PATH}"
rm -rf "${TMP_DIR}"
}
die () { cleanup; echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
mkdir -p "${SHIMS}"
shim () {
{
echo '#!/bin/sh'
echo "$2"
} > "${SHIMS}/$1"
chmod +x "${SHIMS}/$1"
}
# a probe that behaves as if it were not installed, and whose complaint must
# never reach the user
shim_absent () {
shim "$1" "echo 'PROBE_NOISE: $1' >&2; exit 127"
}
REAL_OS="$(nvm_get_os)"
FAKE_OS=''
nvm_get_os () {
nvm_echo "${FAKE_OS}"
}
run () {
FAKE_OS="$1"
shift
NVM_MAKE_JOBS=''
nvm_get_make_jobs "$@" >"${OUT}" 2>"${ERR}"
}
assert_jobs () {
[ "_${NVM_MAKE_JOBS}" = "_$1" ] \
|| die "${2}: expected NVM_MAKE_JOBS ${1}, got '${NVM_MAKE_JOBS}'"
}
assert_stdout () {
ACTUAL="$(cat "${OUT}")"
[ "_${ACTUAL}" = "_$1" ] \
|| die "${2}: expected stdout '${1}', got '${ACTUAL}'"
}
# deliberately narrower than "stderr is empty": ksh93 has no `local`, so every
# nvm.sh function already sprays `local: not found` here (see #574)
assert_no_probe_noise () {
! nvm_grep -q 'PROBE_NOISE' "${ERR}" \
|| die "${1}: a failed probe leaked to stderr: '$(cat "${ERR}")'"
}
assert_not_nagged () {
! nvm_grep -q 'Please report an issue on GitHub' "${ERR}" \
|| die "${1}: unexpected report-an-issue message"
}
assert_nagged () {
nvm_grep -q 'Please report an issue on GitHub' "${ERR}" \
|| die "${1}: expected the report-an-issue message, got '$(cat "${ERR}")'"
}
export PATH="${SHIMS}:${ORIG_PATH}"
# an OS the `case` does not name still gets a real core count
shim getconf 'echo 4'
shim_absent nproc
run win
assert_jobs 3 'win'
assert_stdout 'Detected that you have 4 CPU core(s)
Running with 3 threads to speed up the build' 'win'
assert_not_nagged 'win'
assert_no_probe_noise 'win'
run ''
assert_jobs 3 'unknown OS'
assert_not_nagged 'unknown OS'
# Solaris and NetBSD spell the `getconf` variable without the leading underscore
shim getconf 'case "$1" in NPROCESSORS_ONLN) echo 4 ;; *) exit 1 ;; esac'
run win
assert_jobs 3 'unprefixed getconf name'
assert_not_nagged 'unprefixed getconf name'
# with no `getconf`, `nproc` answers
shim_absent getconf
shim nproc 'echo 4'
run win
assert_jobs 3 'nproc'
assert_not_nagged 'nproc'
assert_no_probe_noise 'nproc'
# Cygwin/MSYS/MinGW inherit `NUMBER_OF_PROCESSORS` from Windows
shim_absent nproc
NUMBER_OF_PROCESSORS=4
run win
assert_jobs 3 'NUMBER_OF_PROCESSORS'
assert_not_nagged 'NUMBER_OF_PROCESSORS'
assert_no_probe_noise 'NUMBER_OF_PROCESSORS'
# with nothing to probe, nvm still says so instead of guessing
unset NUMBER_OF_PROCESSORS
run win
assert_jobs 1 'no probes'
assert_nagged 'no probes'
# the named arms keep priority: darwin asks `sysctl`, not `getconf`
shim getconf 'echo 99'
shim sysctl 'echo 4'
run darwin
assert_jobs 3 'darwin uses sysctl'
assert_not_nagged 'darwin uses sysctl'
export PATH="${ORIG_PATH}"
# an explicit count short-circuits detection entirely
run '' 7
assert_jobs 7 'explicit jobs'
assert_stdout 'number of `make` jobs: 7' 'explicit jobs'
# on the real host, detected or not, the result is always usable
run "${REAL_OS}"
nvm_is_natural_num "${NVM_MAKE_JOBS}" \
|| die "real host: expected a natural number, got '${NVM_MAKE_JOBS}'"
cleanup
+149
View File
@@ -0,0 +1,149 @@
#!/bin/sh
TEST_PWD=$(pwd)
TEST_DIR="${TEST_PWD}/nvm_get_os_tmp"
: nvm.sh
\. ../../../nvm.sh
cleanup() {
rm -rf "${TEST_DIR}"
}
die() {
echo "$@"
cleanup
exit 1
}
[ ! -e "${TEST_DIR}" ] && mkdir "${TEST_DIR}"
OS_RELEASE="${TEST_DIR}/os-release"
MISSING_OS_RELEASE="${TEST_DIR}/nonexistent-os-release"
# a `uname` that reports that it ran (and fails), so that any test can prove
# whether `nvm_get_os` forked it
MOCK_BIN="${TEST_DIR}/bin"
mkdir -p "${MOCK_BIN}"
{
echo '#!/bin/sh'
echo 'echo "uname was called" >&2'
echo 'exit 1'
} > "${MOCK_BIN}/uname"
chmod +x "${MOCK_BIN}/uname"
# asserts that `nvm_get_os` maps the os-release file to $EXPECTED, without
# forking `uname`; the kernel is mocked as Linux, so Linux distro `ID`s pass on any host
KERNEL_LINUX="${TEST_DIR}/ostype-linux"
echo 'Linux' > "${KERNEL_LINUX}"
assert_os_release() {
local DESCRIPTION
DESCRIPTION="${1}"
local EXPECTED
EXPECTED="${2}"
local OUTPUT
NVM_OS_RELEASE="${OS_RELEASE}"
NVM_OS_KERNEL_OSTYPE="${KERNEL_LINUX}"
export NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE
OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_get_os 2>&1)"
unset NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE
case "${OUTPUT}" in
*'uname was called'*) die "for ${DESCRIPTION}, \`nvm_get_os\` forked \`uname\` despite \`${OS_RELEASE}\` being readable" ;;
esac
[ "${OUTPUT}" = "${EXPECTED}" ] || die "for ${DESCRIPTION}, expected '${EXPECTED}', got '${OUTPUT}'"
}
printf 'NAME=Ubuntu\nID=ubuntu\n' > "${OS_RELEASE}"
assert_os_release 'a distro-style os-release' 'linux'
printf 'NAME="Arch Linux"\nID=arch\n' > "${OS_RELEASE}"
assert_os_release 'an os-release with a quoted NAME' 'linux'
printf 'NAME=FreeBSD\nVERSION=14.0-RELEASE\nID=freebsd\n' > "${OS_RELEASE}"
assert_os_release 'the FreeBSD 13.2+ os-release' 'freebsd'
printf 'ID=freebsd' > "${OS_RELEASE}"
assert_os_release 'an os-release whose ID has no trailing newline' 'freebsd'
printf 'NAME=MSYS2\nID=msys2\nPRETTY_NAME="MSYS2"\nID_LIKE="cygwin arch"\n' > "${OS_RELEASE}"
assert_os_release 'the MSYS2 os-release' 'win'
printf 'NAME="Oracle Solaris"\nPRETTY_NAME="Oracle Solaris 11.4"\nCPE_NAME="cpe:/o:oracle:solaris:11:4"\nID=solaris\nVERSION=11.4\nVERSION_ID=11.4\nBUILD_ID=11.4.0.0.1.15.0\nHOME_URL="https://www.oracle.com/solaris/"\nSUPPORT_URL="https://support.oracle.com/"\n' > "${OS_RELEASE}"
assert_os_release 'the Oracle Solaris 11.4 os-release' 'sunos'
printf 'NAME="OmniOS"\nPRETTY_NAME="OmniOS Community Edition v11 r151048"\nCPE_NAME="cpe:/o:omniosce:omnios:11:151048:0"\nID=omnios\nVERSION=r151048\nVERSION_ID=r151048\nBUILD_ID=151048.0.2023.11.04\nHOME_URL="https://omnios.org/"\nSUPPORT_URL="https://omnios.org/"\nBUG_REPORT_URL="https://github.com/omniosorg/omnios-build/issues/new"\n' > "${OS_RELEASE}"
assert_os_release 'the OmniOS r151048 os-release' 'sunos'
printf 'ID=openindiana\nID_LIKE="illumos solaris"\n' > "${OS_RELEASE}"
assert_os_release 'an OpenIndiana os-release' 'sunos'
printf 'ID=smartos\n' > "${OS_RELEASE}"
assert_os_release 'a SmartOS os-release' 'sunos'
printf 'ID=illumos\n' > "${OS_RELEASE}"
assert_os_release 'an illumos os-release' 'sunos'
printf 'ID=ghostbsd\nID_LIKE=freebsd\n' > "${OS_RELEASE}"
assert_os_release 'a GhostBSD os-release' 'freebsd'
printf 'ID=freebsd # a comment\n' > "${OS_RELEASE}"
assert_os_release 'an ID followed by whitespace and a comment' 'freebsd'
# the file is read, not sourced: nothing in it runs
printf 'exit 3\nID=ubuntu\n' > "${OS_RELEASE}"
assert_os_release 'an os-release containing shell code' 'linux'
# a file without an `ID`, or no file at all, falls back to parsing `uname -a`
{
echo '#!/bin/sh'
echo 'echo "${NVM_MOCK_UNAME}"'
} > "${MOCK_BIN}/uname"
chmod +x "${MOCK_BIN}/uname"
assert_uname_os() {
local UNAME_OUTPUT
UNAME_OUTPUT="${1}"
local OS_RELEASE_FILE
OS_RELEASE_FILE="${2}"
local EXPECTED
EXPECTED="${3}"
local OUTPUT
NVM_OS_RELEASE="${OS_RELEASE_FILE}"
NVM_OS_KERNEL_OSTYPE="${MISSING_OS_RELEASE}"
export NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE
NVM_MOCK_UNAME="${UNAME_OUTPUT}"
export NVM_MOCK_UNAME
OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_get_os)"
unset NVM_OS_RELEASE NVM_OS_KERNEL_OSTYPE NVM_MOCK_UNAME
[ "${OUTPUT}" = "${EXPECTED}" ] || die "for uname -a '${UNAME_OUTPUT}', expected '${EXPECTED}', got '${OUTPUT}'"
}
printf 'NAME=OnlyAName\n' > "${OS_RELEASE}"
assert_uname_os 'Linux host 6.1.0 #1 SMP x86_64 GNU/Linux' "${OS_RELEASE}" 'linux'
assert_uname_os 'Darwin host 23.1.0 arm64' "${OS_RELEASE}" 'darwin'
assert_uname_os 'SunOS host 5.11' "${OS_RELEASE}" 'sunos'
assert_uname_os 'FreeBSD host 14.0-RELEASE' "${OS_RELEASE}" 'freebsd'
assert_uname_os 'OpenBSD host 7.4' "${OS_RELEASE}" 'openbsd'
assert_uname_os 'AIX host 3 7' "${OS_RELEASE}" 'aix'
assert_uname_os 'CYGWIN_NT-10.0 host' "${OS_RELEASE}" 'win'
assert_uname_os 'MINGW64_NT-10.0 host' "${OS_RELEASE}" 'win'
assert_uname_os 'MSYS_NT-10.0 host' "${OS_RELEASE}" 'win'
assert_uname_os 'Darwin host 23.1.0 arm64' "${MISSING_OS_RELEASE}" 'darwin'
# a pre-set `ID` in the environment must not be mistaken for the file's `ID`
ID=1000
export ID
assert_uname_os 'Darwin host 23.1.0 arm64' "${OS_RELEASE}" 'darwin'
unset ID
# DragonFly BSD has no `nvm` OS of its own: fall back to `uname -a` as before
printf 'NAME="DragonFly"\nID=dragonfly\n' > "${OS_RELEASE}"
assert_uname_os 'DragonFly host 6.4-RELEASE' "${OS_RELEASE}" ''
# an unlisted `ID` on a non-Linux kernel is not assumed to be Linux
printf 'NAME=HardenedBSD\nID=hardenedbsd\n' > "${OS_RELEASE}"
assert_uname_os 'FreeBSD host 14.0-STABLE' "${OS_RELEASE}" 'freebsd'
printf 'NAME=Helios\nID=helios\n' > "${OS_RELEASE}"
assert_uname_os 'SunOS host 5.11' "${OS_RELEASE}" 'sunos'
cleanup
+80
View File
@@ -0,0 +1,80 @@
#!/bin/sh
WORK="${PWD}/nvm-has-italics-work.$$"
FAKE_BIN="${WORK}/bin"
TPUT_LOG="${WORK}/tput.log"
cleanup() {
command rm -rf "${WORK}"
unset -f cleanup die nvm_has_colors
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
nvm_has_colors() { return 0; }
command mkdir -p "${FAKE_BIN}"
command cat > "${FAKE_BIN}/tput" <<EOF
#!/bin/sh
echo "\$*" > "${TPUT_LOG}"
command printf '\033[3m'
exit "\${FAKE_TPUT_STATUS-0}"
EOF
command chmod +x "${FAKE_BIN}/tput"
(
export PATH="${FAKE_BIN}:${PATH}" TERM=xterm-256color
nvm_has_italics
) || die 'nvm_has_italics should be true when terminfo has the sitm capability'
[ "$(command cat "${TPUT_LOG}")" = '-T xterm-256color sitm' ] \
|| die "nvm_has_italics should query sitm for the current TERM; got >$(command cat "${TPUT_LOG}")<"
OUTPUT="$(
export PATH="${FAKE_BIN}:${PATH}" TERM=xterm-256color
nvm_has_italics
)"
[ -z "${OUTPUT}" ] \
|| die "nvm_has_italics should not print the escape sequence; got >${OUTPUT}<"
(
export PATH="${FAKE_BIN}:${PATH}" TERM=screen FAKE_TPUT_STATUS=1
! nvm_has_italics
) || die 'nvm_has_italics should be false when terminfo lacks the sitm capability'
(
export PATH="${FAKE_BIN}:${PATH}" TERM=not-a-terminal FAKE_TPUT_STATUS=3
! nvm_has_italics
) || die 'nvm_has_italics should be false when the terminal is unknown'
(
export PATH="${FAKE_BIN}:${PATH}"
unset TERM
nvm_has_italics
) || die 'nvm_has_italics should query vt100 when TERM is unset'
[ "$(command cat "${TPUT_LOG}")" = '-T vt100 sitm' ] \
|| die "nvm_has_italics should fall back to vt100 when TERM is unset; got >$(command cat "${TPUT_LOG}")<"
(
PATH="${WORK}"
! nvm_has_italics
) || die 'nvm_has_italics should be false when tput is unavailable'
command rm -f "${TPUT_LOG}"
(
export PATH="${FAKE_BIN}:${PATH}" TERM=xterm-256color
nvm_has_colors() { return 1; }
! nvm_has_italics
) || die 'nvm_has_italics should be false when colors are disabled'
[ ! -f "${TPUT_LOG}" ] \
|| die 'nvm_has_italics should not query terminfo when colors are disabled'
if nvm_has tput; then
(
export TERM=dumb
! nvm_has_italics
) || die 'nvm_has_italics should be false for the dumb terminal'
fi
cleanup
+27
View File
@@ -0,0 +1,27 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
# also covers #3247, where `command hash -r` found a `hash` binary, not the builtin
OUTPUT="$(nvm_hash_reset 2>&1)"
RC=$?
[ ${RC} -eq 0 ] || die "nvm_hash_reset returned ${RC}: ${OUTPUT}"
[ -z "${OUTPUT}" ] || die "nvm_hash_reset was not silent: ${OUTPUT}"
# bash is the only supported shell that can turn hashing off
if [ -n "${BASH_VERSION-}" ]; then
set +h
OUTPUT="$(nvm_hash_reset 2>&1)"
RC=$?
set -h
[ ${RC} -eq 0 ] || die "with hashing disabled, nvm_hash_reset returned ${RC}: ${OUTPUT}"
[ -z "${OUTPUT}" ] || die "with hashing disabled, nvm_hash_reset was not silent: ${OUTPUT}"
ls >/dev/null 2>&1
hash -t ls >/dev/null 2>&1 || die 'expected `ls` to be hashed'
nvm_hash_reset || die 'with hashing enabled, nvm_hash_reset failed'
! hash -t ls >/dev/null 2>&1 || die 'nvm_hash_reset did not clear the hash table'
fi
@@ -0,0 +1,30 @@
#!/bin/sh
WORK="${PWD}/nvm-inherited-tmpdir-work.$$"
cleanup() {
command rm -rf "${WORK}"
unset -f cleanup die nvm_download_artifact
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
nvm_download_artifact() { return 1; }
make_canary() {
command rm -rf "${WORK}/tmp"
command mkdir -p "${WORK}/tmp"
echo canary > "${WORK}/tmp/canary"
}
make_canary
TMPDIR="${WORK}/tmp" nvm_install_binary node std 8.0.0 0 < /dev/null > /dev/null 2>&1
[ -f "${WORK}/tmp/canary" ] || die 'nvm_install_binary removed the TMPDIR it inherited after a failed download'
make_canary
TMPDIR="${WORK}/tmp" nvm_install_source node std 8.0.0 < /dev/null > /dev/null 2>&1
[ -f "${WORK}/tmp/canary" ] || die 'nvm_install_source removed the TMPDIR it inherited after a failed download'
cleanup
@@ -24,10 +24,13 @@ fi
cleanup
SLUG="$(nvm_get_download_slug node binary v0.12.18)"
CHECKSUM_LINE="$(nvm_compute_checksum ../../../nvm.sh 2>&1 >/dev/null)"
OUTPUT="$(TERM=dumb 2>&1 nvm install --no-progress v0.12.18)"
EXPECTED_OUTPUT="Downloading and installing node v0.12.18...
Downloading https://nodejs.org/dist/v0.12.18/node-v0.12.18-linux-x64.tar.xz...
Computing checksum with sha256sum
Downloading https://nodejs.org/dist/v0.12.18/${SLUG}.tar.xz...
${CHECKSUM_LINE}
Checksums matched!
Now using node v0.12.18 (npm v2.15.11)
Creating default alias: default -> v0.12.18 *"
@@ -40,9 +43,9 @@ cleanup
OUTPUT="$(TERM=dumb 2>&1 nvm install v0.12.18)"
EXPECTED_OUTPUT="Downloading and installing node v0.12.18...
Downloading https://nodejs.org/dist/v0.12.18/node-v0.12.18-linux-x64.tar.xz...
Downloading https://nodejs.org/dist/v0.12.18/${SLUG}.tar.xz...
######################################################################### 100.0%
Computing checksum with sha256sum
${CHECKSUM_LINE}
Checksums matched!
Now using node v0.12.18 (npm v2.15.11)
Creating default alias: default -> v0.12.18 *"
+58
View File
@@ -0,0 +1,58 @@
#!/bin/sh
cleanup () {
rm -rf "$NVM_DIR"
unset -f die cleanup
unset NVM_DIR NODE_PATH VERSION
}
die () { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
set -ex
NVM_DIR=$(mktemp -d)
NODE_PATH="$NVM_DIR/versions/node"
mkdir -p "$NODE_PATH"
if [ -z "$NODE_PATH" ]; then
die 'Unable to create temporary folder'
fi
# nvm_is_installed_exact_version is available
type nvm_is_installed_exact_version > /dev/null 2>&1 || die 'nvm_is_installed_exact_version is not available'
# nvm_is_installed_exact_version with no parameter fails
! nvm_is_installed_exact_version || die 'nvm_is_installed_exact_version without parameter should fail'
# an exact version that is not installed fails
! nvm_is_installed_exact_version 'v12.0.0' || die 'v12.0.0 is not installed and should fail'
# an exact version whose node binary is not executable fails
mkdir -p "$NODE_PATH/v12.0.0/bin"
touch "$NODE_PATH/v12.0.0/bin/node"
! nvm_is_installed_exact_version 'v12.0.0' || die 'v12.0.0 with a non-executable node should fail'
# an exact, installed version succeeds
chmod +x "$NODE_PATH/v12.0.0/bin/node"
nvm_is_installed_exact_version 'v12.0.0' || die 'v12.0.0 is installed and should succeed'
# something shaped almost like vX.Y.Z fails, even when a directory by that name is installed
for VERSION in 'v12.0.0.0' 'v12.0.0.' 'v12..0' 'v.12.0' 'v12.0'; do
mkdir -p "$NODE_PATH/$VERSION/bin"
touch "$NODE_PATH/$VERSION/bin/node"
chmod +x "$NODE_PATH/$VERSION/bin/node"
! nvm_is_installed_exact_version "$VERSION" || die "$VERSION is not an exact version and should fail, even when installed"
done
# anything that is not an exact vX.Y.Z fails, even if it would resolve to an installed version
for VERSION in '12.0.0' '12' 'v12' 'v12.0' 'v12.0.0-rc.1' 'node' 'stable' 'lts/*' 'iojs-v1.0.0' 'system' 'default'; do
! nvm_is_installed_exact_version "$VERSION" || die "$VERSION is not an exact version and should fail"
done
# an alias with the exact same name takes precedence, so the fast path must not apply
mkdir -p "$(nvm_alias_path)"
echo 'v12.0.0' > "$(nvm_alias_path)/v12.0.0"
! nvm_is_installed_exact_version 'v12.0.0' || die 'an alias named v12.0.0 should take precedence'
cleanup
+48
View File
@@ -12,3 +12,51 @@ nvm_is_valid_version iojs || die "nvm_is_valid_version iojs did not return 0"
nvm_is_valid_version node || die "nvm_is_valid_version node did not return 0"
nvm_is_valid_version stable || die "nvm_is_valid_version stable did not return 0"
nvm_is_valid_version unstable || die "nvm_is_valid_version unstable did not return 0"
nvm_is_valid_version 123.js && die "nvm_is_valid_version 123.js did not return 1"
nvm_is_valid_version v123.js && die "nvm_is_valid_version v123.js did not return 1"
nvm_is_valid_version v1.js && die "nvm_is_valid_version v1.js did not return 1"
nvm_is_valid_version v1.23.js && die "nvm_is_valid_version v1.23.js did not return 1"
nvm_is_valid_version 1.2.3.js && die "nvm_is_valid_version 1.2.3.js did not return 1"
nvm_is_valid_version 1.2.3.4.5.6.js && die "nvm_is_valid_version 1.2.3.4.5.6.js did not return 1"
nvm_is_valid_version 1.2.3.4 && die "nvm_is_valid_version 1.2.3.4 did not return 1"
nvm_is_valid_version 1..2 && die "nvm_is_valid_version 1..2 did not return 1"
nvm_is_valid_version 1.2.3-foo.js && die "nvm_is_valid_version 1.2.3-foo.js did not return 1"
nvm_is_valid_version 2.0.0-migration.js && die "nvm_is_valid_version 2.0.0-migration.js did not return 1"
nvm_is_valid_version 1.2-3.4-5 && die "nvm_is_valid_version 1.2-3.4-5 did not return 1"
nvm_is_valid_version 1.2.3- && die "nvm_is_valid_version 1.2.3- did not return 1"
nvm_is_valid_version 1.2.3-rc..1 && die "nvm_is_valid_version 1.2.3-rc..1 did not return 1"
nvm_is_valid_version '1.js
2' && die "nvm_is_valid_version with an embedded newline did not return 1"
nvm_is_valid_version 1 || die "nvm_is_valid_version 1 did not return 0"
nvm_is_valid_version v1 || die "nvm_is_valid_version v1 did not return 0"
nvm_is_valid_version 1.2 || die "nvm_is_valid_version 1.2 did not return 0"
nvm_is_valid_version v18.20.0 || die "nvm_is_valid_version v18.20.0 did not return 0"
nvm_is_valid_version 20. || die "nvm_is_valid_version 20. did not return 0"
nvm_is_valid_version v18.20. || die "nvm_is_valid_version v18.20. did not return 0"
nvm_is_valid_version iojs-v1.0.0 || die "nvm_is_valid_version iojs-v1.0.0 did not return 0"
nvm_is_valid_version v9.4.0-rc.1 || die "nvm_is_valid_version v9.4.0-rc.1 did not return 0"
nvm_is_valid_version v9.9.1-nightly201803256591d9f761 || die "nvm_is_valid_version v9.9.1-nightly201803256591d9f761 did not return 0"
nvm_is_valid_version v9.0.0-v8-canary201710301f8f3dcf36 || die "nvm_is_valid_version v9.0.0-v8-canary201710301f8f3dcf36 did not return 0"
nvm_is_valid_version v8.16.2-test201910293843c56739f || die "nvm_is_valid_version v8.16.2-test201910293843c56739f did not return 0"
nvm_is_valid_version iojs-v3.2.1-nightly201508291a531b4e44 || die "nvm_is_valid_version iojs-v3.2.1-nightly201508291a531b4e44 did not return 0"
# `nvm_is_valid_version` must not fork a command for a plain version: mock
# `awk`, which the version comparisons used, and fail if it runs. (Prereleases
# still reach the comparison, which is why this checks a release version.)
TEST_DIR="$(pwd)/nvm_is_valid_version_tmp"
[ ! -e "${TEST_DIR}" ] && mkdir "${TEST_DIR}"
MOCK_BIN="${TEST_DIR}/bin"
mkdir -p "${MOCK_BIN}"
{
echo '#!/bin/sh'
echo 'echo "awk was called" >&2'
echo 'exit 1'
} > "${MOCK_BIN}/awk"
chmod +x "${MOCK_BIN}/awk"
PATH="${MOCK_BIN}:${PATH}" nvm_is_valid_version v18.20.0 \
|| die 'nvm_is_valid_version v18.20.0 forked a command'
rm -rf "${TEST_DIR}"
@@ -45,6 +45,47 @@ type nvm_is_version_installed > /dev/null 2>&1 || die 'nvm_is_version_installed
check_version '12.0.0' 'node'
# the pre-0.12 layout is still found via the fallback
OLD_VERSION='0.11.15'
mkdir -p "$NVM_DIR/$OLD_VERSION/bin"
touch "$NVM_DIR/$OLD_VERSION/bin/node"
chmod +x "$NVM_DIR/$OLD_VERSION/bin/node"
nvm_is_version_installed "$OLD_VERSION" || die "nvm_is_version_installed $OLD_VERSION should work with the pre-0.12 layout"
# a pre-0.12 version does not count as installed from the modern layout
for STRAY_VERSION in '0.10.48' 'v0.10.48'; do
mkdir -p "$NODE_PATH/$STRAY_VERSION/bin"
touch "$NODE_PATH/$STRAY_VERSION/bin/node"
chmod +x "$NODE_PATH/$STRAY_VERSION/bin/node"
! nvm_is_version_installed "$STRAY_VERSION" || die "nvm_is_version_installed $STRAY_VERSION should not find a pre-0.12 version in the modern layout"
done
# io.js versions live in a separate tree and are still found via the fallback
IOJS_VERSION='v2.0.0'
mkdir -p "$NVM_DIR/versions/io.js/$IOJS_VERSION/bin"
touch "$NVM_DIR/versions/io.js/$IOJS_VERSION/bin/node"
chmod +x "$NVM_DIR/versions/io.js/$IOJS_VERSION/bin/node"
nvm_is_version_installed "iojs-$IOJS_VERSION" || die "nvm_is_version_installed iojs-$IOJS_VERSION should work via the fallback"
# the modern layout is found without shelling out to detect the OS
FAST_VERSION='14.0.0'
! nvm_is_version_installed "$FAST_VERSION" || die "nvm_is_version_installed $FAST_VERSION should fail before it is installed"
nvm_get_os() {
die 'nvm_is_version_installed must not call nvm_get_os when the modern-layout binary exists'
}
mkdir -p "$NODE_PATH/$FAST_VERSION/bin"
touch "$NODE_PATH/$FAST_VERSION/bin/node"
chmod +x "$NODE_PATH/$FAST_VERSION/bin/node"
nvm_is_version_installed "$FAST_VERSION" || die "nvm_is_version_installed $FAST_VERSION should succeed via the fast path"
# 0.12.x is the first version in the modern layout
for FAST_VERSION in '0.12.18' 'v0.12.18'; do
mkdir -p "$NODE_PATH/$FAST_VERSION/bin"
touch "$NODE_PATH/$FAST_VERSION/bin/node"
chmod +x "$NODE_PATH/$FAST_VERSION/bin/node"
nvm_is_version_installed "$FAST_VERSION" || die "nvm_is_version_installed $FAST_VERSION should succeed via the fast path"
done
unset -f nvm_get_os
# Checking for Windows
nvm_get_os() {
echo "win"
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
HOME='/home/user'
for DIR in '/tmp/a&b/.nvm' '/tmp/a#b/.nvm' '/tmp/a[1]/.nvm' '/tmp/a*b/.nvm' '/tmp/a+(b)/.nvm' '/tmp/a.b/.nvm' '/tmp/a\b/.nvm' '/tmp/a$b/.nvm' '/tmp/a|b/.nvm'; do
NVM_DIR="${DIR}"
OUTPUT="$(nvm_sanitize_path "${NVM_DIR}/versions/node/v4.5.0")"
EXPECTED='${NVM_DIR}/versions/node/v4.5.0'
[ "${OUTPUT}" = "${EXPECTED}" ] || die "NVM_DIR=${DIR}: expected >${EXPECTED}<, got >${OUTPUT}<"
OUTPUT="$(nvm_sanitize_path "${NVM_DIR}")"
[ "${OUTPUT}" = "${NVM_DIR}" ] || die "NVM_DIR=${DIR}: path equal to NVM_DIR should be left alone, got >${OUTPUT}<"
done
# `.` in NVM_DIR must match itself only, not any character
NVM_DIR='/tmp/a.b/.nvm'
OUTPUT="$(nvm_sanitize_path '/tmp/aXb/.nvm/foo')"
[ "${OUTPUT}" = '/tmp/aXb/.nvm/foo' ] || die "unrelated path was rewritten: >${OUTPUT}<"
# HOME is replaced too
NVM_DIR='/tmp/a#b/.nvm'
OUTPUT="$(nvm_sanitize_path "${HOME}/.npmrc")"
[ "${OUTPUT}" = '${HOME}/.npmrc' ] || die "expected >\${HOME}/.npmrc<, got >${OUTPUT}<"
@@ -1,6 +1,13 @@
#!/bin/sh
cleanup () {
rm tmp-alias
if [ "${CASE_SENSITIVE-}" = '1' ]; then
rm tmp/TREE/node
rmdir tmp/TREE
fi
rm tmp/tree/node
rmdir tmp/tree
rm tmp/node
rmdir tmp
rm tmp2/node
@@ -15,6 +22,15 @@ mkdir -p tmp
touch tmp/node
mkdir -p tmp2
touch tmp2/node
mkdir -p tmp/tree
touch tmp/tree/node
ln -s tmp tmp-alias
CASE_SENSITIVE=0
if [ ! -d tmp/TREE ]; then
CASE_SENSITIVE=1
mkdir tmp/TREE
touch tmp/TREE/node
fi
[ "$(nvm_tree_contains_path 2>&1)" = "both the tree and the node path are required" ] || die 'incorrect error message with no args'
[ "$(nvm_tree_contains_path > /dev/null 2>&1 ; echo $?)" = "2" ] || die 'incorrect error code with no args'
@@ -29,4 +45,25 @@ nvm_tree_contains_path tmp2 tmp2/node || die '"tmp2" should contain "tmp2/node"'
nvm_tree_contains_path tmp2 tmp/node && die '"tmp2" should not contain "tmp/node"'
nvm_tree_contains_path tmp/ tmp/node || die '"tmp/" should contain "tmp/node"'
nvm_tree_contains_path tmp// tmp/node || die '"tmp//" should contain "tmp/node"'
nvm_tree_contains_path / /tmp/node || die '"/" should contain "/tmp/node"'
nvm_tree_contains_path "tmp[glob]" "tmp[glob]/node" || die '"tmp[glob]" should contain "tmp[glob]/node"'
nvm_tree_contains_path "tmp" "tmp[glob]/node" && die '"tmp" should not contain "tmp[glob]/node"'
if [ "${CASE_SENSITIVE}" = '1' ]; then
nvm_tree_contains_path tmp/tree tmp/TREE/node && die 'case-sensitive directories should stay distinct'
nvm_tree_contains_path tmp/TREE tmp/tree/node && die 'case-sensitive directories should stay distinct'
else
nvm_tree_contains_path tmp/tree tmp/TREE/node || die 'case-insensitive directories should match'
nvm_tree_contains_path tmp/TREE tmp/tree/node || die 'case-insensitive directories should match'
fi
nvm_tree_contains_path tmp-alias tmp/node || die 'a symlink to the tree should contain its node'
nvm_tree_contains_path tmp tmp-alias/node || die 'the tree should contain a node reached through a symlink'
nvm_tree_contains_path tmp-alias tmp2/node && die 'a symlink should not contain a sibling tree'
nvm_tree_contains_path nonexistent NONEXISTENT/node && die 'missing directories should not be case folded'
cleanup
+28 -1
View File
@@ -2,7 +2,7 @@
die () { echo "$@" ; cleanup ; exit 1; }
cleanup () {
unset -f nvm_ls_current nvm_ls
unset -f nvm_ls_current nvm_ls nvm_is_version_installed
}
: nvm.sh
@@ -48,3 +48,30 @@ try nvm_version foo
EXPECTED_OUTPUT="N/A"
[ "_$CAPTURED_STDOUT" = "_$EXPECTED_OUTPUT" ] || die '"nvm_version" did not return N/A when nvm_ls returns nothing'
[ "_$CAPTURED_EXIT_CODE" = "_3" ] || die '"nvm_version" returning N/A did not exit code with code 3'
# an exact installed version resolves without forking "nvm_ls"
nvm_is_version_installed() { return 0; }
nvm_ls() { die '"nvm_version" must not call "nvm_ls" for an exact installed version'; }
try nvm_version v1.2.3
EXPECTED_OUTPUT="v1.2.3"
[ "_$CAPTURED_STDOUT" = "_$EXPECTED_OUTPUT" ] || die '"nvm_version v1.2.3" did not return the version itself; got '"$CAPTURED_STDOUT"
[ "_$CAPTURED_EXIT_CODE" = "_0" ] || die '"nvm_version v1.2.3" did not exit 0; got '"$CAPTURED_EXIT_CODE"
# an exact version that is not installed still falls back to "nvm_ls"
nvm_is_version_installed() { return 1; }
nvm_ls() { echo "pattern: $1"; }
try nvm_version v1.2.3
EXPECTED_OUTPUT="pattern: v1.2.3"
[ "_$CAPTURED_STDOUT" = "_$EXPECTED_OUTPUT" ] || die '"nvm_version v1.2.3" did not fall back to "nvm_ls"; got '"$CAPTURED_STDOUT"
[ "_$CAPTURED_EXIT_CODE" = "_0" ] || die '"nvm_version v1.2.3" did not exit 0; got '"$CAPTURED_EXIT_CODE"
# only exact, fully-qualified versions take the fast path
nvm_is_version_installed() { die '"nvm_version" must not call "nvm_is_version_installed" for non-exact versions'; }
nvm_ls() { echo "pattern: $1"; }
for PATTERN in v1.2 v1 1.2.3 v1.2.3-rc.1 v1.2.3.4 v1.2.3.; do
try nvm_version "$PATTERN"
EXPECTED_OUTPUT="pattern: $PATTERN"
[ "_$CAPTURED_STDOUT" = "_$EXPECTED_OUTPUT" ] || die "nvm_version $PATTERN did not fall back to nvm_ls; got $CAPTURED_STDOUT"
[ "_$CAPTURED_EXIT_CODE" = "_0" ] || die "nvm_version $PATTERN did not exit 0; got $CAPTURED_EXIT_CODE"
done
unset -f nvm_is_version_installed
+39
View File
@@ -6,6 +6,8 @@ die () { echo "$@" ; exit 1; }
\. ../../../nvm.sh
nvm_version_greater 0.10.0 0.2.12 || die '"nvm_version_greater 0.10.0 0.2.12" did not return true'
nvm_version_greater 0.20.12 0.10.0 || die '"nvm_version_greater 0.20.12 0.10.0" did not return true'
nvm_version_greater v18.20.0 v18.19.9 || die '"nvm_version_greater v18.20.0 v18.19.9" did not return true'
if nvm_version_greater 0.10.0 0.20.12; then
die '"nvm_version_greater 0.10.0 0.20.12" returned true'
@@ -14,3 +16,40 @@ fi
if nvm_version_greater 0.10.0 0.10.0; then
die '"nvm_version_greater" returned false for the same two versions'
fi
if nvm_version_greater v18.20.0 v18.20.0; then
die '"nvm_version_greater v18.20.0 v18.20.0" returned true for the same two versions'
fi
if nvm_version_greater v18.19.9 v18.20.0; then
die '"nvm_version_greater v18.19.9 v18.20.0" returned true'
fi
# a partial version is not a plain `x.y.z`, so it keeps the awk comparison
nvm_version_greater 0.10 0.2.12 || die '"nvm_version_greater 0.10 0.2.12" did not return true'
# the comparison must not write anything to stdout (zsh's `typeset` prints a
# local variable when it is redeclared)
OUTPUT="$(nvm_version_greater 0.10.0 0.2.12 2>&1)"
[ -z "${OUTPUT}" ] || die "nvm_version_greater 0.10.0 0.2.12 wrote output: '${OUTPUT}'"
# `nvm_version_greater` must not fork a command for a plain `x.y.z` pair:
# mock `awk`, which the comparison used, and fail if it runs
TEST_DIR="$(pwd)/nvm_version_greater_tmp"
[ ! -e "${TEST_DIR}" ] && mkdir "${TEST_DIR}"
MOCK_BIN="${TEST_DIR}/bin"
mkdir -p "${MOCK_BIN}"
{
echo '#!/bin/sh'
echo 'echo "awk was called" >&2'
echo 'exit 1'
} > "${MOCK_BIN}/awk"
chmod +x "${MOCK_BIN}/awk"
PATH="${MOCK_BIN}:${PATH}" nvm_version_greater 0.10.0 0.2.12 \
|| die 'nvm_version_greater 0.10.0 0.2.12 forked a command'
PATH="${MOCK_BIN}:${PATH}" nvm_version_greater v18.20.0 v18.19.9 \
|| die 'nvm_version_greater v18.20.0 v18.19.9 forked a command'
rm -rf "${TEST_DIR}"
+28
View File
@@ -0,0 +1,28 @@
#!/bin/sh
die () { echo "$@" ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
nvm_version_greater_than_or_equal_to 0.10.0 0.2.12 || die '"nvm_version_greater_than_or_equal_to 0.10.0 0.2.12" did not return true'
nvm_version_greater_than_or_equal_to 0.10.0 0.10.0 || die '"nvm_version_greater_than_or_equal_to" did not return true for the same two versions'
nvm_version_greater_than_or_equal_to v0.10.0 0.10.0 || die '"nvm_version_greater_than_or_equal_to v0.10.0 0.10.0" did not return true'
if nvm_version_greater_than_or_equal_to 0.10.0 0.20.12; then
die '"nvm_version_greater_than_or_equal_to 0.10.0 0.20.12" returned true'
fi
if nvm_version_greater_than_or_equal_to 0.2.12 0.10.0; then
die '"nvm_version_greater_than_or_equal_to 0.2.12 0.10.0" returned true'
fi
if nvm_version_greater_than_or_equal_to 0.10.0 ''; then
die '"nvm_version_greater_than_or_equal_to" returned true with an empty argument'
fi
if nvm_version_greater_than_or_equal_to '' 0.10.0; then
die '"nvm_version_greater_than_or_equal_to" returned true with an empty first argument'
fi
@@ -0,0 +1,65 @@
#!/bin/sh
die () { echo "$@" ; cleanup ; exit 1; }
cleanup() {
unset -f install_nvm_from_git install_nvm_as_script nvm_detect_profile nvm_has
unset -f nvm_check_global_modules nvm_install_node
unset -f setup cleanup die assert_profile
unset NVM_ENV METHOD PROFILE
rm -rf "${TMPDIR_FOR_TEST-}" 2>/dev/null
}
setup() {
NVM_ENV=testing \. ../../install.sh
# Mock installation functions to do nothing
install_nvm_from_git() { :; }
install_nvm_as_script() { :; }
nvm_check_global_modules() { :; }
nvm_install_node() { :; }
# Mock nvm_has to return true for git
nvm_has() {
case "$1" in
git) return 0 ;;
xcode-select) return 1 ;;
*) return 1 ;;
esac
}
}
setup
TMPDIR_FOR_TEST="$(mktemp -d)"
TEST_PROFILE="${TMPDIR_FOR_TEST}/.bashrc"
EXPECTED_PROFILE="${TMPDIR_FOR_TEST}/expected"
COMPLETION_LINE='[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion'
# runs the installer against $TEST_PROFILE, and compares the whole file, byte for byte, with $EXPECTED_PROFILE.
# `nvm_do_install` unsets every `nvm_` function when it finishes, so each run sources the installer and mocks afresh.
assert_profile() {
setup
nvm_detect_profile() {
echo "${TEST_PROFILE}"
}
PROFILE='' METHOD='' NVM_DIR="$(cd ../.. && pwd)" nvm_do_install > /dev/null 2>&1
command cmp -s "${TEST_PROFILE}" "${EXPECTED_PROFILE}" || die "$1; got: >$(command cat "${TEST_PROFILE}")<"
}
#
# Test: when the profile already sources nvm.sh but does not end with a newline,
# the bash_completion line must be appended on its own line, and the profile must end with a newline
#
command printf '%s\n%s' '. "$HOME/.nvm/nvm.sh"' "alias ll='ls -l'" > "${TEST_PROFILE}"
command printf '%s\n%s\n%s\n' '. "$HOME/.nvm/nvm.sh"' "alias ll='ls -l'" "${COMPLETION_LINE}" > "${EXPECTED_PROFILE}"
assert_profile 'bash_completion line was not appended on its own line, ending with a newline'
#
# Test: when the profile already ends with a newline, no blank line is added before the bash_completion line
#
command printf '%s\n%s\n' '. "$HOME/.nvm/nvm.sh"' "alias ll='ls -l'" > "${TEST_PROFILE}"
command printf '%s\n%s\n%s\n' '. "$HOME/.nvm/nvm.sh"' "alias ll='ls -l'" "${COMPLETION_LINE}" > "${EXPECTED_PROFILE}"
assert_profile 'a profile ending with a newline got an extra blank line before the bash_completion line'
cleanup
+10
View File
@@ -20,6 +20,16 @@ nvm_make_alias() {
return 0
}
nvm_get_remote_aliases() {
# prevent local aliases from leaking into `nvm ls-remote` mocks
return 0
}
nvm_has_italics() {
# keep mocks independent of the local terminal's italics support
return 0
}
nvm_ls_remote > "$MOCKS_DIR/nvm_ls_remote.txt"
nvm_ls_remote_iojs > "$MOCKS_DIR/nvm_ls_remote_iojs.txt"
NVM_LTS=* nvm_ls_remote > "$MOCKS_DIR/nvm_ls_remote LTS.txt"