Files
nvm/nvm.sh
T
Wei-Lun Li 970ed9ea18 [Fix] nvm_die_on_prefix: check a nonexistent prefix on Windows
On Windows, `npm_config_prefix` is resolved with `cd` + `pwd` so it can be compared with `$NVM_DIR`.
When the directory does not exist yet, that resolution fails,
the value becomes empty, and the check is skipped.
Keep the value as given in that case, like on other systems.

Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Wei-Lun Li <b84330808@gmail.com>
2026-10-29 09:48:45 +09:00

6793 lines
229 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Node Version Manager
# Implemented as a POSIX-compliant function
# Should work on sh, dash, bash, ksh, zsh
# To use source this file from your bash profile
#
# Implemented by Tim Caswell <tim@creationix.com>
# with much bash help from Matthew Ranney
# "local" warning, quote expansion warning, sed warning, `local` warning
# shellcheck disable=SC2039,SC2016,SC2001,SC3043
{ # this ensures the entire script is downloaded #
nvm_is_zsh() {
[ -n "${ZSH_VERSION-}" ]
}
nvm_stdout_is_terminal() {
[ -t 1 ]
}
nvm_echo() {
# in zsh, `command printf` skips the builtin and runs `/usr/bin/printf`
if [ -n "${ZSH_VERSION-}" ]; then
# shellcheck disable=SC3044
builtin printf %s\\n "$*" 2>/dev/null
else
command printf %s\\n "$*" 2>/dev/null
fi
}
nvm_echo_with_colors() {
if [ -n "${ZSH_VERSION-}" ]; then
# shellcheck disable=SC3044
builtin printf %b\\n "$*" 2>/dev/null
else
command printf %b\\n "$*" 2>/dev/null
fi
}
nvm_cd() {
# `\cd` still runs a user-defined `cd` function; in zsh, `command cd` runs `/usr/bin/cd` instead of the builtin
if [ -n "${ZSH_VERSION-}" ]; then
# shellcheck disable=SC3044
builtin cd "$@"
else
command cd "$@"
fi
}
# a caller that closed stderr, rather than redirecting it to /dev/null, makes
# the `>&2` fail; zsh cannot report that, so it aborts the script, which only a
# subshell contains, and `|| return 0` keeps the status from the caller
nvm_err() {
(>&2 nvm_echo "$@") || return 0
}
nvm_err_with_colors() {
(>&2 nvm_echo_with_colors "$@") || return 0
}
nvm_grep() {
GREP_OPTIONS='' command grep "$@"
}
nvm_has() {
type "${1-}" >/dev/null 2>&1
}
# resolves like `command "${1}"` does: only executables on the PATH,
# ignoring shell functions and aliases
nvm_has_executable() {
(
# `|| true` so that shells with errexit-style options (eg, zsh's ERR_RETURN)
# do not abort the subshell when the name is not an alias or a function
unalias "${1-}" 2>/dev/null || true
unset -f "${1-}" 2>/dev/null || true
command -v "${1-}" >/dev/null 2>&1
)
}
nvm_has_non_aliased() {
nvm_has "${1-}" && ! nvm_is_alias "${1-}"
}
nvm_is_alias() {
# this is intentionally not "command alias" so it works in zsh.
\alias "${1-}" >/dev/null 2>&1
}
nvm_command_info() {
local COMMAND
local INFO
COMMAND="${1}"
if type "${COMMAND}" | nvm_grep -q hashed; then
INFO="$(type "${COMMAND}" | command sed -E 's/\(|\)//g' | command awk '{print $4}')"
elif type "${COMMAND}" | nvm_grep -q aliased; then
# shellcheck disable=SC2230
INFO="$(which "${COMMAND}") ($(type "${COMMAND}" | command awk '{ $1=$2=$3=$4="" ;print }' | command sed -e 's/^\ *//g' -Ee "s/\`|'//g"))"
elif type "${COMMAND}" | nvm_grep -q "^${COMMAND} is an alias for"; then
# shellcheck disable=SC2230
INFO="$(which "${COMMAND}") ($(type "${COMMAND}" | command awk '{ $1=$2=$3=$4=$5="" ;print }' | command sed 's/^\ *//g'))"
elif type "${COMMAND}" | nvm_grep -q "^${COMMAND} is /"; then
INFO="$(type "${COMMAND}" | command awk '{print $3}')"
else
INFO="$(type "${COMMAND}")"
fi
nvm_echo "${INFO}"
}
nvm_has_colors() {
local NVM_NUM_COLORS
if nvm_has tput; then
NVM_NUM_COLORS="$(command tput -T "${TERM:-vt100}" colors)"
fi
[ -t 1 ] && [ "${NVM_NUM_COLORS:--1}" -ge 8 ] && [ "${NVM_NO_COLORS-}" != '--no-colors' ]
}
# terminals without italics may render the italic escape as reverse video instead, so check terminfo's `sitm` capability
nvm_has_italics() {
nvm_has_colors && command tput -T "${TERM:-vt100}" sitm >/dev/null 2>&1
}
nvm_curl_libz_support() {
command curl -V 2>/dev/null | nvm_grep "^Features:" | nvm_grep -q "libz"
}
nvm_curl_use_compression() {
nvm_curl_libz_support && nvm_version_greater_than_or_equal_to "$(nvm_curl_version)" 7.21.0
}
nvm_get_latest() {
local NVM_LATEST_URL
local CURL_COMPRESSED_FLAG
if nvm_has_executable "curl"; then
if nvm_curl_use_compression; then
CURL_COMPRESSED_FLAG="--compressed"
fi
NVM_LATEST_URL="$(command curl -q ${CURL_COMPRESSED_FLAG:-} -w "%{url_effective}\\n" -L -s -S https://latest.nvm.sh -o /dev/null)"
elif nvm_has_executable "wget"; then
NVM_LATEST_URL="$(command wget -q https://latest.nvm.sh --server-response -O /dev/null 2>&1 | command awk '/^ Location: /{DEST=$2} END{ print DEST }')"
else
nvm_err 'nvm needs curl or wget to proceed.'
return 1
fi
if [ -z "${NVM_LATEST_URL}" ]; then
nvm_err "https://latest.nvm.sh did not redirect to the latest release on GitHub"
return 2
fi
nvm_echo "${NVM_LATEST_URL##*/}"
}
# Every argument is passed through as a literal argv element so that untrusted,
# mirror-supplied version strings in the URLs are never re-parsed by the shell
# (which would allow command substitution / OS command injection).
nvm_download() {
local sanitized_header
sanitized_header=''
if [ -n "${NVM_AUTH_HEADER:-}" ]; then
local NVM_DOWNLOAD_AUTH
NVM_DOWNLOAD_AUTH=''
local NVM_DOWNLOAD_ARG
for NVM_DOWNLOAD_ARG in "$@"; do
case "${NVM_DOWNLOAD_ARG}" in
http://* | https://*)
if nvm_auth_header_applies_to "${NVM_DOWNLOAD_ARG}"; then
NVM_DOWNLOAD_AUTH=1
else
NVM_DOWNLOAD_AUTH=''
break
fi
;;
esac
done
if [ -n "${NVM_DOWNLOAD_AUTH}" ]; then
sanitized_header="$(nvm_sanitize_auth_header "${NVM_AUTH_HEADER}")"
fi
fi
local NVM_DOWNLOADER
NVM_DOWNLOADER=''
if nvm_has_executable "curl"; then
NVM_DOWNLOADER='curl'
set -- --fail "$@"
if nvm_curl_use_compression; then
set -- --compressed "$@"
fi
# curl only skips reading `.curlrc` when `-q` is its very first argument
set -- -q "$@"
elif nvm_has_executable "wget"; then
NVM_DOWNLOADER='wget'
# Emulate curl with wget
local NVM_DOWNLOAD_WGET_COUNT
NVM_DOWNLOAD_WGET_COUNT=$#
local NVM_DOWNLOAD_WGET_SKIP
NVM_DOWNLOAD_WGET_SKIP=0
local NVM_DOWNLOAD_WGET_ARG
for NVM_DOWNLOAD_WGET_ARG in "$@"; do
if [ "${NVM_DOWNLOAD_WGET_SKIP}" = '1' ]; then
NVM_DOWNLOAD_WGET_SKIP=0
continue
fi
case "${NVM_DOWNLOAD_WGET_ARG}" in
'--progress-bar') set -- "$@" '--progress=bar' ;;
'--compressed') : ;;
'--fail') : ;;
'-L') : ;;
'-I') set -- "$@" '--server-response' ;;
'-s') set -- "$@" '-q' ;;
'-sS') set -- "$@" '-nv' ;;
'-o') set -- "$@" '-O' ;;
'-C') NVM_DOWNLOAD_WGET_SKIP=1; set -- "$@" '-c' ;;
*) set -- "$@" "${NVM_DOWNLOAD_WGET_ARG}" ;;
esac
done
shift "${NVM_DOWNLOAD_WGET_COUNT}"
fi
if [ -z "${NVM_DOWNLOADER}" ]; then
return 0
fi
if [ -n "${sanitized_header}" ]; then
if [ "${NVM_DOWNLOADER}" = 'wget' ] && nvm_wget_is_gnu; then
nvm_wget_same_origin "${sanitized_header}" "$@"
return $?
fi
set -- "$@" --header "Authorization: ${sanitized_header}"
fi
command "${NVM_DOWNLOADER}" "$@"
}
# BusyBox wget rejects `--version`; GNU Wget2 reports itself as "GNU Wget2"
nvm_wget_is_gnu() {
command wget --version 2>/dev/null | nvm_grep -q '^GNU Wget '
}
# args: url; prints its `scheme://authority`
nvm_url_origin() {
local NVM_URL_REST
NVM_URL_REST="${1#*://}"
nvm_echo "${1%%://*}://${NVM_URL_REST%%/*}"
}
# args: sanitized Authorization header value, wget arguments
# `curl -L` (7.58.0 and later) does not send a custom Authorization header to a
# redirect target on another host, but wget sends `--header` along to every
# one. So GNU Wget is stopped at every redirect, which is then followed only if
# it stays on the same origin (scheme, host, and port). Other wgets, like
# BusyBox's, cannot be stopped from following redirects.
nvm_wget_same_origin() {
local NVM_WGET_HEADER
NVM_WGET_HEADER="Authorization: ${1-}"
shift
local NVM_WGET_URL
NVM_WGET_URL=''
local NVM_WGET_ARG
for NVM_WGET_ARG in "$@"; do
case "${NVM_WGET_ARG}" in
http://* | https://*) NVM_WGET_URL="${NVM_WGET_ARG}" ;;
esac
done
local NVM_WGET_REQUESTED_URL
NVM_WGET_REQUESTED_URL="${NVM_WGET_URL}"
local NVM_WGET_EXIT_CODE
local NVM_WGET_LOCATION
local NVM_WGET_ARG_COUNT
local NVM_WGET_REDIRECTS
NVM_WGET_REDIRECTS=0
while :; do
command wget --max-redirect=0 "$@" --header "${NVM_WGET_HEADER}"
NVM_WGET_EXIT_CODE=$?
# wget exits with 8 for an HTTP error status, including a redirect it did not follow
if [ "${NVM_WGET_EXIT_CODE}" != 8 ] || [ -z "${NVM_WGET_URL}" ]; then
return "${NVM_WGET_EXIT_CODE}"
fi
NVM_WGET_LOCATION="$(command wget --max-redirect=0 -q -S -O /dev/null "${NVM_WGET_URL}" --header "${NVM_WGET_HEADER}" 2>&1 \
| command awk 'tolower($1) == "location:" { print $2; exit }' | command tr -d '\r')"
case "${NVM_WGET_LOCATION}" in
'') return "${NVM_WGET_EXIT_CODE}" ;;
http://* | https://*) ;;
//*) NVM_WGET_LOCATION="${NVM_WGET_URL%%//*}${NVM_WGET_LOCATION}" ;;
/*) NVM_WGET_LOCATION="$(nvm_url_origin "${NVM_WGET_URL}")${NVM_WGET_LOCATION}" ;;
*) NVM_WGET_LOCATION="${NVM_WGET_URL%/*}/${NVM_WGET_LOCATION}" ;;
esac
if [ "$(nvm_url_origin "${NVM_WGET_LOCATION}")" != "$(nvm_url_origin "${NVM_WGET_URL}")" ]; then
nvm_err "${NVM_WGET_REQUESTED_URL} redirects to another origin; wget would send \$NVM_AUTH_HEADER there too, so it is not followed. Install curl to download from this mirror."
return "${NVM_WGET_EXIT_CODE}"
fi
NVM_WGET_REDIRECTS=$((NVM_WGET_REDIRECTS + 1))
if [ "${NVM_WGET_REDIRECTS}" -gt 20 ]; then
nvm_err "${NVM_WGET_REQUESTED_URL}: too many redirects"
return "${NVM_WGET_EXIT_CODE}"
fi
NVM_WGET_ARG_COUNT=$#
for NVM_WGET_ARG in "$@"; do
if [ "${NVM_WGET_ARG}" = "${NVM_WGET_URL}" ]; then
set -- "$@" "${NVM_WGET_LOCATION}"
else
set -- "$@" "${NVM_WGET_ARG}"
fi
done
shift "${NVM_WGET_ARG_COUNT}"
NVM_WGET_URL="${NVM_WGET_LOCATION}"
done
}
# args: url
# Whether `$NVM_AUTH_HEADER` applies to a request for the given URL: only URLs
# under a mirror qualify, never any other host (eg, npmjs.org). When exactly one
# of `$NVM_NODEJS_ORG_MIRROR` and `$NVM_IOJS_ORG_MIRROR` is set, the header is
# that mirror's credential, so the other flavor's default host does not get it.
nvm_auth_header_applies_to() {
local NVM_AUTH_FLAVOR
local NVM_AUTH_MIRROR
for NVM_AUTH_FLAVOR in node iojs; do
case "${NVM_AUTH_FLAVOR}" in
node)
if [ -z "${NVM_NODEJS_ORG_MIRROR-}" ] && [ -n "${NVM_IOJS_ORG_MIRROR-}" ]; then
continue
fi
;;
iojs)
if [ -z "${NVM_IOJS_ORG_MIRROR-}" ] && [ -n "${NVM_NODEJS_ORG_MIRROR-}" ]; then
continue
fi
;;
esac
# an invalid mirror matches nothing; the download itself reports it
NVM_AUTH_MIRROR="$(nvm_get_mirror "${NVM_AUTH_FLAVOR}" std 2>/dev/null)" || continue
case "${1-}" in
"${NVM_AUTH_MIRROR}"/*) return 0 ;;
esac
done
return 1
}
nvm_sanitize_auth_header() {
# Remove potentially dangerous characters; allow the full base64 (A-Za-z0-9+/=)
# and base64url (A-Za-z0-9-_=) charsets, plus the space, colon, dot, and
# underscore the previous allowlist already permitted, so that values like
# `Basic <base64>` and `Bearer <token>` survive intact.
# '~' is also allowed, completing RFC 7235 `token68` (and thus RFC 6750
# `b64token`), so opaque Bearer tokens containing it are not corrupted.
# Note: '-' must be at the end of the set to be treated as a literal.
# `tr`, not `sed`: sed is line-based and would keep newlines, eg from a
# `base64` credential that was wrapped at 76 columns.
nvm_echo "$1" | command tr -cd 'a-zA-Z0-9 :_.+/=~-'
}
nvm_has_system_node() {
[ "$(nvm deactivate >/dev/null 2>&1 && command -v node)" != '' ]
}
nvm_has_system_iojs() {
[ "$(nvm deactivate >/dev/null 2>&1 && command -v iojs)" != '' ]
}
nvm_is_installed_exact_version() {
case "${1-}" in
v*) ;;
*) return 1 ;;
esac
local NVM_EXACT_VERSION
NVM_EXACT_VERSION="${1#v}"
case "${NVM_EXACT_VERSION}" in
*-*)
case "${NVM_EXACT_VERSION#*-}" in
'' | .* | *. | *..* | *[!0-9A-Za-z.-]*) return 1 ;;
esac
NVM_EXACT_VERSION="${NVM_EXACT_VERSION%%-*}"
;;
esac
case "${NVM_EXACT_VERSION}" in
*[!0-9.]* | .* | *. | *..* | *.*.*.*) return 1 ;;
*.*.*) ;;
*) return 1 ;;
esac
# an alias with this exact name takes precedence, as it does in `nvm_version`
if [ -e "$(nvm_alias_path)/${1}" ]; then
return 1
fi
nvm_is_version_installed "${1}" && nvm_is_version_selected "${1}"
}
nvm_is_version_installed() {
if [ -z "${1-}" ]; then
return 1
fi
# Fast path: versions in the modern layout live at a directly-computable
# path. Checking it first avoids forking `nvm_version_path` (and the `awk`
# version comparison inside it) and `nvm_get_os` on shell startup. Versions
# below `v0.12` are skipped, since they must not count from the modern
# layout; those, io.js, and Windows binaries fall through to the full lookup
# below, which also rejects path traversal.
case "/${1}/" in
*/../* | /v0.[0-9].* | /v0.1[01].* | /0.[0-9].* | /0.1[01].*) ;;
*)
if [ -x "${NVM_DIR}/versions/node/${1}/bin/node" ]; then
return 0
fi
;;
esac
local NVM_NODE_BINARY
NVM_NODE_BINARY='node'
if [ "_$(nvm_get_os)" = '_win' ]; then
NVM_NODE_BINARY='node.exe'
fi
local VERSION_PATH
VERSION_PATH="$(nvm_version_path "$1" 2>/dev/null)" || return 1
if [ -x "${VERSION_PATH}/bin/${NVM_NODE_BINARY}" ]; then
return 0
fi
return 1
}
# Sanity-check an installed version's layout: a non-empty, executable bin/node
# and, if present, an npm entry that resolves. nvm_is_version_installed only
# tests the bin/node exec bit, which a zero-byte binary and a dangling npm
# symlink both pass; this catches those, so a partial install is not reported
# as a success. It deliberately does NOT execute node: a correctly installed
# binary can still fail to run on an incompatible host (e.g. a newer node on an
# older glibc), which is not a broken install - and a corrupt download is
# already rejected by the checksum check before extraction.
nvm_validate_install() {
local VERSION
VERSION="${1-}"
if [ -z "${VERSION}" ]; then
return 1
fi
local VERSION_PATH
VERSION_PATH="$(nvm_version_path "${VERSION}" 2>/dev/null)"
if [ -z "${VERSION_PATH}" ] || [ ! -d "${VERSION_PATH}" ]; then
return 1
fi
local NVM_NODE_BINARY
NVM_NODE_BINARY='node'
if [ "_$(nvm_get_os)" = '_win' ]; then
NVM_NODE_BINARY='node.exe'
fi
local NVM_NODE_PATH
NVM_NODE_PATH="${VERSION_PATH}/bin/${NVM_NODE_BINARY}"
# A zero-byte file with the exec bit set still passes `[ -x ]` (the shell
# would run it as an empty script), so require a non-empty executable.
if [ ! -s "${NVM_NODE_PATH}" ] || [ ! -x "${NVM_NODE_PATH}" ]; then
nvm_err "The installed node binary at ${NVM_NODE_PATH} is missing or empty."
return 1
fi
# npm ships with every supported node/io.js version; if its entry is a
# symlink it must resolve (one pointing at a removed target counts as broken).
if [ -h "${VERSION_PATH}/bin/npm" ] && [ ! -e "${VERSION_PATH}/bin/npm" ]; then
nvm_err "npm for ${VERSION} is a dangling symlink."
return 1
fi
return 0
}
nvm_print_npm_version() {
if nvm_has "npm"; then
local NPM_VERSION
NPM_VERSION="$(npm --version 2>/dev/null)"
if [ -n "${NPM_VERSION}" ]; then
command printf " (npm v${NPM_VERSION})"
fi
fi
}
nvm_install_latest_npm() {
nvm_echo 'Attempting to upgrade to the latest working version of npm...'
local NODE_VERSION
NODE_VERSION="$(nvm_strip_iojs_prefix "$(nvm_ls_current)")"
local NPM_VERSION
NPM_VERSION="$(npm --version 2>/dev/null)"
if [ "${NODE_VERSION}" = 'system' ]; then
NODE_VERSION="$(node --version)"
elif [ "${NODE_VERSION}" = 'none' ]; then
nvm_echo "Detected node version ${NODE_VERSION}, npm version v${NPM_VERSION}"
NODE_VERSION=''
fi
if [ -z "${NODE_VERSION}" ]; then
nvm_err 'Unable to obtain node version.'
return 1
fi
if [ -z "${NPM_VERSION}" ]; then
nvm_err 'Unable to obtain npm version.'
return 2
fi
local NVM_NPM_CMD
NVM_NPM_CMD='npm'
if [ "${NVM_DEBUG-}" = 1 ]; then
nvm_echo "Detected node version ${NODE_VERSION}, npm version v${NPM_VERSION}"
NVM_NPM_CMD='nvm_echo npm'
fi
local NVM_IS_0_6
NVM_IS_0_6=0
if nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 0.6.0 && nvm_version_greater 0.7.0 "${NODE_VERSION}"; then
NVM_IS_0_6=1
fi
local NVM_IS_0_9
NVM_IS_0_9=0
if nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 0.9.0 && nvm_version_greater 0.10.0 "${NODE_VERSION}"; then
NVM_IS_0_9=1
fi
if [ $NVM_IS_0_6 -eq 1 ]; then
nvm_echo '* `node` v0.6.x can only upgrade to `npm` v1.3.x'
$NVM_NPM_CMD install -g npm@1.3
elif [ $NVM_IS_0_9 -eq 0 ]; then
# node 0.9 breaks here, for some reason
if nvm_version_greater_than_or_equal_to "${NPM_VERSION}" 1.0.0 && nvm_version_greater 2.0.0 "${NPM_VERSION}"; then
nvm_echo '* `npm` v1.x needs to first jump to `npm` v1.4.28 to be able to upgrade further'
$NVM_NPM_CMD install -g npm@1.4.28
elif nvm_version_greater_than_or_equal_to "${NPM_VERSION}" 2.0.0 && nvm_version_greater 3.0.0 "${NPM_VERSION}"; then
nvm_echo '* `npm` v2.x needs to first jump to the latest v2 to be able to upgrade further'
$NVM_NPM_CMD install -g npm@2
fi
fi
if [ $NVM_IS_0_9 -eq 1 ] || [ $NVM_IS_0_6 -eq 1 ]; then
nvm_echo '* node v0.6 and v0.9 are unable to upgrade further'
elif nvm_version_greater 1.1.0 "${NODE_VERSION}"; then
nvm_echo '* `npm` v4.5.x is the last version that works on `node` versions < v1.1.0'
$NVM_NPM_CMD install -g npm@4.5
elif nvm_version_greater 4.0.0 "${NODE_VERSION}"; then
nvm_echo '* `npm` v5 and higher do not work on `node` versions below v4.0.0'
$NVM_NPM_CMD install -g npm@4
elif [ $NVM_IS_0_9 -eq 0 ] && [ $NVM_IS_0_6 -eq 0 ]; then
local NVM_IS_4_4_OR_BELOW
NVM_IS_4_4_OR_BELOW=0
if nvm_version_greater 4.5.0 "${NODE_VERSION}"; then
NVM_IS_4_4_OR_BELOW=1
fi
local NVM_IS_5_OR_ABOVE
NVM_IS_5_OR_ABOVE=0
if [ $NVM_IS_4_4_OR_BELOW -eq 0 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 5.0.0; then
NVM_IS_5_OR_ABOVE=1
fi
local NVM_IS_6_OR_ABOVE
NVM_IS_6_OR_ABOVE=0
local NVM_IS_6_2_OR_ABOVE
NVM_IS_6_2_OR_ABOVE=0
if [ $NVM_IS_5_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 6.0.0; then
NVM_IS_6_OR_ABOVE=1
if nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 6.2.0; then
NVM_IS_6_2_OR_ABOVE=1
fi
fi
local NVM_IS_9_OR_ABOVE
NVM_IS_9_OR_ABOVE=0
local NVM_IS_9_3_OR_ABOVE
NVM_IS_9_3_OR_ABOVE=0
if [ $NVM_IS_6_2_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 9.0.0; then
NVM_IS_9_OR_ABOVE=1
if nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 9.3.0; then
NVM_IS_9_3_OR_ABOVE=1
fi
fi
local NVM_IS_10_OR_ABOVE
NVM_IS_10_OR_ABOVE=0
if [ $NVM_IS_9_3_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 10.0.0; then
NVM_IS_10_OR_ABOVE=1
fi
local NVM_IS_12_LTS_OR_ABOVE
NVM_IS_12_LTS_OR_ABOVE=0
if [ $NVM_IS_10_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 12.13.0; then
NVM_IS_12_LTS_OR_ABOVE=1
fi
local NVM_IS_13_OR_ABOVE
NVM_IS_13_OR_ABOVE=0
if [ $NVM_IS_12_LTS_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 13.0.0; then
NVM_IS_13_OR_ABOVE=1
fi
local NVM_IS_14_LTS_OR_ABOVE
NVM_IS_14_LTS_OR_ABOVE=0
if [ $NVM_IS_13_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 14.15.0; then
NVM_IS_14_LTS_OR_ABOVE=1
fi
local NVM_IS_14_17_OR_ABOVE
NVM_IS_14_17_OR_ABOVE=0
if [ $NVM_IS_14_LTS_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 14.17.0; then
NVM_IS_14_17_OR_ABOVE=1
fi
local NVM_IS_15_OR_ABOVE
NVM_IS_15_OR_ABOVE=0
if [ $NVM_IS_14_LTS_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 15.0.0; then
NVM_IS_15_OR_ABOVE=1
fi
local NVM_IS_16_OR_ABOVE
NVM_IS_16_OR_ABOVE=0
if [ $NVM_IS_15_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 16.0.0; then
NVM_IS_16_OR_ABOVE=1
fi
local NVM_IS_16_LTS_OR_ABOVE
NVM_IS_16_LTS_OR_ABOVE=0
if [ $NVM_IS_16_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 16.13.0; then
NVM_IS_16_LTS_OR_ABOVE=1
fi
local NVM_IS_17_OR_ABOVE
NVM_IS_17_OR_ABOVE=0
if [ $NVM_IS_16_LTS_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 17.0.0; then
NVM_IS_17_OR_ABOVE=1
fi
local NVM_IS_18_OR_ABOVE
NVM_IS_18_OR_ABOVE=0
if [ $NVM_IS_17_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 18.0.0; then
NVM_IS_18_OR_ABOVE=1
fi
local NVM_IS_18_17_OR_ABOVE
NVM_IS_18_17_OR_ABOVE=0
if [ $NVM_IS_18_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 18.17.0; then
NVM_IS_18_17_OR_ABOVE=1
fi
local NVM_IS_19_OR_ABOVE
NVM_IS_19_OR_ABOVE=0
if [ $NVM_IS_18_17_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 19.0.0; then
NVM_IS_19_OR_ABOVE=1
fi
local NVM_IS_20_5_OR_ABOVE
NVM_IS_20_5_OR_ABOVE=0
if [ $NVM_IS_19_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 20.5.0; then
NVM_IS_20_5_OR_ABOVE=1
fi
local NVM_IS_20_17_OR_ABOVE
NVM_IS_20_17_OR_ABOVE=0
if [ $NVM_IS_20_5_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 20.17.0; then
NVM_IS_20_17_OR_ABOVE=1
fi
local NVM_IS_21_OR_ABOVE
NVM_IS_21_OR_ABOVE=0
if [ $NVM_IS_20_17_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 21.0.0; then
NVM_IS_21_OR_ABOVE=1
fi
local NVM_IS_22_9_OR_ABOVE
NVM_IS_22_9_OR_ABOVE=0
if [ $NVM_IS_21_OR_ABOVE -eq 1 ] && nvm_version_greater_than_or_equal_to "${NODE_VERSION}" 22.9.0; then
NVM_IS_22_9_OR_ABOVE=1
fi
if [ $NVM_IS_4_4_OR_BELOW -eq 1 ] || {
[ $NVM_IS_5_OR_ABOVE -eq 1 ] && nvm_version_greater 5.10.0 "${NODE_VERSION}"; \
}; then
nvm_echo '* `npm` `v5.3.x` is the last version that works on `node` 4.x versions below v4.4, or 5.x versions below v5.10, due to `Buffer.alloc`'
$NVM_NPM_CMD install -g npm@5.3
elif [ $NVM_IS_4_4_OR_BELOW -eq 0 ] && nvm_version_greater 4.7.0 "${NODE_VERSION}"; then
nvm_echo '* `npm` `v5.4.1` is the last version that works on `node` `v4.5` and `v4.6`'
$NVM_NPM_CMD install -g npm@5.4.1
elif [ $NVM_IS_6_OR_ABOVE -eq 0 ]; then
nvm_echo '* `npm` `v5.x` is the last version that works on `node` below `v6.0.0`'
$NVM_NPM_CMD install -g npm@5
elif \
{ [ $NVM_IS_6_OR_ABOVE -eq 1 ] && [ $NVM_IS_6_2_OR_ABOVE -eq 0 ]; } \
|| { [ $NVM_IS_9_OR_ABOVE -eq 1 ] && [ $NVM_IS_9_3_OR_ABOVE -eq 0 ]; } \
; then
nvm_echo '* `npm` `v6.9` is the last version that works on `node` `v6.0.x`, `v6.1.x`, `v9.0.x`, `v9.1.x`, or `v9.2.x`'
$NVM_NPM_CMD install -g npm@6.9
elif [ $NVM_IS_10_OR_ABOVE -eq 0 ]; then
if nvm_version_greater 4.4.4 "${NPM_VERSION}"; then
nvm_echo '* `npm` `v4.4.4` or later is required to install npm v6.14.18'
$NVM_NPM_CMD install -g npm@4
fi
nvm_echo '* `npm` `v6.x` is the last version that works on `node` below `v10.0.0`'
$NVM_NPM_CMD install -g npm@6
elif \
[ $NVM_IS_12_LTS_OR_ABOVE -eq 0 ] \
|| { [ $NVM_IS_13_OR_ABOVE -eq 1 ] && [ $NVM_IS_14_LTS_OR_ABOVE -eq 0 ]; } \
|| { [ $NVM_IS_15_OR_ABOVE -eq 1 ] && [ $NVM_IS_16_OR_ABOVE -eq 0 ]; } \
; then
nvm_echo '* `npm` `v7.x` is the last version that works on `node` `v13`, `v15`, below `v12.13`, or `v14.0` - `v14.15`'
$NVM_NPM_CMD install -g npm@7
elif \
{ [ $NVM_IS_12_LTS_OR_ABOVE -eq 1 ] && [ $NVM_IS_13_OR_ABOVE -eq 0 ]; } \
|| { [ $NVM_IS_14_LTS_OR_ABOVE -eq 1 ] && [ $NVM_IS_14_17_OR_ABOVE -eq 0 ]; } \
|| { [ $NVM_IS_16_OR_ABOVE -eq 1 ] && [ $NVM_IS_16_LTS_OR_ABOVE -eq 0 ]; } \
|| { [ $NVM_IS_17_OR_ABOVE -eq 1 ] && [ $NVM_IS_18_OR_ABOVE -eq 0 ]; } \
; then
nvm_echo '* `npm` `v8.6` is the last version that works on `node` `v12`, `v14.13` - `v14.16`, or `v16.0` - `v16.12`'
# ^8.7 breaks `npm ls` on file: deps
$NVM_NPM_CMD install -g npm@8.6
elif \
[ $NVM_IS_18_17_OR_ABOVE -eq 0 ] \
|| { [ $NVM_IS_19_OR_ABOVE -eq 1 ] && [ $NVM_IS_20_5_OR_ABOVE -eq 0 ]; } \
; then
# TODO: 10.8.3 can run on 16.20.2?? https://github.com/nodejs/Release/issues/884#issuecomment-2558077691
nvm_echo '* `npm` `v9.x` is the last version that works on `node` `< v18.17`, `v19`, or `v20.0` - `v20.4`'
$NVM_NPM_CMD install -g npm@9
elif \
[ $NVM_IS_20_17_OR_ABOVE -eq 0 ] \
|| { [ $NVM_IS_21_OR_ABOVE -eq 1 ] && [ $NVM_IS_22_9_OR_ABOVE -eq 0 ]; } \
; then
nvm_echo '* `npm` `v10.x` is the last version that works on `node` `< v20.17`, `v21`, or `v22.0` - `v22.8`'
$NVM_NPM_CMD install -g npm@10
else
nvm_echo '* Installing latest `npm`; if this does not work on your node version, please report a bug!'
$NVM_NPM_CMD install -g npm
fi
fi
nvm_echo "* npm upgraded to: v$(npm --version 2>/dev/null)"
}
# Make zsh glob matching behave same as bash
# This fixes the "zsh: no matches found" errors
if [ -z "${NVM_CD_FLAGS-}" ]; then
export NVM_CD_FLAGS=''
fi
if nvm_is_zsh; then
NVM_CD_FLAGS="-q"
fi
# Auto detect the NVM_DIR when not set
if [ -z "${NVM_DIR-}" ]; then
NVM_SCRIPT_SOURCE=''
# shellcheck disable=SC2128
if [ -n "${BASH_SOURCE-}" ]; then
NVM_SCRIPT_SOURCE="${BASH_SOURCE}"
elif nvm_is_zsh; then
# `%x` names the file being sourced even when `$0` does not, eg under `emulate sh`
eval 'NVM_SCRIPT_SOURCE="${(%):-%x}"'
elif [ -n "${KSH_VERSION-}" ] && (eval ': "${.sh.file}"') 2>/dev/null; then
# only ksh93 has `.sh.file`; other shells abort on the syntax, so it is probed in a subshell first
eval 'NVM_SCRIPT_SOURCE="${.sh.file}"'
fi
if [ -n "${NVM_SCRIPT_SOURCE}" ] && [ -f "${NVM_SCRIPT_SOURCE}" ]; then
# shellcheck disable=SC2086
NVM_DIR="$(nvm_cd ${NVM_CD_FLAGS} "$(dirname "${NVM_SCRIPT_SOURCE}")" >/dev/null && \pwd)"
else
# other shells (eg, dash) cannot tell where a sourced file lives (`$0` names the shell or the calling script),
# and a file sourced from a pipe (eg, `/dev/fd/63`) has no directory, so use the default install location, as `install.sh` does
if [ -n "${XDG_CONFIG_HOME-}" ]; then
NVM_DIR="${XDG_CONFIG_HOME}/nvm"
else
NVM_DIR="${HOME-}/.nvm"
fi
if [ -f "${NVM_DIR}/nvm.sh" ]; then
# shellcheck disable=SC2086
NVM_DIR="$(nvm_cd ${NVM_CD_FLAGS} "${NVM_DIR}" >/dev/null && \pwd)"
else
NVM_DIR=''
fi
fi
if [ -z "${NVM_DIR}" ]; then
unset NVM_DIR NVM_SCRIPT_SOURCE 2>/dev/null
nvm_err 'nvm: unable to detect $NVM_DIR; set it to the directory containing nvm.sh before sourcing it'
return 1
fi
export NVM_DIR
else
# https://unix.stackexchange.com/a/198289
case $NVM_DIR in
*[!/]*/)
NVM_DIR="${NVM_DIR%"${NVM_DIR##*[!/]}"}"
export NVM_DIR
nvm_err "Warning: \$NVM_DIR should not have trailing slashes"
;;
esac
fi
unset NVM_SCRIPT_SOURCE 2>/dev/null
# Walks parent paths without subshells, comparing names literally before checking
# filesystem identity to account for case-insensitive paths and directory symlinks.
nvm_tree_contains_path() {
local tree
tree="${1-}"
local node_path
node_path="${2-}"
if [ "@${tree}@" = "@@" ] || [ "@${node_path}@" = "@@" ]; then
nvm_err "both the tree and the node path are required"
return 2
fi
local clean_tree
clean_tree="${tree}"
# Strip trailing slashes in shell memory (e.g., "dir//" -> "dir")
while [ "${clean_tree}" != "${clean_tree%/}" ]; do
clean_tree="${clean_tree%/}"
done
if [ -z "${clean_tree}" ]; then
clean_tree='/'
fi
# Keep literal matching for paths that do not exist, including glob characters.
local pathdir
pathdir="${node_path}"
while [ "${pathdir}" != '' ] && [ "${pathdir}" != '.' ] && [ "${pathdir}" != '/' ] &&
[ "${pathdir}" != "${clean_tree}" ] && ! [ "${pathdir}" -ef "${clean_tree}" ]; do
case "${pathdir}" in
*/*)
pathdir="${pathdir%/*}"
if [ -z "${pathdir}" ]; then
pathdir='/'
fi
;;
*)
break
;;
esac
done
[ "${pathdir}" = "${clean_tree}" ] || [ "${pathdir}" -ef "${clean_tree}" ]
}
nvm_find_project_dir() {
local path_
local parent_
path_="${PWD}"
while [ "${path_}" != "" ] && [ ! -f "${path_}/package.json" ] && [ ! -d "${path_}/node_modules" ]; do
parent_=${path_%/*}
# stop when there is nowhere left to go up, e.g. `.` or a Windows drive root like `C:`
[ "${parent_}" != "${path_}" ] || break
path_="${parent_}"
done
nvm_echo "${path_}"
}
# Traverse up in directory tree to find containing folder
nvm_find_up() {
local path_
local parent_
path_="${PWD}"
while [ "${path_}" != "" ] && [ ! -f "${path_}/${1-}" ]; do
parent_=${path_%/*}
# stop when there is nowhere left to go up, e.g. `.` or a Windows drive root like `C:`
[ "${parent_}" != "${path_}" ] || break
path_="${parent_}"
done
nvm_echo "${path_}"
}
nvm_find_nvmrc() {
local dir
dir="$(nvm_find_up '.nvmrc')"
if [ -e "${dir}/.nvmrc" ]; then
nvm_echo "${dir}/.nvmrc"
fi
}
nvm_nvmrc_invalid_msg() {
local error_text
error_text="invalid .nvmrc!
all non-commented content (anything after # is a comment) must be either:
- a single bare nvm-recognized version-ish
- or, multiple distinct key-value pairs, each key/value separated by a single equals sign (=)
additionally, a single bare nvm-recognized version-ish must be present (after stripping comments)."
# show control characters (other than tabs and newlines) as `?`, so the parsed content is printed as plain text
local warn_text
warn_text="non-commented content parsed:
$(nvm_echo "${1}" | command tr '\001-\010\013-\037\177' '??????????????????????????????')"
nvm_err "$(nvm_wrap_with_color_code 'r' "${error_text}")
$(nvm_wrap_with_color_code 'y' "${warn_text}")"
}
nvm_process_nvmrc_content() {
local NVMRC_CONTENT
NVMRC_CONTENT="${1-}"
local lines
lines=$(nvm_echo "${NVMRC_CONTENT}" | command sed 's/#.*//' | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | nvm_grep -v '^$')
if [ -z "$lines" ]; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
# control characters, other than tabs, are not valid in any line
if [ -n "$(nvm_echo "${lines}" | command tr -d '\t\n' | command tr -cd '[:cntrl:]')" ]; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
# Initialize key-value storage
local keys
keys=''
local values
values=''
local unpaired_line
unpaired_line=''
while IFS= read -r line; do
if [ -z "${line}" ]; then
continue
elif [ -z "${line%%=*}" ]; then
if [ -n "${unpaired_line}" ]; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
unpaired_line="${line}"
elif case "$line" in *'='*) true;; *) false;; esac; then
key="${line%%=*}"
value="${line#*=}"
# Trim whitespace around key and value
key=$(nvm_echo "${key}" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
value=$(nvm_echo "${value}" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# Check for invalid key "node"
if [ "${key}" = 'node' ]; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
# Check for duplicate keys
if nvm_echo "${keys}" | nvm_grep -q -E "(^| )${key}( |$)"; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
keys="${keys} ${key}"
values="${values} ${value}"
else
if [ -n "${unpaired_line}" ]; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
unpaired_line="${line}"
fi
done <<EOF
$lines
EOF
if [ -z "${unpaired_line}" ]; then
nvm_nvmrc_invalid_msg "${lines}"
return 1
fi
nvm_echo "${unpaired_line}"
}
nvm_is_version_or_alias() {
case "${1-}" in
system | 'lts/*') return 0 ;;
lts/-*)
case "${1#lts/-}" in
'' | *[!0-9]*) return 1 ;;
esac
return 0
;;
lts/*)
case "${1#lts/}" in
'' | *[![:lower:]]*) return 1 ;;
esac
return 0
;;
esac
nvm_is_valid_version "${1-}" || nvm_alias "${1-}" > /dev/null 2>&1
}
nvm_process_nvmrc() {
local NVMRC_PATH
NVMRC_PATH="$1"
if [ ! -L "${NVMRC_PATH}" ]; then
nvm_process_nvmrc_content "$(command cat "${NVMRC_PATH}")"
return
fi
# a symlink can point at any file, so never print its content,
# and only accept a version or an existing alias, which would be printed later
local NVMRC_VERSION
if ! NVMRC_VERSION="$(nvm_process_nvmrc_content "$(command cat "${NVMRC_PATH}")" 2>/dev/null)" \
|| ! nvm_is_version_or_alias "${NVMRC_VERSION}"; then
nvm_err "invalid .nvmrc! '${NVMRC_PATH}' is a symbolic link, so it must contain a version or an alias name; its content is not shown."
return 1
fi
nvm_echo "${NVMRC_VERSION}"
}
nvm_rc_version() {
local NVMRC_PATH
NVMRC_PATH="$(nvm_find_nvmrc)"
if [ ! -e "${NVMRC_PATH}" ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "No version provided and no .nvmrc file found"
fi
return 1
fi
local NVM_RC_VERSION
if ! NVM_RC_VERSION="$(nvm_process_nvmrc "${NVMRC_PATH}")"; then
return 1
fi
if [ -z "${NVM_RC_VERSION}" ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "Warning: empty .nvmrc file found at \"${NVMRC_PATH}\""
fi
return 2
fi
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "Found '${NVMRC_PATH}' with version <${NVM_RC_VERSION}>"
fi
nvm_echo "${NVM_RC_VERSION}" >&3
}
nvm_clang_version() {
clang --version | command awk '{ if ($2 == "version") print $3; else if ($3 == "version") print $4 }' | command sed 's/-.*$//g'
}
nvm_curl_version() {
command curl -V | command awk '{ if ($1 == "curl") print $2 }' | command sed 's/-.*$//g'
}
# Try to do some shell magic to do semver greater-than maths.
# Fall through to the expensive test by calling `awk` if we can't be sure.
nvm_version_greater() {
local NVM_LEFT
NVM_LEFT="${1#v}"
local NVM_RIGHT
NVM_RIGHT="${2#v}"
local NVM_PLAIN
# a third, more complex, argument of `1` (a flag) compares equal versions as true; `0` or
# no argument compares them as false.
local NVM_OR_EQUAL
NVM_OR_EQUAL="${3:-0}"
NVM_PLAIN='true'
# `x.y.z` operands are compared in shell arithmetic, which avoids a fork,
# except when a group is long enough to overflow it; anything else - partial
# versions, prereleases, and malformed operands - keeps the comparison this
# function has always made
case "${NVM_LEFT}" in
'' | *[!0-9.]* | *..* | .* | *. | *.*.*.*) NVM_PLAIN='false' ;;
*.*.*) ;;
*) NVM_PLAIN='false' ;;
esac
case "${NVM_RIGHT}" in
'' | *[!0-9.]* | *..* | .* | *. | *.*.*.*) NVM_PLAIN='false' ;;
*.*.*) ;;
*) NVM_PLAIN='false' ;;
esac
if [ "${NVM_PLAIN}" = 'true' ] && [ "${#NVM_LEFT}" -lt 19 ] && [ "${#NVM_RIGHT}" -lt 19 ]; then
local NVM_GROUP
local NVM_LEFT_GROUP
local NVM_RIGHT_GROUP
NVM_GROUP=1
while [ "${NVM_GROUP}" -le 3 ]; do
NVM_LEFT_GROUP="${NVM_LEFT%%.*}"
NVM_LEFT="${NVM_LEFT#*.}"
NVM_RIGHT_GROUP="${NVM_RIGHT%%.*}"
NVM_RIGHT="${NVM_RIGHT#*.}"
if [ "${NVM_LEFT_GROUP}" -lt "${NVM_RIGHT_GROUP}" ]; then
return 1
elif [ "${NVM_LEFT_GROUP}" -gt "${NVM_RIGHT_GROUP}" ]; then
return 0
fi
NVM_GROUP=$((NVM_GROUP + 1))
done
if [ "${NVM_OR_EQUAL}" = 1 ]; then
return 0
fi
return 1
fi
command awk -v or_equal="${NVM_OR_EQUAL}" 'BEGIN {
if (ARGV[1] == "" || ARGV[2] == "") exit(1)
split(ARGV[1], a, /\./);
split(ARGV[2], b, /\./);
for (i=1; i<=3; i++) {
if (a[i] && a[i] !~ /^[0-9]+$/) exit(2);
if (b[i] && b[i] !~ /^[0-9]+$/) {
# a non-numeric right-hand group (a prerelease): the left is greater,
# unless equality counts, in which case the comparison below decides
if (or_equal != 1) { exit(0); }
}
if (a[i] < b[i]) exit(3);
else if (a[i] > b[i]) exit(0);
}
if (or_equal == 1) { exit(0); }
exit(4)
}' "${NVM_LEFT}" "${NVM_RIGHT}"
}
# Try to do some shell magic to do semver greater-than or equal-to maths.
# Fall through to the expensive test by calling `awk` if we can't be sure.
# see `nvm_version_greater`
nvm_version_greater_than_or_equal_to() {
nvm_version_greater "${1-}" "${2-}" 1
}
nvm_version_dir() {
local NVM_WHICH_DIR
NVM_WHICH_DIR="${1-}"
if [ -z "${NVM_WHICH_DIR}" ] || [ "${NVM_WHICH_DIR}" = "new" ]; then
nvm_echo "${NVM_DIR}/versions/node"
elif [ "_${NVM_WHICH_DIR}" = "_iojs" ]; then
nvm_echo "${NVM_DIR}/versions/io.js"
elif [ "_${NVM_WHICH_DIR}" = "_old" ]; then
nvm_echo "${NVM_DIR}"
else
nvm_err 'unknown version dir'
return 3
fi
}
nvm_alias_path() {
nvm_echo "$(nvm_version_dir old)/alias"
}
nvm_version_path() {
local VERSION
VERSION="${1-}"
case "/${VERSION}/" in
*/../*)
nvm_err "invalid version: ${VERSION}"
return 3
;;
esac
if [ -z "${VERSION}" ]; then
nvm_err 'version is required'
return 3
elif nvm_is_iojs_version "${VERSION}"; then
nvm_echo "$(nvm_version_dir iojs)/$(nvm_strip_iojs_prefix "${VERSION}")"
elif nvm_version_greater 0.12.0 "${VERSION}"; then
nvm_echo "$(nvm_version_dir old)/${VERSION}"
else
nvm_echo "$(nvm_version_dir new)/${VERSION}"
fi
}
nvm_ensure_version_installed() {
local PROVIDED_VERSION
PROVIDED_VERSION="${1-}"
local IS_VERSION_FROM_NVMRC
IS_VERSION_FROM_NVMRC="${2-}"
if [ "${PROVIDED_VERSION}" = 'system' ]; then
if nvm_has_system_iojs || nvm_has_system_node; then
return 0
fi
nvm_err "N/A: no system version of node/io.js is installed."
return 1
fi
local LOCAL_VERSION
local EXIT_CODE
LOCAL_VERSION="$(nvm_version "${PROVIDED_VERSION}")"
EXIT_CODE="$?"
local NVM_VERSION_DIR
if [ "${EXIT_CODE}" != "0" ] || ! nvm_is_version_installed "${LOCAL_VERSION}"; then
if nvm_explain_excluded_version "${PROVIDED_VERSION}"; then
return 1
fi
if VERSION="$(nvm_resolve_alias "${PROVIDED_VERSION}")"; then
nvm_err "N/A: version \"${PROVIDED_VERSION} -> ${VERSION}\" is not yet installed."
else
local PREFIXED_VERSION
PREFIXED_VERSION="$(nvm_ensure_version_prefix "${PROVIDED_VERSION}")"
nvm_err "N/A: version \"${PREFIXED_VERSION:-$PROVIDED_VERSION}\" is not yet installed."
fi
nvm_err ""
if [ "${PROVIDED_VERSION}" = 'lts' ]; then
nvm_err '`lts` is not an alias - you may need to run `nvm install --lts` to install and `nvm use --lts` to use it.'
elif [ "${IS_VERSION_FROM_NVMRC}" != '1' ]; then
nvm_err "You need to run \`nvm install ${PROVIDED_VERSION}\` to install and use it."
else
nvm_err 'You need to run `nvm install` to install and use the node version specified in `.nvmrc`.'
fi
return 1
fi
}
# args: version
# Explains, and succeeds, when the version only matches installed versions outside the selected categories.
nvm_explain_excluded_version() {
local NVM_EXCLUDED_VERSION
NVM_EXCLUDED_VERSION="$(NVM_ONLY_SELECTED='alpha,lts,non-lts,iojs' nvm_version "${1-}" 2>/dev/null)" ||:
if [ "_${NVM_EXCLUDED_VERSION:-N/A}" = '_N/A' ] || ! nvm_is_version_installed "${NVM_EXCLUDED_VERSION}"; then
return 1
fi
if [ "_${NVM_EXCLUDED_VERSION}" != "_$(nvm_ensure_version_prefix "${1-}")" ]; then
NVM_EXCLUDED_VERSION="${1-} -> ${NVM_EXCLUDED_VERSION}"
fi
nvm_err "N/A: version \"${NVM_EXCLUDED_VERSION}\" is installed, but excluded by the selected version categories (${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}})."
nvm_err ''
nvm_err 'Include its category with `--only=<categories>`, or in `$NVM_ONLY`.'
}
# Expand a version using the version cache
nvm_version() {
local PATTERN
PATTERN="${1-}"
local VERSION
# The default version is the current one
if [ -z "${PATTERN}" ]; then
PATTERN='current'
fi
if [ "${PATTERN}" = "current" ]; then
nvm_ls_current
return $?
fi
# flags stored in an alias, like `--lts`, precede the version they apply to
local NVM_LTS_FILTER
NVM_LTS_FILTER=''
local NVM_ONLY_ALIAS
NVM_ONLY_ALIAS=''
while :; do
case "${PATTERN}" in
'--lts '*)
NVM_LTS_FILTER='*'
;;
--only=*' '*)
NVM_ONLY_ALIAS="${PATTERN%% *}"
if ! NVM_ONLY_ALIAS="$(nvm_normalize_only "${NVM_ONLY_ALIAS#--only=}" "an alias's \`--only\`")"; then
nvm_echo 'N/A'
return 3
fi
;;
--lts=*' '*)
NVM_LTS_FILTER="${PATTERN%% *}"
NVM_LTS_FILTER="${NVM_LTS_FILTER#--lts=}"
;;
--*)
nvm_echo 'N/A'
return 3
;;
*) break ;;
esac
PATTERN="${PATTERN#* }"
done
# like `nvm_resolve_alias`, these flags replace those of an alias they precede
if [ -n "${NVM_LTS_FILTER}${NVM_ONLY_ALIAS}" ]; then
local NVM_FLAGGED_TARGET
if NVM_FLAGGED_TARGET="$(nvm_resolve_alias "${PATTERN}" 2>/dev/null)" && [ "_${NVM_FLAGGED_TARGET}" != '_∞' ]; then
while :; do
case "${NVM_FLAGGED_TARGET}" in
--*' '*) NVM_FLAGGED_TARGET="${NVM_FLAGGED_TARGET#* }" ;;
*) break ;;
esac
done
PATTERN="${NVM_FLAGGED_TARGET}"
fi
fi
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
case "_${PATTERN}" in
"_${NVM_NODE_PREFIX}" | "_${NVM_NODE_PREFIX}-" | _stable)
# `stable` is only the latest version, which might not match the LTS filter
if [ -n "${NVM_LTS_FILTER}" ]; then
PATTERN="${NVM_NODE_PREFIX}"
else
PATTERN="stable"
fi
;;
_lts/*)
# `lts/` aliases are written from index.tab's LTS rows, so their targets are LTS
case ",${NVM_ONLY_ALIAS:-${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}}}," in
*,non-lts,*) ;;
*,lts,*) NVM_ONLY_ALIAS="${NVM_ONLY_ALIAS:-${NVM_ONLY_SELECTED:-${NVM_ONLY-}}},non-lts" ;;
esac
;;
esac
if [ -n "${NVM_ONLY_ALIAS}" ]; then
if nvm_needs_lts_status "${NVM_ONLY_ALIAS}" && ! nvm_ensure_lts_status; then
nvm_err 'The LTS status of installed versions is not recorded yet; run `nvm ls-remote` to record it.'
nvm_echo 'N/A'
return 3
fi
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_ALIAS}"
fi
# Fast path: an exact, fully-qualified version that is installed resolves to
# itself, unless an alias of the same name takes precedence. Short-circuiting
# it here avoids the `nvm_ls` subprocess pipeline on shell startup; every
# other pattern falls through to `nvm_ls` unchanged.
if [ -z "${NVM_LTS_FILTER}" ] && nvm_is_installed_exact_version "${PATTERN}"; then
nvm_echo "${PATTERN}"
return 0
fi
if [ -n "${NVM_LTS_FILTER}" ]; then
VERSION="$(nvm_ls "${PATTERN}" | nvm_filter_lts_versions "${NVM_LTS_FILTER}" | command tail -1)"
else
VERSION="$(nvm_ls "${PATTERN}" | command tail -1)"
fi
case "${VERSION}" in
system[[:blank:]]*)
VERSION='system'
;;
esac
if [ -z "${VERSION}" ] || [ "_${VERSION}" = "_N/A" ]; then
nvm_echo "N/A"
return 3
fi
nvm_echo "${VERSION}"
}
nvm_remote_version() {
local PATTERN
PATTERN="${1-}"
local VERSION
if nvm_validate_implicit_alias "${PATTERN}" 2>/dev/null; then
case "${PATTERN}" in
"$(nvm_iojs_prefix)")
VERSION="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote_iojs | command tail -1)" &&:
;;
*)
VERSION="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote "${PATTERN}")" &&:
;;
esac
else
VERSION="$(NVM_LTS="${NVM_LTS-}" nvm_remote_versions "${PATTERN}" | command tail -1)"
fi
if [ -n "${PATTERN}" ] && [ "_${VERSION}" != "_N/A" ] && ! nvm_validate_implicit_alias "${PATTERN}" 2>/dev/null; then
local VERSION_NUM
VERSION_NUM="$(nvm_echo "${VERSION}" | command awk '{print $1}')"
# the `v` prefix and the trailing non-digit keep `20` from matching `v10.20.0` or `v200.0.0`
if ! nvm_echo "${VERSION_NUM} " | nvm_grep -q "$(nvm_ensure_version_prefix "${PATTERN%.}")[^0-9]"; then
VERSION='N/A'
fi
fi
if [ -n "${NVM_VERSION_ONLY-}" ]; then
command awk 'BEGIN {
n = split(ARGV[1], a);
print a[1]
}' "${VERSION}"
else
nvm_echo "${VERSION}"
fi
if [ "${VERSION}" = 'N/A' ]; then
return 3
fi
}
nvm_remote_versions() {
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
local PATTERN
PATTERN="${1-}"
local NVM_FLAVOR
if [ -n "${NVM_LTS-}" ]; then
NVM_FLAVOR="${NVM_NODE_PREFIX}"
fi
case "${PATTERN}" in
"${NVM_IOJS_PREFIX}" | "io.js")
NVM_FLAVOR="${NVM_IOJS_PREFIX}"
unset PATTERN
;;
"${NVM_NODE_PREFIX}")
NVM_FLAVOR="${NVM_NODE_PREFIX}"
unset PATTERN
;;
[04-9]* | [1-9][0-9]* | v[04-9]* | v[1-9][0-9]*)
# io.js only released v1 through v3, so it has no versions matching any other major
NVM_FLAVOR="${NVM_NODE_PREFIX}"
;;
esac
if nvm_validate_implicit_alias "${PATTERN-}" 2>/dev/null; then
nvm_err 'Implicit aliases are not supported in nvm_remote_versions.'
return 1
fi
local NVM_LS_REMOTE_EXIT_CODE
NVM_LS_REMOTE_EXIT_CODE=0
local NVM_LS_REMOTE_PRE_MERGED_OUTPUT
NVM_LS_REMOTE_PRE_MERGED_OUTPUT=''
local NVM_LS_REMOTE_POST_MERGED_OUTPUT
NVM_LS_REMOTE_POST_MERGED_OUTPUT=''
if {
[ -z "${NVM_FLAVOR-}" ] || [ "${NVM_FLAVOR-}" = "${NVM_NODE_PREFIX}" ];
} && {
nvm_only_includes alpha || nvm_only_includes lts || nvm_only_includes non-lts;
}; then
local NVM_LS_REMOTE_OUTPUT
# extra space is needed here to avoid weird behavior when `nvm_ls_remote` ends in a `*`
NVM_LS_REMOTE_OUTPUT="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote "${PATTERN-}") " &&:
NVM_LS_REMOTE_EXIT_CODE=$?
# split output into two: node v0.x sorts before io.js, and node v4+ after it.
# the list is sorted, so cut at the first line whose major is nonzero.
case "${NVM_LS_REMOTE_OUTPUT}" in
v[1-9]*) NVM_LS_REMOTE_PRE_MERGED_OUTPUT='' ;;
*) NVM_LS_REMOTE_PRE_MERGED_OUTPUT="${NVM_LS_REMOTE_OUTPUT%%
v[1-9]*}" ;;
esac
NVM_LS_REMOTE_POST_MERGED_OUTPUT="${NVM_LS_REMOTE_OUTPUT#"$NVM_LS_REMOTE_PRE_MERGED_OUTPUT"}"
fi
local NVM_LS_REMOTE_IOJS_EXIT_CODE
NVM_LS_REMOTE_IOJS_EXIT_CODE=0
local NVM_LS_REMOTE_IOJS_OUTPUT
NVM_LS_REMOTE_IOJS_OUTPUT=''
if [ -z "${NVM_LTS-}" ] && nvm_only_includes iojs && {
[ -z "${NVM_FLAVOR-}" ] || [ "${NVM_FLAVOR-}" = "${NVM_IOJS_PREFIX}" ];
}; then
NVM_LS_REMOTE_IOJS_OUTPUT=$(nvm_ls_remote_iojs "${PATTERN-}") &&:
NVM_LS_REMOTE_IOJS_EXIT_CODE=$?
fi
# the `sed` removes both blank lines, and only-whitespace lines (see "weird behavior" ~24 lines up)
VERSIONS="$(nvm_echo "${NVM_LS_REMOTE_PRE_MERGED_OUTPUT}
${NVM_LS_REMOTE_IOJS_OUTPUT}
${NVM_LS_REMOTE_POST_MERGED_OUTPUT}" | nvm_grep -v "N/A" | command sed '/^ *$/d')"
if [ -z "${VERSIONS}" ]; then
nvm_echo 'N/A'
return 3
fi
# the `sed` is to remove trailing whitespaces (see "weird behavior" ~33 lines up)
nvm_echo "${VERSIONS}" | command sed 's/ *$//g'
# shellcheck disable=SC2317
if [ "${NVM_LS_REMOTE_EXIT_CODE}" != '0' ]; then
return "${NVM_LS_REMOTE_EXIT_CODE}"
fi
return "${NVM_LS_REMOTE_IOJS_EXIT_CODE}"
}
nvm_is_valid_version() {
case "${1-}" in
"stable" | "unstable" | "iojs" | "node")
return 0
;;
*)
local VERSION
VERSION="${1-}"
VERSION="${VERSION#iojs-}"
local NVM_VERSION_CORE
NVM_VERSION_CORE="${VERSION#v}"
case "${NVM_VERSION_CORE}" in
*-*)
# prereleases (rc, nightly, v8-canary, ...) need a full x.y.z, and never have a dot followed by a non-digit, like a file extension
case "${NVM_VERSION_CORE#*-}" in
'' | .* | *. | *..* | *.*[!0-9.]* | *[!0-9A-Za-z.-]*) return 1 ;;
esac
NVM_VERSION_CORE="${NVM_VERSION_CORE%%-*}"
case "${NVM_VERSION_CORE}" in
*.*.*) ;;
*) return 1 ;;
esac
# a prerelease's `-` makes it unreachable for the pure-shell checks
# below, so do the full check now.
nvm_version_greater_than_or_equal_to "${VERSION}" 0 || return 1
;;
*.)
NVM_VERSION_CORE="${NVM_VERSION_CORE%.}"
;;
esac
case "${NVM_VERSION_CORE}" in
'' | .* | *. | *..* | *.*.*.* | *[!0-9.]*) return 1 ;;
esac
# every version that reaches this point is a number, and so `>= 0`
;;
esac
}
nvm_normalize_version() {
command awk 'BEGIN {
split(ARGV[1], a, /\./);
printf "%d%06d%06d\n", a[1], a[2], a[3];
exit;
}' "${1#v}"
}
nvm_normalize_lts() {
local LTS
LTS="${1-}"
case "${LTS}" in
lts/-[123456789] | lts/-[123456789][0123456789]*)
local N
N="$(echo "${LTS}" | cut -d '-' -f 2)"
N=$((N+1))
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
nvm_echo "${LTS}"
return 0
fi
local NVM_ALIAS_DIR
NVM_ALIAS_DIR="$(nvm_alias_path)"
local RESULT
RESULT="$(command ls "${NVM_ALIAS_DIR}/lts" | command tail -n "${N}" | command head -n 1)"
if [ "${RESULT}" != '*' ]; then
nvm_echo "lts/${RESULT}"
else
nvm_err 'That many LTS releases do not exist yet.'
return 2
fi
;;
*)
case "${LTS}" in
lts/*)
if [ "${LTS}" != "$(echo "${LTS}" | command tr '[:upper:]' '[:lower:]')" ]; then
nvm_err 'LTS names must be lowercase'
return 3
fi
;;
esac
nvm_echo "${LTS}"
;;
esac
}
nvm_ensure_version_prefix() {
local NVM_VERSION
NVM_VERSION="$(nvm_strip_iojs_prefix "${1-}" | command sed -e 's/^\([0-9]\)/v\1/g')"
if nvm_is_iojs_version "${1-}"; then
nvm_add_iojs_prefix "${NVM_VERSION}"
else
nvm_echo "${NVM_VERSION}"
fi
}
nvm_format_version() {
local VERSION
VERSION="$(nvm_ensure_version_prefix "${1-}")"
local NUM_GROUPS
NUM_GROUPS="$(nvm_num_version_groups "${VERSION}")"
if [ "${NUM_GROUPS}" -lt 3 ]; then
nvm_format_version "${VERSION%.}.0"
else
nvm_echo "${VERSION}" | command cut -f1-3 -d.
fi
}
nvm_num_version_groups() {
local VERSION
VERSION="${1-}"
VERSION="${VERSION#v}"
VERSION="${VERSION%.}"
if [ -z "${VERSION}" ]; then
nvm_echo "0"
return
fi
local NVM_NUM_DOTS
NVM_NUM_DOTS=$(nvm_echo "${VERSION}" | command sed -e 's/[^\.]//g')
local NVM_NUM_GROUPS
NVM_NUM_GROUPS=".${NVM_NUM_DOTS}" # add extra dot, since it's (n - 1) dots at this point
nvm_echo "${#NVM_NUM_GROUPS}"
}
nvm_strip_path() {
if [ -z "${NVM_DIR-}" ]; then
nvm_err '${NVM_DIR} not set!'
return 1
fi
local RESULT
RESULT="$(command printf %s "${1-}" | NVM_DIR="${NVM_DIR}" command awk -v RS=: '
BEGIN { NVM_DIR = ENVIRON["NVM_DIR"] }
index($0, NVM_DIR) == 1 {
path = substr($0, length(NVM_DIR) + 1)
if (path ~ "^(/versions/[^/]*)?/[^/]*'"${2-}"'.*$") { next }
}
{ printf "%s%s", sep, $0; sep=RS }')"
# mawk does not support RT, so preserve trailing colon manually
case "${1-}" in
*:) command printf '%s:' "${RESULT}" ;;
*) command printf '%s' "${RESULT}" ;;
esac
}
nvm_change_path() {
# if there’s no initial path, just return the supplementary path
if [ -z "${1-}" ]; then
nvm_echo "${3-}${2-}"
return
fi
# `${NVM_DIR}` is matched literally, so escape characters that are special in regexes
local NVM_DIR_RE
NVM_DIR_RE="$(nvm_echo "${NVM_DIR}" | command sed 's/[][\.*^$+?(){}|]/\\&/g')"
# if the initial path doesn’t contain an nvm path, prepend the supplementary
# path
if ! nvm_echo "${1-}" | nvm_grep -Eq "${NVM_DIR_RE}/[^/]*${2-}" \
&& ! nvm_echo "${1-}" | nvm_grep -Eq "${NVM_DIR_RE}/versions/[^/]*/[^/]*${2-}"; then
nvm_echo "${3-}${2-}:${1-}"
# if the initial path contains BOTH an nvm path (checked for above) and
# the first nvm path is preceded by a system binary path, just prepend the
# supplementary path instead of replacing it. Only what precedes the first
# nvm path counts, so that a shadowed nvm path further on does not make
# every change prepend yet another entry.
# https://github.com/nvm-sh/nvm/issues/1652#issuecomment-342571223
elif nvm_echo "${1%%"${NVM_DIR}"/*}" | nvm_grep -Eq "(^|:)(/usr(/local)?)?${2-}:"; then
nvm_echo "${3-}${2-}:${1-}"
# use sed to replace the existing nvm path with the supplementary path. This
# preserves the order of the path.
else
local NVM_DIR_SED
NVM_DIR_SED="$(nvm_echo "${NVM_DIR_RE}" | command sed 's/#/\\#/g')"
local NEW_DIR_SED
NEW_DIR_SED="$(nvm_echo "${3-}" | command sed 's/[\&#]/\\&/g')"
nvm_echo "${1-}" | command sed -E \
-e "s#${NVM_DIR_SED}/[^/]*${2-}[^:]*#${NEW_DIR_SED}${2-}#" \
-e "s#${NVM_DIR_SED}/versions/[^/]*/[^/]*${2-}[^:]*#${NEW_DIR_SED}${2-}#"
fi
}
nvm_hash_reset() {
# under `set +h` there is no cache to clear, and `hash -r` errors
if [ -n "${BASH_VERSION-}" ] && [ "${-#*h}" = "$-" ]; then
return 0
fi
# `ksh93`'s `hash` takes no `-r` and its usage error is fatal; probing in a
# subshell contains it, and spares the `ksh` variants that do accept `-r`
if [ -n "${KSH_VERSION-}" ] && ! ( \hash -r ) >/dev/null 2>&1; then
return 0
fi
\hash -r
}
nvm_binary_available() {
# binaries started with node 0.8.6
nvm_version_greater_than_or_equal_to "$(nvm_strip_iojs_prefix "${1-}")" v0.8.6
}
nvm_set_colors() {
if [ "${#1}" -eq 5 ] && nvm_echo "$1" | nvm_grep -E "^[rRgGbBcCyYmMkKeW]{1,}$" 1>/dev/null; then
local INSTALLED_COLOR
local LTS_AND_SYSTEM_COLOR
local CURRENT_COLOR
local NOT_INSTALLED_COLOR
local DEFAULT_COLOR
local NVM_HAS_COLORS
NVM_HAS_COLORS=0
INSTALLED_COLOR="$(echo "$1" | awk '{ print substr($0, 1, 1); }')"
LTS_AND_SYSTEM_COLOR="$(echo "$1" | awk '{ print substr($0, 2, 1); }')"
CURRENT_COLOR="$(echo "$1" | awk '{ print substr($0, 3, 1); }')"
NOT_INSTALLED_COLOR="$(echo "$1" | awk '{ print substr($0, 4, 1); }')"
DEFAULT_COLOR="$(echo "$1" | awk '{ print substr($0, 5, 1); }')"
if ! nvm_has_colors; then
nvm_echo "Setting colors to: ${INSTALLED_COLOR} ${LTS_AND_SYSTEM_COLOR} ${CURRENT_COLOR} ${NOT_INSTALLED_COLOR} ${DEFAULT_COLOR}"
nvm_echo "WARNING: Colors may not display because they are not supported in this shell."
else
NVM_HAS_COLORS=1
nvm_echo_with_colors "Setting colors to: $(nvm_wrap_with_color_code "${INSTALLED_COLOR}" "${INSTALLED_COLOR}")$(nvm_wrap_with_color_code "${LTS_AND_SYSTEM_COLOR}" "${LTS_AND_SYSTEM_COLOR}")$(nvm_wrap_with_color_code "${CURRENT_COLOR}" "${CURRENT_COLOR}")$(nvm_wrap_with_color_code "${NOT_INSTALLED_COLOR}" "${NOT_INSTALLED_COLOR}")$(nvm_wrap_with_color_code "${DEFAULT_COLOR}" "${DEFAULT_COLOR}")"
fi
export NVM_COLORS="$1"
else
return 17
fi
}
nvm_get_colors() {
local COLOR
local SYS_COLOR
local COLORS
COLORS="${NVM_COLORS:-bygre}"
case $1 in
1) COLOR=$(nvm_print_color_code "$(echo "$COLORS" | awk '{ print substr($0, 1, 1); }')");;
2) COLOR=$(nvm_print_color_code "$(echo "$COLORS" | awk '{ print substr($0, 2, 1); }')");;
3) COLOR=$(nvm_print_color_code "$(echo "$COLORS" | awk '{ print substr($0, 3, 1); }')");;
4) COLOR=$(nvm_print_color_code "$(echo "$COLORS" | awk '{ print substr($0, 4, 1); }')");;
5) COLOR=$(nvm_print_color_code "$(echo "$COLORS" | awk '{ print substr($0, 5, 1); }')");;
6)
SYS_COLOR=$(nvm_print_color_code "$(echo "$COLORS" | awk '{ print substr($0, 2, 1); }')")
COLOR=$(nvm_echo "$SYS_COLOR" | command tr '0;' '1;')
;;
*)
nvm_err "Invalid color index, ${1-}"
return 1
;;
esac
nvm_echo "$COLOR"
}
nvm_wrap_with_color_code() {
local CODE
CODE="$(nvm_print_color_code "${1}" 2>/dev/null ||:)"
local TEXT
TEXT="${2-}"
# `nvm_has_colors` cannot answer for itself inside a command substitution,
# where `[ -t 1 ]` sees the capture pipe: callers that already checked pass
# the answer in, as `nvm_print_alias_path` also accepts it.
if { [ "${NVM_HAS_COLORS-}" = 1 ] || nvm_has_colors; } && [ -n "${CODE}" ]; then
nvm_echo_with_colors "\033[${CODE}${TEXT}\033[0m"
else
nvm_echo "${TEXT}"
fi
}
nvm_print_color_legend() {
# Every line below builds its text in a command substitution, which cannot
# detect color support itself, so resolve it once here. `local` matters:
# leaking the flag would override `--no-colors` for every later call.
local NVM_HAS_COLORS
NVM_HAS_COLORS=0
if nvm_has_colors; then
NVM_HAS_COLORS=1
fi
nvm_echo ' Initial colors are:'
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'b' 'b')$(nvm_wrap_with_color_code 'y' 'y')$(nvm_wrap_with_color_code 'g' 'g')$(nvm_wrap_with_color_code 'r' 'r')$(nvm_wrap_with_color_code 'e' 'e')"
nvm_echo ' Color codes:'
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'r' 'r')/$(nvm_wrap_with_color_code 'R' 'R') = $(nvm_wrap_with_color_code 'r' 'red') / $(nvm_wrap_with_color_code 'R' 'bold red')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'g' 'g')/$(nvm_wrap_with_color_code 'G' 'G') = $(nvm_wrap_with_color_code 'g' 'green') / $(nvm_wrap_with_color_code 'G' 'bold green')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'b' 'b')/$(nvm_wrap_with_color_code 'B' 'B') = $(nvm_wrap_with_color_code 'b' 'blue') / $(nvm_wrap_with_color_code 'B' 'bold blue')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'c' 'c')/$(nvm_wrap_with_color_code 'C' 'C') = $(nvm_wrap_with_color_code 'c' 'cyan') / $(nvm_wrap_with_color_code 'C' 'bold cyan')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'm' 'm')/$(nvm_wrap_with_color_code 'M' 'M') = $(nvm_wrap_with_color_code 'm' 'magenta') / $(nvm_wrap_with_color_code 'M' 'bold magenta')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'y' 'y')/$(nvm_wrap_with_color_code 'Y' 'Y') = $(nvm_wrap_with_color_code 'y' 'yellow') / $(nvm_wrap_with_color_code 'Y' 'bold yellow')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'k' 'k')/$(nvm_wrap_with_color_code 'K' 'K') = $(nvm_wrap_with_color_code 'k' 'black') / $(nvm_wrap_with_color_code 'K' 'bold black')"
nvm_echo_with_colors " $(nvm_wrap_with_color_code 'e' 'e')/$(nvm_wrap_with_color_code 'W' 'W') = $(nvm_wrap_with_color_code 'e' 'light grey') / $(nvm_wrap_with_color_code 'W' 'white')"
}
nvm_print_color_code() {
case "${1-}" in
'0') return 0 ;;
'r') nvm_echo '0;31m' ;;
'R') nvm_echo '1;31m' ;;
'g') nvm_echo '0;32m' ;;
'G') nvm_echo '1;32m' ;;
'b') nvm_echo '0;34m' ;;
'B') nvm_echo '1;34m' ;;
'c') nvm_echo '0;36m' ;;
'C') nvm_echo '1;36m' ;;
'm') nvm_echo '0;35m' ;;
'M') nvm_echo '1;35m' ;;
'y') nvm_echo '0;33m' ;;
'Y') nvm_echo '1;33m' ;;
'k') nvm_echo '0;30m' ;;
'K') nvm_echo '1;30m' ;;
'e') nvm_echo '0;37m' ;;
'W') nvm_echo '1;37m' ;;
*)
nvm_err "Invalid color code: ${1-}";
return 1
;;
esac
}
nvm_print_formatted_alias() {
local ALIAS
ALIAS="${1-}"
local DEST
DEST="${2-}"
local VERSION
VERSION="${3-}"
if [ -z "${VERSION}" ]; then
VERSION="$(nvm_version "${DEST}")" ||:
fi
local VERSION_FORMAT
local ALIAS_FORMAT
local DEST_FORMAT
local INSTALLED_COLOR
local SYSTEM_COLOR
local CURRENT_COLOR
local NOT_INSTALLED_COLOR
local DEFAULT_COLOR
local LTS_COLOR
INSTALLED_COLOR=$(nvm_get_colors 1)
SYSTEM_COLOR=$(nvm_get_colors 2)
CURRENT_COLOR=$(nvm_get_colors 3)
NOT_INSTALLED_COLOR=$(nvm_get_colors 4)
DEFAULT_COLOR=$(nvm_get_colors 5)
LTS_COLOR=$(nvm_get_colors 6)
ALIAS_FORMAT='%s'
DEST_FORMAT='%s'
VERSION_FORMAT='%s'
local NEWLINE
NEWLINE='\n'
if [ "_${DEFAULT}" = '_true' ]; then
NEWLINE=' (default)\n'
fi
local ARROW
ARROW='->'
if [ "${NVM_HAS_COLORS-}" = 1 ] || nvm_has_colors; then
ARROW='\033[0;90m->\033[0m'
if [ "_${DEFAULT}" = '_true' ]; then
NEWLINE=" \033[${DEFAULT_COLOR}(default)\033[0m\n"
fi
if [ "_${VERSION}" = "_${NVM_CURRENT-}" ]; then
ALIAS_FORMAT="\033[${CURRENT_COLOR}%s\033[0m"
DEST_FORMAT="\033[${CURRENT_COLOR}%s\033[0m"
VERSION_FORMAT="\033[${CURRENT_COLOR}%s\033[0m"
elif nvm_is_version_installed "${VERSION}"; then
ALIAS_FORMAT="\033[${INSTALLED_COLOR}%s\033[0m"
DEST_FORMAT="\033[${INSTALLED_COLOR}%s\033[0m"
VERSION_FORMAT="\033[${INSTALLED_COLOR}%s\033[0m"
elif [ "${VERSION}" = '∞' ] || [ "${VERSION}" = 'N/A' ]; then
ALIAS_FORMAT="\033[${NOT_INSTALLED_COLOR}%s\033[0m"
DEST_FORMAT="\033[${NOT_INSTALLED_COLOR}%s\033[0m"
VERSION_FORMAT="\033[${NOT_INSTALLED_COLOR}%s\033[0m"
fi
if [ "_${NVM_LTS-}" = '_true' ]; then
ALIAS_FORMAT="\033[${LTS_COLOR}%s\033[0m"
fi
if [ "_${DEST%/*}" = "_lts" ]; then
DEST_FORMAT="\033[${LTS_COLOR}%s\033[0m"
fi
elif [ "_${VERSION}" != '_∞' ] && [ "_${VERSION}" != '_N/A' ]; then
VERSION_FORMAT='%s *'
fi
if [ "${DEST}" = "${VERSION}" ]; then
command printf -- "${ALIAS_FORMAT} ${ARROW} ${VERSION_FORMAT}${NEWLINE}" "${ALIAS}" "${DEST}"
else
command printf -- "${ALIAS_FORMAT} ${ARROW} ${DEST_FORMAT} (${ARROW} ${VERSION_FORMAT})${NEWLINE}" "${ALIAS}" "${DEST}" "${VERSION}"
fi
}
nvm_print_alias_path() {
local NVM_ALIAS_DIR
NVM_ALIAS_DIR="${1-}"
if [ -z "${NVM_ALIAS_DIR}" ]; then
nvm_err 'An alias dir is required.'
return 1
fi
local ALIAS_PATH
ALIAS_PATH="${2-}"
if [ -z "${ALIAS_PATH}" ]; then
nvm_err 'An alias path is required.'
return 2
fi
local ALIAS
ALIAS="${ALIAS_PATH##"${NVM_ALIAS_DIR}"\/}"
local DEST
DEST="$(nvm_alias "${ALIAS}" 2>/dev/null)" ||:
if [ -n "${DEST}" ]; then
NVM_NO_COLORS="${NVM_NO_COLORS-}" NVM_LTS="${NVM_LTS-}" DEFAULT=false nvm_print_formatted_alias "${ALIAS}" "${DEST}"
fi
}
nvm_print_default_alias() {
local ALIAS
ALIAS="${1-}"
if [ -z "${ALIAS}" ]; then
nvm_err 'A default alias is required.'
return 1
fi
local DEST
DEST="$(nvm_print_implicit_alias local "${ALIAS}")"
if [ -n "${DEST}" ]; then
NVM_NO_COLORS="${NVM_NO_COLORS-}" DEFAULT=true nvm_print_formatted_alias "${ALIAS}" "${DEST}"
fi
}
nvm_make_alias() {
local ALIAS
ALIAS="${1-}"
if [ -z "${ALIAS}" ]; then
nvm_err "an alias name is required"
return 1
fi
local VERSION
VERSION="${2-}"
if [ -z "${VERSION}" ]; then
nvm_err "an alias target version is required"
return 2
fi
# slashes are legal (eg `lts/iron`), but a `..` component would escape the alias dir
case "/${ALIAS}/" in
*/../*)
nvm_err "invalid alias name: ${ALIAS}"
return 3
;;
esac
nvm_echo "${VERSION}" | tee "$(nvm_alias_path)/${ALIAS}" >/dev/null
}
nvm_list_aliases() {
local ALIAS
ALIAS="${1-}"
local NVM_CURRENT
NVM_CURRENT="$(nvm_ls_current)"
local NVM_ALIAS_DIR
NVM_ALIAS_DIR="$(nvm_alias_path)"
command mkdir -p "${NVM_ALIAS_DIR}/lts"
if [ "${ALIAS}" != "${ALIAS#lts/}" ]; then
nvm_alias "${ALIAS}"
return $?
fi
local NVM_HAS_COLORS
NVM_HAS_COLORS=0
if nvm_has_colors; then
NVM_HAS_COLORS=1
fi
nvm_is_zsh && setopt local_options nonomatch
(
local ALIAS_PATH
# background jobs are explicit subshells: bash 3.2 otherwise drops output from nested `command` calls in them
for ALIAS_PATH in "${NVM_ALIAS_DIR}/${ALIAS}"*; do
(NVM_NO_COLORS="${NVM_NO_COLORS-}" NVM_HAS_COLORS="${NVM_HAS_COLORS}" NVM_CURRENT="${NVM_CURRENT}" nvm_print_alias_path "${NVM_ALIAS_DIR}" "${ALIAS_PATH}") &
done
wait
) | command sort
(
local ALIAS_NAME
for ALIAS_NAME in "$(nvm_node_prefix)" "stable" "unstable" "$(nvm_iojs_prefix)"; do
(
# shellcheck disable=SC2030,SC2031 # (https://github.com/koalaman/shellcheck/issues/2217)
if [ ! -f "${NVM_ALIAS_DIR}/${ALIAS_NAME}" ] && { [ -z "${ALIAS}" ] || [ "${ALIAS_NAME}" = "${ALIAS}" ]; }; then
NVM_NO_COLORS="${NVM_NO_COLORS-}" NVM_HAS_COLORS="${NVM_HAS_COLORS}" NVM_CURRENT="${NVM_CURRENT}" nvm_print_default_alias "${ALIAS_NAME}"
fi
) &
done
wait
) | command sort
(
local LTS_ALIAS
# shellcheck disable=SC2030,SC2031 # (https://github.com/koalaman/shellcheck/issues/2217)
for ALIAS_PATH in "${NVM_ALIAS_DIR}/lts/${ALIAS}"*; do
(
LTS_ALIAS="$(NVM_NO_COLORS="${NVM_NO_COLORS-}" NVM_HAS_COLORS="${NVM_HAS_COLORS}" NVM_LTS=true nvm_print_alias_path "${NVM_ALIAS_DIR}" "${ALIAS_PATH}")"
if [ -n "${LTS_ALIAS}" ]; then
nvm_echo "${LTS_ALIAS}"
fi
) &
done
wait
) | command sort
return
}
nvm_print_alias_file() {
# a `#` pattern is a repetition operator under zsh's `extendedglob`, so it is
# unset for the length of this function and restored by `local_options`
nvm_is_zsh && setopt local_options noextendedglob
local NVM_ALIAS_LINE
while IFS= read -r NVM_ALIAS_LINE || [ -n "${NVM_ALIAS_LINE}" ]; do
NVM_ALIAS_LINE="${NVM_ALIAS_LINE%%#*}"
case "${NVM_ALIAS_LINE}" in
*[![:space:]]*) ;;
*) continue ;;
esac
NVM_ALIAS_LINE="${NVM_ALIAS_LINE%"${NVM_ALIAS_LINE##*[![:space:]]}"}"
nvm_echo "${NVM_ALIAS_LINE}"
done < "$1"
}
nvm_alias() {
local ALIAS
ALIAS="${1-}"
if [ -z "${ALIAS}" ]; then
nvm_err 'An alias is required.'
return 1
fi
ALIAS="$(nvm_normalize_lts "${ALIAS}")" || return $?
if [ -z "${ALIAS}" ]; then
return 2
fi
# slashes are legal (eg `lts/iron`), but a `..` component would read outside
# the alias dir; `nvm_make_alias` rejects the same shape on the write side
case "/${ALIAS}/" in
*/../*)
nvm_err "invalid alias name: ${ALIAS}"
return 3
;;
esac
local NVM_ALIAS_PATH
NVM_ALIAS_PATH="$(nvm_alias_path)/${ALIAS}"
if [ ! -f "${NVM_ALIAS_PATH}" ]; then
nvm_err 'Alias does not exist.'
return 2
fi
if [ ! -r "${NVM_ALIAS_PATH}" ]; then
# an existing-but-unreadable alias file yields empty output with a success
# status - a nonzero status here would make `nvm_ensure_default_set`
# overwrite an existing default alias it merely could not read
nvm_err "Alias file is not readable: ${NVM_ALIAS_PATH}"
return 0
fi
nvm_print_alias_file "${NVM_ALIAS_PATH}"
}
nvm_ls_current() {
local NVM_LS_CURRENT_NODE_PATH
if ! NVM_LS_CURRENT_NODE_PATH="$(command which node 2>/dev/null)"; then
nvm_echo 'none'
elif nvm_tree_contains_path "$(nvm_version_dir iojs)" "${NVM_LS_CURRENT_NODE_PATH}"; then
nvm_add_iojs_prefix "$(iojs --version 2>/dev/null)"
elif nvm_tree_contains_path "${NVM_DIR}" "${NVM_LS_CURRENT_NODE_PATH}"; then
local VERSION
VERSION="$(node --version 2>/dev/null)"
if [ "${VERSION}" = "v0.6.21-pre" ]; then
nvm_echo 'v0.6.21'
else
nvm_echo "${VERSION:-none}"
fi
else
nvm_echo 'system'
fi
}
nvm_resolve_alias() {
if [ -z "${1-}" ]; then
return 1
fi
local PATTERN
PATTERN="${1-}"
local ALIAS
ALIAS="${PATTERN}"
local ALIAS_TEMP
local ALIAS_OUTPUT
# flags stored in an alias, like `--lts`, precede its target; the outermost alias's apply
local ALIAS_FLAGS
ALIAS_FLAGS=''
local ALIAS_TEMP_FLAGS
local SEEN_ALIASES
SEEN_ALIASES="
${ALIAS}
"
while true; do
ALIAS_OUTPUT="$(nvm_alias "${ALIAS}" 2>/dev/null)" || ALIAS_OUTPUT=''
ALIAS_TEMP="${ALIAS_OUTPUT%%
*}"
ALIAS_TEMP_FLAGS=''
while :; do
case "${ALIAS_TEMP}" in
--*' '*)
ALIAS_TEMP_FLAGS="${ALIAS_TEMP_FLAGS:+${ALIAS_TEMP_FLAGS} }${ALIAS_TEMP%% *}"
ALIAS_TEMP="${ALIAS_TEMP#* }"
;;
*) break ;;
esac
done
if [ -z "${ALIAS_FLAGS}" ]; then
ALIAS_FLAGS="${ALIAS_TEMP_FLAGS}"
fi
if [ -z "${ALIAS_TEMP}" ]; then
break
fi
case "${SEEN_ALIASES}" in
*"
${ALIAS_TEMP}
"*)
ALIAS="∞"
break
;;
esac
SEEN_ALIASES="${SEEN_ALIASES}${ALIAS_TEMP}
"
ALIAS="${ALIAS_TEMP}"
done
if [ -n "${ALIAS}" ] && [ "_${ALIAS}" != "_${PATTERN}" ]; then
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
case "${ALIAS}" in
'∞')
nvm_echo "${ALIAS}"
;;
"${NVM_IOJS_PREFIX}" | "${NVM_IOJS_PREFIX}-" | \
"${NVM_NODE_PREFIX}")
nvm_echo "${ALIAS_FLAGS:+${ALIAS_FLAGS} }${ALIAS}"
;;
*)
nvm_echo "${ALIAS_FLAGS:+${ALIAS_FLAGS} }$(nvm_ensure_version_prefix "${ALIAS}")"
;;
esac
return 0
fi
if nvm_validate_implicit_alias "${PATTERN}" 2>/dev/null; then
local IMPLICIT
IMPLICIT="$(nvm_print_implicit_alias local "${PATTERN}" 2>/dev/null)"
if [ -n "${IMPLICIT}" ]; then
nvm_ensure_version_prefix "${IMPLICIT}"
fi
fi
return 2
}
nvm_resolve_local_alias() {
if [ -z "${1-}" ]; then
return 1
fi
local VERSION
local EXIT_CODE
VERSION="$(nvm_resolve_alias "${1-}")"
EXIT_CODE=$?
if [ -z "${VERSION}" ]; then
return $EXIT_CODE
fi
if [ "_${VERSION}" = '_∞' ]; then
nvm_echo "${VERSION}"
return
fi
# Fast path: an exact, installed vX.Y.Z needs no further resolution.
if nvm_is_installed_exact_version "${VERSION}"; then
nvm_echo "${VERSION}"
return
fi
nvm_version "${VERSION}"
}
nvm_iojs_prefix() {
nvm_echo 'iojs'
}
nvm_node_prefix() {
nvm_echo 'node'
}
nvm_is_iojs_version() {
case "${1-}" in iojs-*) return 0 ;; esac
return 1
}
nvm_add_iojs_prefix() {
nvm_echo "$(nvm_iojs_prefix)-$(nvm_ensure_version_prefix "$(nvm_strip_iojs_prefix "${1-}")")"
}
nvm_strip_iojs_prefix() {
case "${1-}" in
"iojs") nvm_echo ;;
*) nvm_echo "${1#iojs-}" ;;
esac
}
# vN.0.0-alpha.X.Y.Z
nvm_is_alpha_version() {
local NVM_ALPHA_VERSION
NVM_ALPHA_VERSION="${1#v}"
case "${NVM_ALPHA_VERSION}" in
*-alpha.*) ;;
*) return 1 ;;
esac
local NVM_ALPHA_PART
for NVM_ALPHA_PART in "${NVM_ALPHA_VERSION%%-alpha.*}" "${NVM_ALPHA_VERSION#*-alpha.}"; do
case "${NVM_ALPHA_PART}" in
*[!0-9.]* | .* | *. | *..* | *.*.*.*) return 1 ;;
*.*.*) ;;
*) return 1 ;;
esac
done
}
# args: comma-separated version categories, where they came from (for errors)
nvm_normalize_only() {
local NVM_ONLY_VALUE
NVM_ONLY_VALUE="${1-}"
local NVM_ONLY_SOURCE
NVM_ONLY_SOURCE="${2-}"
local NVM_ONLY_REST
NVM_ONLY_REST=",${NVM_ONLY_VALUE},"
local NVM_ONLY_RESULT
NVM_ONLY_RESULT=''
local NVM_ONLY_CATEGORY
case "${NVM_ONLY_VALUE}" in
'' | ,* | *, | *,,*) NVM_ONLY_REST='' ;;
esac
for NVM_ONLY_CATEGORY in alpha lts non-lts iojs; do
case "${NVM_ONLY_REST}" in
*",${NVM_ONLY_CATEGORY},"*) NVM_ONLY_RESULT="${NVM_ONLY_RESULT:+${NVM_ONLY_RESULT},}${NVM_ONLY_CATEGORY}" ;;
esac
while :; do
case "${NVM_ONLY_REST}" in
*",${NVM_ONLY_CATEGORY},"*) NVM_ONLY_REST="${NVM_ONLY_REST%%,"${NVM_ONLY_CATEGORY}",*},${NVM_ONLY_REST#*,"${NVM_ONLY_CATEGORY}",}" ;;
*) break ;;
esac
done
done
if [ "${NVM_ONLY_REST}" != ',' ]; then
nvm_err "Invalid ${NVM_ONLY_SOURCE} value \"${NVM_ONLY_VALUE}\": it must be a comma-separated list of any of: alpha, lts, non-lts, iojs"
return 55
fi
nvm_echo "${NVM_ONLY_RESULT}"
}
# args: how many times `--only=` was provided, its value, the LTS selection in effect (if any)
# Prints the version categories to select from: the `--only=` value if provided, else
# those of an enclosing `nvm` command, else `$NVM_ONLY`, else every category but alpha.
# An LTS selection, like `--lts`, picks versions through `lts/` aliases, whose targets
# are LTS, so it needs no recorded LTS status; it can't combine with an `--only=` that
# excludes LTS versions.
nvm_resolve_only() {
local NVM_ONLY_RESOLVED
if [ "${1:-0}" -gt 1 ]; then
nvm_err '`--only` may only be provided once.'
return 55
elif [ "${1-}" = 1 ]; then
NVM_ONLY_RESOLVED="$(nvm_normalize_only "${2-}" '`--only`')" || return
elif [ -n "${NVM_ONLY_SELECTED-}" ]; then
# the enclosing command has already resolved, and recorded LTS status if needed
nvm_echo "${NVM_ONLY_SELECTED}"
return
elif [ -n "${NVM_ONLY-}" ]; then
NVM_ONLY_RESOLVED="$(nvm_normalize_only "${NVM_ONLY}" '`$NVM_ONLY`')" || return
else
NVM_ONLY_RESOLVED='lts,non-lts,iojs'
fi
if [ -n "${3-}" ]; then
case ",${NVM_ONLY_RESOLVED}," in
*,lts,*) ;;
*)
if [ "${1-}" = 1 ]; then
nvm_err "\`--only=${2-}\` excludes LTS versions, so it cannot be combined with an LTS selection like \`--lts\`."
return 55
fi
;;
esac
NVM_ONLY_RESOLVED='lts,non-lts'
fi
# commands that download index.tab themselves record LTS status as they do
if [ -z "${NVM_NO_LTS_STATUS-}" ] && nvm_needs_lts_status "${NVM_ONLY_RESOLVED}" && ! nvm_ensure_lts_status; then
nvm_err 'The LTS status of installed versions is not recorded yet; run `nvm ls-remote` to record it.'
return 3
fi
nvm_echo "${NVM_ONLY_RESOLVED}"
}
# args: a version read from .nvmrc
# An `lts/` version is an LTS selection, like `--lts`; this updates the enclosing
# `nvm` command's NVM_LTS_REQUEST and NVM_ONLY_SELECTED to match.
nvm_select_lts_from_nvmrc() {
case "${1-}" in
lts/*) ;;
*) return 0 ;;
esac
local NVM_ONLY_LTS
NVM_ONLY_LTS="$(NVM_ONLY_SELECTED='' nvm_resolve_only "${NVM_ONLY_FLAG_COUNT-}" "${NVM_ONLY_FLAG-}" '*')" || return
NVM_ONLY_SELECTED="${NVM_ONLY_LTS}"
NVM_LTS_REQUEST='*'
}
# assumes the categories have been normalized by `nvm_resolve_only`
nvm_only_includes() {
case ",${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}}," in
*",${1-},"*) return 0 ;;
esac
return 1
}
# args: categories
# Telling LTS from non-LTS versions apart needs their recorded LTS status.
nvm_needs_lts_status() {
case ",${1-}," in
*,lts,*)
case ",${1-}," in
*,non-lts,*) return 1 ;;
esac
;;
*,non-lts,*) ;;
*) return 1 ;;
esac
}
# Filters `nvm_ls`-style version lines on stdin down to the selected categories.
nvm_filter_installed_versions() {
local NVM_NEEDS_LTS_STATUS
NVM_NEEDS_LTS_STATUS=0
if nvm_needs_lts_status "${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}}"; then
NVM_NEEDS_LTS_STATUS=1
if [ ! -f "$(nvm_lts_status_path)" ]; then
nvm_err 'The LTS status of installed versions is not recorded yet; run `nvm ls-remote` to record it.'
return 3
fi
fi
NVM_LTS_STATUS_PATH="$(nvm_lts_status_path)" command awk \
-v only=",${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}}," \
-v needs_lts_status="${NVM_NEEDS_LTS_STATUS}" '
BEGIN {
if (needs_lts_status) {
record = ENVIRON["NVM_LTS_STATUS_PATH"];
while ((getline line < record) > 0) {
split(line, fields, " ");
lts[fields[1]] = fields[2];
}
}
}
{
if ($1 == "system" || $1 == "N/A") { print; next }
if ($1 ~ /^iojs-/) { category = "iojs" }
else if ($1 ~ /^v[0-9]+\.[0-9]+\.[0-9]+-alpha\.[0-9]+\.[0-9]+\.[0-9]+$/) { category = "alpha" }
else if (!needs_lts_status) { category = index(only, ",lts,") ? "lts" : "non-lts" }
else { category = (($1 in lts) && lts[$1] != "-") ? "lts" : "non-lts" }
if (index(only, "," category ",")) { print }
}'
}
# args: version
nvm_is_version_selected() {
case "${1-}" in
system) return 0 ;;
iojs-*)
nvm_only_includes iojs
return
;;
esac
if nvm_is_alpha_version "${1-}"; then
nvm_only_includes alpha
return
fi
if ! nvm_needs_lts_status "${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}}"; then
nvm_only_includes lts
return
fi
[ -n "$(nvm_echo "${1-}" | nvm_filter_installed_versions)" ]
}
# Sorts version lines, keyed on their first field, which may end in `.node` or `.iojs`,
# by semver precedence: prereleases come before their release, and their numeric
# identifiers compare as numbers, so `v24.0.0-rc.2` comes before `v24.0.0-rc.10`.
# With an argument of `1`, prereleases other than alphas, like nightlies, collapse
# into one line per release.
nvm_sort_versions() {
command awk -v collapse="${1-}" '{
version = $1;
sub(/\.(node|iojs)$/, "", version);
sub(/^(iojs-)?v/, "", version);
prerelease = "~";
dash = index(version, "-");
if (dash) {
count = split(substr(version, dash + 1), identifiers, ".");
prerelease = "";
for (i = 1; i <= count; i++) {
identifier = identifiers[i];
if (identifier ~ /^[0-9]+$/) {
sub(/^0+/, "", identifier);
while (length(identifier) < 20) { identifier = "0" identifier }
identifier = "0" identifier;
} else {
identifier = "1" identifier;
}
prerelease = prerelease identifier "!";
}
if (collapse && version !~ /^[0-9]+\.[0-9]+\.[0-9]+-alpha\.[0-9]+\.[0-9]+\.[0-9]+$/) { prerelease = "0" }
version = substr(version, 1, dash - 1);
}
split(version, parts, ".");
printf "%d %d %d %s\t%s\n", parts[1], parts[2], parts[3], prerelease, $0;
}' | if [ "${1-}" = 1 ]; then
LC_ALL=C command sort -u -k 1,1n -k 2,2n -k 3,3n -k 4,4 | command cut -f 2-
else
LC_ALL=C command sort -k 1,1n -k 2,2n -k 3,3n -k 4,4 | command cut -f 2- | command uniq
fi
}
nvm_ls() {
local PATTERN
PATTERN="${1-}"
case "${PATTERN}" in
*'#'* | *'
'*)
local NVMRC_PATTERN
if ! NVMRC_PATTERN="$(nvm_process_nvmrc_content "${PATTERN}" 2>/dev/null)"; then
nvm_echo 'N/A'
return 3
fi
PATTERN="${NVMRC_PATTERN}"
;;
esac
local VERSIONS
VERSIONS=''
if [ "${PATTERN}" = 'current' ]; then
nvm_ls_current
return
fi
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
local NVM_VERSION_DIR_IOJS
NVM_VERSION_DIR_IOJS="$(nvm_version_dir "${NVM_IOJS_PREFIX}")"
local NVM_VERSION_DIR_NEW
NVM_VERSION_DIR_NEW="$(nvm_version_dir new)"
local NVM_VERSION_DIR_OLD
NVM_VERSION_DIR_OLD="$(nvm_version_dir old)"
case "${PATTERN}" in
"${NVM_IOJS_PREFIX}" | "${NVM_NODE_PREFIX}")
PATTERN="${PATTERN}-"
;;
*)
local ALIAS_TARGET
ALIAS_TARGET="$(nvm_resolve_alias "${PATTERN}" 2>/dev/null || nvm_echo)"
if [ "_${ALIAS_TARGET}" = '_system' ] && (nvm_has_system_iojs || nvm_has_system_node); then
local SYSTEM_VERSION
SYSTEM_VERSION="$(nvm deactivate >/dev/null 2>&1 && node -v 2>/dev/null)"
if [ -n "${SYSTEM_VERSION}" ]; then
nvm_echo "system ${SYSTEM_VERSION}"
else
nvm_echo "system"
fi
return
fi
if nvm_resolve_local_alias "${PATTERN}"; then
return
fi
PATTERN="$(nvm_ensure_version_prefix "${PATTERN}")"
;;
esac
if [ "${PATTERN}" = 'N/A' ]; then
return
fi
# If it looks like an explicit version, don't do anything funny
local NVM_PATTERN_STARTS_WITH_V
case $PATTERN in
v*) NVM_PATTERN_STARTS_WITH_V=true ;;
*) NVM_PATTERN_STARTS_WITH_V=false ;;
esac
local NVM_PATTERN_IS_PRERELEASE
case "${PATTERN}" in
v*-*) NVM_PATTERN_IS_PRERELEASE=true ;;
*) NVM_PATTERN_IS_PRERELEASE=false ;;
esac
if [ $NVM_PATTERN_IS_PRERELEASE = true ] && nvm_is_version_installed "${PATTERN}"; then
VERSIONS="${PATTERN}"
elif [ $NVM_PATTERN_STARTS_WITH_V = true ] && [ $NVM_PATTERN_IS_PRERELEASE = false ] && [ "_$(nvm_num_version_groups "${PATTERN}")" = "_3" ]; then
if nvm_is_version_installed "${PATTERN}"; then
VERSIONS="${PATTERN}"
elif nvm_is_version_installed "$(nvm_add_iojs_prefix "${PATTERN}")"; then
VERSIONS="$(nvm_add_iojs_prefix "${PATTERN}")"
fi
else
case "${PATTERN}" in
"${NVM_IOJS_PREFIX}-" | "${NVM_NODE_PREFIX}-" | "system") ;;
*)
local NUM_VERSION_GROUPS
NUM_VERSION_GROUPS="$(nvm_num_version_groups "${PATTERN}")"
if [ "${NUM_VERSION_GROUPS}" = "2" ] || [ "${NUM_VERSION_GROUPS}" = "1" ]; then
PATTERN="${PATTERN%.}."
fi
;;
esac
nvm_is_zsh && setopt local_options shwordsplit
nvm_is_zsh && setopt local_options nomarkdirs
local NVM_DIRS_TO_SEARCH1
NVM_DIRS_TO_SEARCH1=''
local NVM_DIRS_TO_SEARCH2
NVM_DIRS_TO_SEARCH2=''
local NVM_DIRS_TO_SEARCH3
NVM_DIRS_TO_SEARCH3=''
local NVM_ADD_SYSTEM
NVM_ADD_SYSTEM=false
if nvm_is_iojs_version "${PATTERN}"; then
NVM_DIRS_TO_SEARCH1="${NVM_VERSION_DIR_IOJS}"
PATTERN="$(nvm_strip_iojs_prefix "${PATTERN}")"
if nvm_has_system_iojs; then
NVM_ADD_SYSTEM=true
fi
elif [ "${PATTERN}" = "${NVM_NODE_PREFIX}-" ]; then
NVM_DIRS_TO_SEARCH1="${NVM_VERSION_DIR_OLD}"
NVM_DIRS_TO_SEARCH2="${NVM_VERSION_DIR_NEW}"
PATTERN=''
if nvm_has_system_node; then
NVM_ADD_SYSTEM=true
fi
else
NVM_DIRS_TO_SEARCH1="${NVM_VERSION_DIR_OLD}"
NVM_DIRS_TO_SEARCH2="${NVM_VERSION_DIR_NEW}"
NVM_DIRS_TO_SEARCH3="${NVM_VERSION_DIR_IOJS}"
if nvm_has_system_iojs || nvm_has_system_node; then
NVM_ADD_SYSTEM=true
fi
fi
if ! [ -d "${NVM_DIRS_TO_SEARCH1}" ] || ! (command ls -1qA "${NVM_DIRS_TO_SEARCH1}" | nvm_grep -q .); then
NVM_DIRS_TO_SEARCH1=''
fi
if ! [ -d "${NVM_DIRS_TO_SEARCH2}" ] || ! (command ls -1qA "${NVM_DIRS_TO_SEARCH2}" | nvm_grep -q .); then
NVM_DIRS_TO_SEARCH2="${NVM_DIRS_TO_SEARCH1}"
fi
if ! [ -d "${NVM_DIRS_TO_SEARCH3}" ] || ! (command ls -1qA "${NVM_DIRS_TO_SEARCH3}" | nvm_grep -q .); then
NVM_DIRS_TO_SEARCH3="${NVM_DIRS_TO_SEARCH2}"
fi
local SEARCH_PATTERN
if [ -z "${PATTERN}" ]; then
PATTERN='v'
SEARCH_PATTERN='.*'
else
SEARCH_PATTERN="$(nvm_echo "${PATTERN}" | command sed 's/[[\.*^$#]/\\&/g')"
fi
# a partial prerelease must end at a `.`, so `v24.0.0-rc.1` does not match `v24.0.0-rc.10`
local NVM_PRERELEASE_PATTERN
NVM_PRERELEASE_PATTERN=''
case "${PATTERN}" in
*-*) NVM_PRERELEASE_PATTERN="${PATTERN}" ;;
esac
if [ -n "${NVM_DIRS_TO_SEARCH1}${NVM_DIRS_TO_SEARCH2}${NVM_DIRS_TO_SEARCH3}" ]; then
# the directories are matched literally, so escape characters that are special in sed
local NVM_DIR_SED
NVM_DIR_SED="$(nvm_echo "${NVM_DIR}" | command sed 's/[][\.*^$#]/\\&/g')"
local NVM_VERSION_DIR_IOJS_SED
NVM_VERSION_DIR_IOJS_SED="$(nvm_echo "${NVM_VERSION_DIR_IOJS}" | command sed 's/[][\.*^$#]/\\&/g')"
VERSIONS="$(command find "${NVM_DIRS_TO_SEARCH1}"/* "${NVM_DIRS_TO_SEARCH2}"/* "${NVM_DIRS_TO_SEARCH3}"/* -name . -o -type d -prune -o -path "${PATTERN}*" \
| command sed -e "
s#${NVM_VERSION_DIR_IOJS_SED}/#versions/${NVM_IOJS_PREFIX}/#;
s#^${NVM_DIR_SED}/##;
\\#^[^v]# d;
\\#^versions\$# d;
s#^versions/##;
s#^v#${NVM_NODE_PREFIX}/v#;
\\#${SEARCH_PATTERN}# !d;
" \
-e 's#^\([^/]\{1,\}\)/\(.*\)$#\2.\1#;' \
| nvm_sort_versions \
| command sed -e 's#\(.*\)\.\([^\.]\{1,\}\)$#\2-\1#;' \
-e "s#^${NVM_NODE_PREFIX}-##;" \
)"
if [ -n "${NVM_PRERELEASE_PATTERN}" ] && [ -n "${VERSIONS}" ]; then
VERSIONS="$(nvm_echo "${VERSIONS}" | command awk -v pattern="${NVM_PRERELEASE_PATTERN}" '{
position = index($0, pattern);
if (!position) { next }
rest = substr($0, position + length(pattern));
if (rest == "" || substr(rest, 1, 1) == ".") { print }
}')"
fi
fi
fi
# filtering is only needed when a selected category leaves out some of these versions
local NVM_FILTER_VERSIONS
NVM_FILTER_VERSIONS=true
if nvm_only_includes lts && nvm_only_includes non-lts; then
NVM_FILTER_VERSIONS=false
case "${VERSIONS}" in
*-alpha.*) nvm_only_includes alpha || NVM_FILTER_VERSIONS=true ;;
esac
case "${VERSIONS}" in
*iojs-*) nvm_only_includes iojs || NVM_FILTER_VERSIONS=true ;;
esac
fi
if [ -n "${VERSIONS}" ] && [ "${NVM_FILTER_VERSIONS}" = true ]; then
VERSIONS="$(nvm_echo "${VERSIONS}" | nvm_filter_installed_versions)"
fi
if [ "${NVM_ADD_SYSTEM-}" = true ]; then
local SYSTEM_VERSION
SYSTEM_VERSION="$(nvm deactivate >/dev/null 2>&1 && node -v 2>/dev/null)"
case "${PATTERN}" in
'' | v)
if [ -n "${SYSTEM_VERSION}" ]; then
VERSIONS="${VERSIONS:+${VERSIONS}
}system ${SYSTEM_VERSION}"
else
VERSIONS="${VERSIONS:+${VERSIONS}
}system"
fi
;;
system)
if [ -n "${SYSTEM_VERSION}" ]; then
VERSIONS="system ${SYSTEM_VERSION}"
else
VERSIONS="system"
fi
;;
esac
fi
if [ -z "${VERSIONS}" ]; then
nvm_echo 'N/A'
return 3
fi
nvm_echo "${VERSIONS}"
}
nvm_ls_remote() {
local PATTERN
PATTERN="${1-}"
if nvm_validate_implicit_alias "${PATTERN}" 2>/dev/null ; then
local IMPLICIT
IMPLICIT="$(nvm_print_implicit_alias remote "${PATTERN}")"
if [ -z "${IMPLICIT-}" ] || [ "${IMPLICIT}" = 'N/A' ]; then
nvm_echo "N/A"
return 3
fi
PATTERN="$(NVM_LTS="${NVM_LTS-}" nvm_ls_remote "${IMPLICIT}" | command tail -1 | command awk '{ print $1 }')"
elif [ -n "${PATTERN}" ]; then
PATTERN="$(nvm_ensure_version_prefix "${PATTERN}")"
else
PATTERN=".*"
fi
NVM_LTS="${NVM_LTS-}" nvm_ls_remote_index_tab node std "${PATTERN}"
}
nvm_ls_remote_iojs() {
NVM_LTS="${NVM_LTS-}" nvm_ls_remote_index_tab iojs std "${1-}"
}
# Every node version's LTS codename, or `-` when it isn't LTS, as of the latest index.tab
# that listed it. Versions it doesn't list have never been in an index.tab, so aren't LTS.
nvm_lts_status_path() {
nvm_echo "${NVM_DIR}/.lts-status"
}
# Records LTS status from node index.tab rows on stdin, keeping versions they don't list.
# Only rows that include an LTS version, unlike a nightly or release candidate index,
# can start the record, since every version they don't list counts as not LTS.
nvm_record_lts_status() {
local NVM_LTS_STATUS_PATH
NVM_LTS_STATUS_PATH="$(nvm_lts_status_path)"
local NVM_LTS_STATUS_TMP
NVM_LTS_STATUS_TMP="$(command mktemp "${NVM_LTS_STATUS_PATH}.XXXXXX" 2>/dev/null)" || return 1
# anything without a full row, like an error page, is not an index
if NVM_LTS_STATUS_PATH="${NVM_LTS_STATUS_PATH}" command awk '
BEGIN { previous = ENVIRON["NVM_LTS_STATUS_PATH"] }
NF >= 10 && $1 ~ /^v[0-9]+\.[0-9]+\.[0-9]+/ {
if (!($1 in lts)) { versions[++rows] = $1 }
lts[$1] = ($10 ~ /^-?$/ ? "-" : tolower($10));
if (lts[$1] != "-") { has_lts = 1 }
}
END {
if (!rows) { exit 1 }
if (!has_lts && (getline line < previous) <= 0) { exit 1 }
close(previous);
while ((getline line < previous) > 0) {
split(line, fields, " ");
if (!(fields[1] in lts)) { print fields[1], fields[2] }
}
for (i = 1; i <= rows; i++) { print versions[i], lts[versions[i]] }
}
' > "${NVM_LTS_STATUS_TMP}"; then
command mv -f "${NVM_LTS_STATUS_TMP}" "${NVM_LTS_STATUS_PATH}" 2>/dev/null && return 0
fi
command rm -f "${NVM_LTS_STATUS_TMP}"
return 1
}
# Versions installed before LTS status was recorded need one download of index.tab.
nvm_ensure_lts_status() {
if [ -f "$(nvm_lts_status_path)" ]; then
return 0
elif [ "${NVM_OFFLINE-}" = 1 ] || [ -n "${NVM_INDEX_NO_FETCH-}" ]; then
return 3
fi
NVM_LTS='' nvm_ls_remote_index_tab node std '' >/dev/null 2>&1
[ -f "$(nvm_lts_status_path)" ]
}
# args: an LTS codename, or `*` for any
# Keeps the version lines on stdin whose recorded LTS status matches.
nvm_filter_lts_versions() {
if ! nvm_ensure_lts_status; then
nvm_err 'The LTS status of installed versions is not recorded yet; run `nvm ls-remote` to record it.'
return 3
fi
NVM_LTS_STATUS_PATH="$(nvm_lts_status_path)" command awk -v lts="${1-}" '
BEGIN {
record = ENVIRON["NVM_LTS_STATUS_PATH"];
while ((getline line < record) > 0) {
split(line, fields, " ");
status[fields[1]] = fields[2];
}
}
($1 in status) && status[$1] != "-" && (lts == "*" || status[$1] == lts) { print }
'
}
# args flavor, type, version
nvm_ls_remote_index_tab() {
local LTS
LTS="${NVM_LTS-}"
if [ "$#" -lt 3 ]; then
nvm_err 'not enough arguments'
return 5
fi
local FLAVOR
FLAVOR="${1-}"
local TYPE
TYPE="${2-}"
local MIRROR
MIRROR="$(nvm_get_mirror "${FLAVOR}" "${TYPE}")"
if [ -z "${MIRROR}" ]; then
return 3
fi
local PREFIX
PREFIX=''
case "${FLAVOR}-${TYPE}" in
iojs-std) PREFIX="$(nvm_iojs_prefix)-" ;;
node-std) PREFIX='' ;;
iojs-*)
nvm_err 'unknown type of io.js release'
return 4
;;
*)
nvm_err 'unknown type of node.js release'
return 4
;;
esac
local SORT_COMMAND
SORT_COMMAND='command sort'
case "${FLAVOR}" in
node) SORT_COMMAND='nvm_sort_versions 1' ;;
esac
local PATTERN
PATTERN="${3-}"
if [ "${PATTERN#"${PATTERN%?}"}" = '.' ]; then
PATTERN="${PATTERN%.}"
fi
local VERSIONS
if [ -n "${PATTERN}" ] && [ "${PATTERN}" != '*' ]; then
if [ "${FLAVOR}" = 'iojs' ]; then
PATTERN="$(nvm_ensure_version_prefix "$(nvm_strip_iojs_prefix "${PATTERN}")")"
else
PATTERN="$(nvm_ensure_version_prefix "${PATTERN}")"
fi
else
unset PATTERN
fi
nvm_is_zsh && setopt local_options shwordsplit
local VERSION_LIST
VERSION_LIST="$(nvm_download -L -s "${MIRROR}/index.tab" -o - \
| command sed "
1d;
s/^/${PREFIX}/;
" \
)"
local LTS_ALIAS
local LTS_VERSION
command mkdir -p "$(nvm_alias_path)/lts"
{ command awk '{
if ($10 ~ /^\-?$/) { next }
if (tolower($10) !~ /^[a-z0-9][a-z0-9._-]*$/) { next }
if ($10 && !a[tolower($10)]++) {
if (alias) { print alias, version }
alias_name = "lts/" tolower($10)
if (!alias) { print "lts/*", alias_name }
alias = alias_name
version = $1
}
}
END {
if (alias) {
print alias, version
}
}' \
| while read -r LTS_ALIAS_LINE; do
LTS_ALIAS="${LTS_ALIAS_LINE%% *}"
LTS_VERSION="${LTS_ALIAS_LINE#* }"
nvm_make_alias "${LTS_ALIAS}" "${LTS_VERSION}" >/dev/null 2>&1
done; } << EOF
$VERSION_LIST
EOF
if [ "${FLAVOR}" = 'node' ] && [ -n "${VERSION_LIST}" ]; then
nvm_record_lts_status << EOF ||:
$VERSION_LIST
EOF
fi
if [ -n "${LTS-}" ]; then
LTS="$(nvm_normalize_lts "lts/${LTS}")" || return $?
LTS="${LTS#lts/}"
fi
VERSIONS="$( { command awk -v lts="${LTS-}" -v flavor="${FLAVOR}" -v only=",${NVM_ONLY_SELECTED:-${NVM_ONLY:-lts,non-lts,iojs}}," -v pattern="${PATTERN-}" '{
if (!$1) { next }
if (flavor == "iojs") { category = "iojs" }
else if ($1 ~ /^v[0-9]+\.[0-9]+\.[0-9]+-alpha\.[0-9]+\.[0-9]+\.[0-9]+$/) {
# a release, like v27.0.0, is not one of its alphas
if (pattern ~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ && index($1, pattern "-") == 1) { next }
category = "alpha"
}
else if ($10 ~ /^\-?$/) { category = "non-lts" }
else { category = "lts" }
if (!index(only, "," category ",")) { next }
if (lts && $10 ~ /^\-?$/) { next }
if (lts && lts != "*" && tolower($10) !~ tolower(lts)) { next }
if ($10 !~ /^\-?$/) {
if ($10 && $10 != prev) {
print $1, $10, "*"
} else {
print $1, $10
}
} else {
print $1
}
prev=$10;
}' \
| nvm_grep -w "${PATTERN:-.*}" \
| $SORT_COMMAND; } << EOF
$VERSION_LIST
EOF
)"
if [ -z "${VERSIONS}" ]; then
nvm_echo 'N/A'
return 3
fi
nvm_echo "${VERSIONS}"
}
nvm_get_checksum_binary() {
if nvm_has_non_aliased 'sha256sum'; then
nvm_echo 'sha256sum'
elif nvm_has_non_aliased 'shasum'; then
nvm_echo 'shasum'
elif nvm_has_non_aliased 'sha256'; then
nvm_echo 'sha256'
elif nvm_has_non_aliased 'gsha256sum'; then
nvm_echo 'gsha256sum'
elif nvm_has_non_aliased 'openssl'; then
nvm_echo 'openssl'
elif nvm_has_non_aliased 'bssl'; then
nvm_echo 'bssl'
elif nvm_has_non_aliased 'sha1sum'; then
nvm_echo 'sha1sum'
elif nvm_has_non_aliased 'sha1'; then
nvm_echo 'sha1'
else
nvm_err 'Unaliased sha256sum, shasum, sha256, gsha256sum, openssl, or bssl not found.'
nvm_err 'Unaliased sha1sum or sha1 not found.'
return 1
fi
}
nvm_get_checksum_alg() {
local NVM_CHECKSUM_BIN
NVM_CHECKSUM_BIN="$(nvm_get_checksum_binary 2>/dev/null)"
case "${NVM_CHECKSUM_BIN-}" in
sha256sum | shasum | sha256 | gsha256sum | openssl | bssl)
nvm_echo 'sha-256'
;;
sha1sum | sha1)
nvm_echo 'sha-1'
;;
*)
nvm_get_checksum_binary
return $?
;;
esac
}
nvm_compute_checksum() {
local FILE
FILE="${1-}"
if [ -z "${FILE}" ]; then
nvm_err 'Provided file to checksum is empty.'
return 2
elif ! [ -f "${FILE}" ]; then
nvm_err 'Provided file to checksum does not exist.'
return 1
fi
if nvm_has_non_aliased "sha256sum"; then
nvm_err 'Computing checksum with sha256sum'
command sha256sum "${FILE}" | command awk '{print $1}'
elif nvm_has_non_aliased "shasum"; then
nvm_err 'Computing checksum with shasum -a 256'
command shasum -a 256 "${FILE}" | command awk '{print $1}'
elif nvm_has_non_aliased "sha256"; then
nvm_err 'Computing checksum with sha256 -q'
command sha256 -q "${FILE}" | command awk '{print $1}'
elif nvm_has_non_aliased "gsha256sum"; then
nvm_err 'Computing checksum with gsha256sum'
command gsha256sum "${FILE}" | command awk '{print $1}'
elif nvm_has_non_aliased "openssl"; then
nvm_err 'Computing checksum with openssl dgst -sha256'
command openssl dgst -sha256 "${FILE}" | command awk '{print $NF}'
elif nvm_has_non_aliased "bssl"; then
nvm_err 'Computing checksum with bssl sha256sum'
command bssl sha256sum "${FILE}" | command awk '{print $1}'
elif nvm_has_non_aliased "sha1sum"; then
nvm_err 'Computing checksum with sha1sum'
command sha1sum "${FILE}" | command awk '{print $1}'
elif nvm_has_non_aliased "sha1"; then
nvm_err 'Computing checksum with sha1 -q'
command sha1 -q "${FILE}"
fi
}
nvm_compare_checksum() {
local FILE
FILE="${1-}"
if [ -z "${FILE}" ]; then
nvm_err 'Provided file to checksum is empty.'
return 4
elif ! [ -f "${FILE}" ]; then
nvm_err 'Provided file to checksum does not exist.'
return 3
fi
local COMPUTED_SUM
COMPUTED_SUM="$(nvm_compute_checksum "${FILE}")"
local CHECKSUM
CHECKSUM="${2-}"
if [ -z "${CHECKSUM}" ]; then
nvm_err 'Provided checksum to compare to is empty.'
return 2
fi
if [ -z "${COMPUTED_SUM}" ]; then
nvm_err "Computed checksum of '${FILE}' is empty." # missing in raspberry pi binary
nvm_err 'WARNING: Continuing *without checksum verification*'
return
elif [ "${COMPUTED_SUM}" != "${CHECKSUM}" ] && [ "${COMPUTED_SUM}" != "\\${CHECKSUM}" ]; then
nvm_err "Checksums do not match: '${COMPUTED_SUM}' found, '${CHECKSUM}' expected."
return 1
fi
nvm_err 'Checksums matched!'
}
# args: flavor, type, version, slug, compression
nvm_get_checksum() {
local FLAVOR
case "${1-}" in
node | iojs) FLAVOR="${1}" ;;
*)
nvm_err 'supported flavors: node, iojs'
return 2
;;
esac
local MIRROR
MIRROR="$(nvm_get_mirror "${FLAVOR}" "${2-}")"
if [ -z "${MIRROR}" ]; then
return 1
fi
local SHASUMS_URL
if [ "$(nvm_get_checksum_alg)" = 'sha-256' ]; then
SHASUMS_URL="${MIRROR}/${3}/SHASUMS256.txt"
else
SHASUMS_URL="${MIRROR}/${3}/SHASUMS.txt"
fi
nvm_download -L -s "${SHASUMS_URL}" -o - | command awk -v tarball="${4}.${5}" '{ if (tarball == $2) print $1 }'
}
nvm_get_remote_aliases() {
local NVM_ALIAS_DIR
NVM_ALIAS_DIR="$(nvm_alias_path)"
if [ ! -d "${NVM_ALIAS_DIR}" ]; then
return 0
fi
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local NVM_ALIAS_PATH
local NVM_ALIAS_NAME
local NVM_ALIAS_TARGET
nvm_is_zsh && setopt local_options nonomatch
# the same glob as `nvm_list_aliases`, so this never shows an alias that `nvm alias` omits
for NVM_ALIAS_PATH in "${NVM_ALIAS_DIR}/"*; do
if [ ! -f "${NVM_ALIAS_PATH}" ]; then
continue
fi
NVM_ALIAS_NAME="${NVM_ALIAS_PATH##*/}"
case "${NVM_ALIAS_NAME}" in
"${NVM_NODE_PREFIX}" | "${NVM_IOJS_PREFIX}" | stable | unstable) continue ;;
# control characters would corrupt the terminal, or the tab-separated output
*[[:cntrl:]]*) continue ;;
esac
NVM_ALIAS_TARGET="$(nvm_resolve_alias "${NVM_ALIAS_NAME}" 2>/dev/null)" || continue
case "${NVM_ALIAS_TARGET}" in
# flags, like `--lts`, select among installed versions, not remote ones
'' | --* | *[[:cntrl:]]*) continue ;;
esac
command printf '%s\t%s\n' "${NVM_ALIAS_TARGET}" "${NVM_ALIAS_NAME}"
done
}
nvm_print_versions() {
local NVM_CURRENT
NVM_CURRENT=$(nvm_ls_current)
local NVM_LATEST_ALIAS
NVM_LATEST_ALIAS="${2-}"
local NVM_NAMED_ALIASES
NVM_NAMED_ALIASES="${3-}"
local INSTALLED_COLOR
local SYSTEM_COLOR
local CURRENT_COLOR
local NOT_INSTALLED_COLOR
local DEFAULT_COLOR
local LTS_COLOR
local NVM_HAS_COLORS
NVM_HAS_COLORS=0
INSTALLED_COLOR=$(nvm_get_colors 1)
SYSTEM_COLOR=$(nvm_get_colors 2)
CURRENT_COLOR=$(nvm_get_colors 3)
NOT_INSTALLED_COLOR=$(nvm_get_colors 4)
DEFAULT_COLOR=$(nvm_get_colors 5)
LTS_COLOR=$(nvm_get_colors 6)
if nvm_has_colors; then
NVM_HAS_COLORS=1
fi
local NVM_HAS_ITALICS
NVM_HAS_ITALICS=0
if [ "${NVM_HAS_COLORS}" = 1 ] && [ -n "${NVM_LATEST_ALIAS}${NVM_NAMED_ALIASES}" ] && nvm_has_italics; then
NVM_HAS_ITALICS=1
fi
NVM_NAMED_ALIASES="${NVM_NAMED_ALIASES}" \
command awk \
-v remote_versions="$(printf '%s' "${1-}" | tr '\n' '|')" \
-v latest_alias="${NVM_LATEST_ALIAS}" \
-v node_prefix="$(nvm_node_prefix)" -v iojs_prefix="$(nvm_iojs_prefix)" \
-v installed_versions="$(nvm_ls 2>/dev/null | nvm_grep -v '^N/A$' | tr '\n' '|')" -v current="$NVM_CURRENT" \
-v installed_color="$INSTALLED_COLOR" -v system_color="$SYSTEM_COLOR" \
-v current_color="$CURRENT_COLOR" -v default_color="$DEFAULT_COLOR" \
-v old_lts_color="$DEFAULT_COLOR" -v has_colors="$NVM_HAS_COLORS" \
-v has_italics="$NVM_HAS_ITALICS" '
function alen(arr, i, len) { len=0; for(i in arr) len++; return len; }
function paint(color, text) { return (has_colors && color) ? ("\033[" color text "\033[0m") : text; }
function spaces(count, result) { result = ""; while (count-- > 0) result = result " "; return result; }
function italicize(text) { return has_italics ? ("\033[3m" text "\033[23m") : text; }
BEGIN {
named_alias_list = ENVIRON["NVM_NAMED_ALIASES"];
# wide enough for the longest version, like a nightly, plus the arrow before the current version
column = 15;
column_rows = split(remote_versions, column_lines, "|");
for (n = 1; n <= column_rows; n++) {
split(column_lines[n], column_fields, "[[:blank:]]+");
column_width = length(column_fields[1]) + (column_fields[1] == current ? 2 : 0);
if (column_width > column) {
column = column_width;
}
}
fmt_column = "%" column "s";
fmt_arrow = "->%" (column - 2) "s";
fmt_installed = has_colors ? (installed_color ? "\033[" installed_color fmt_column "\033[0m" : fmt_column) : fmt_column " *";
fmt_system = has_colors ? (system_color ? "\033[" system_color fmt_column "\033[0m" : fmt_column) : fmt_column " *";
fmt_current = has_colors ? (current_color ? "\033[" current_color fmt_arrow "\033[0m" : fmt_column) : fmt_arrow " *";
latest_lts_color = current_color;
sub(/0;/, "1;", latest_lts_color);
alias_color = current_color;
sub(/^1;/, "0;", alias_color);
fmt_latest_lts = has_colors && latest_lts_color ? ("\033[" latest_lts_color " (Latest LTS: %s)\033[0m") : " (Latest LTS: %s)";
fmt_old_lts = has_colors && old_lts_color ? ("\033[" old_lts_color " (LTS: %s)\033[0m") : " (LTS: %s)";
fmt_system_target = has_colors && system_color ? (" (\033[" system_color "-> %s\033[0m)") : " (-> %s)";
split(remote_versions, lines, "|");
split(installed_versions, installed, "|");
rows = alen(lines);
for (n = 1; n <= rows; n++) {
split(lines[n], fields, "[[:blank:]]+");
if (index(fields[1], iojs_prefix "-") == 1) {
latest_iojs = fields[1];
} else if (fields[1] ~ /^v0\.[0-9]*[13579]\./) {
latest_unstable = fields[1];
} else if (fields[1] ~ /^v[0-9]/) {
latest_stable = fields[1];
}
}
named_alias_rows = split(named_alias_list, named_alias_lines, "\n");
for (a = 1; a <= named_alias_rows; a++) {
tab_position = index(named_alias_lines[a], "\t");
if (tab_position < 2) {
continue;
}
alias_target = substr(named_alias_lines[a], 1, tab_position - 1);
alias_name = substr(named_alias_lines[a], tab_position + 1);
if (alias_name == "") {
continue;
}
alias_version = "";
if (alias_target == node_prefix || alias_target == "stable") {
alias_version = latest_stable;
} else if (alias_target == "unstable") {
alias_version = latest_unstable;
} else if (alias_target == iojs_prefix || alias_target == (iojs_prefix "-")) {
alias_version = latest_iojs;
} else {
for (n = 1; n <= rows; n++) {
split(lines[n], fields, "[[:blank:]]+");
if (fields[1] == alias_target || index(fields[1], alias_target ".") == 1) {
alias_version = fields[1];
}
}
}
if (alias_version != "") {
# mawk creates the assigned element before evaluating the right side, so `in` must be checked first
if (alias_version in named_aliases) {
named_aliases[alias_version] = named_aliases[alias_version] ", " alias_name;
italic_aliases[alias_version] = italic_aliases[alias_version] ", " italicize(alias_name);
} else {
named_aliases[alias_version] = alias_name;
italic_aliases[alias_version] = italicize(alias_name);
}
}
}
for (n = 1; n <= rows; n++) {
split(lines[n], fields, "[[:blank:]]+");
cols = alen(fields);
version = fields[1];
is_installed = 0;
for (i in installed) {
if (version == installed[i]) {
is_installed = 1;
break;
}
}
fmt_version = fmt_column;
if (version == current) {
fmt_version = fmt_current;
} else if (version == "system") {
fmt_version = fmt_system;
} else if (is_installed) {
fmt_version = fmt_installed;
}
padding[n] = (!has_colors && is_installed) ? "" : " ";
output[n] = sprintf(fmt_version, version);
version_width[n] = output[n] padding[n];
gsub(/\033\[[0-9;]*m/, "", version_width[n]);
version_width[n] = length(version_width[n]);
if (version_width[n] > max_version_width) {
max_version_width = version_width[n];
}
for (c = 1; c <= 3; c++) {
text[n, c] = "";
cell[n, c] = "";
}
if (version == "system" && cols >= 2) {
output[n] = output[n] sprintf(fmt_system_target, fields[2]);
} else if (cols == 2) {
text[n, 1] = sprintf(" (LTS: %s)", fields[2]);
cell[n, 1] = sprintf(fmt_old_lts, fields[2]);
} else if (cols == 3 && fields[3] == "*") {
text[n, 1] = sprintf(" (Latest LTS: %s)", fields[2]);
cell[n, 1] = sprintf(fmt_latest_lts, fields[2]);
}
if (latest_alias != "" && version == latest_stable) {
text[n, 2] = " (Latest: " latest_alias ")";
cell[n, 2] = paint(alias_color, " (Latest: " italicize(latest_alias) ")");
}
if (version in named_aliases) {
text[n, 3] = " (Aliases: " named_aliases[version] ")";
cell[n, 3] = paint(alias_color, " (Aliases: " italic_aliases[version] ")");
}
for (c = 1; c <= 3; c++) {
if (length(text[n, c]) > width[c]) {
width[c] = length(text[n, c]);
}
}
}
# each kind of annotation starts in the same column on every row, so the output stays `cut`-able
for (n = 1; n <= rows; n++) {
last = 0;
for (c = 1; c <= 3; c++) {
if (text[n, c] != "") {
last = c;
}
}
formatted = output[n];
if (last) {
formatted = formatted padding[n];
if (width[2] || width[3]) {
formatted = formatted spaces(max_version_width - version_width[n]);
}
gap = "";
for (c = 1; c <= last; c++) {
if (width[c]) {
formatted = formatted gap cell[n, c];
gap = spaces(width[c] - length(text[n, c])) " ";
}
}
}
print formatted
}
exit
}'
}
nvm_validate_implicit_alias() {
case "$1" in
"stable" | "unstable" | "iojs" | "node")
return
;;
*)
nvm_err "Only implicit aliases 'stable', 'unstable', 'iojs', and 'node' are supported."
return 1
;;
esac
}
nvm_print_implicit_alias() {
if [ "_$1" != "_local" ] && [ "_$1" != "_remote" ]; then
nvm_err "nvm_print_implicit_alias must be specified with local or remote as the first argument."
return 1
fi
local NVM_IMPLICIT
NVM_IMPLICIT="$2"
if ! nvm_validate_implicit_alias "${NVM_IMPLICIT}"; then
return 2
fi
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
local NVM_COMMAND
local NVM_ADD_PREFIX_COMMAND
local LAST_TWO
case "${NVM_IMPLICIT}" in
"${NVM_IOJS_PREFIX}")
NVM_COMMAND="nvm_ls_remote_iojs"
NVM_ADD_PREFIX_COMMAND="nvm_add_iojs_prefix"
if [ "_$1" = "_local" ]; then
NVM_COMMAND="nvm_ls ${NVM_IMPLICIT}"
fi
nvm_is_zsh && setopt local_options shwordsplit
local NVM_IOJS_VERSION
local EXIT_CODE
NVM_IOJS_VERSION="$(${NVM_COMMAND})" &&:
EXIT_CODE="$?"
if [ "_${EXIT_CODE}" = "_0" ]; then
NVM_IOJS_VERSION="$(nvm_echo "${NVM_IOJS_VERSION}" | command sed "s/^${NVM_IMPLICIT}-//" | nvm_grep -e '^v' | command cut -c2- | command cut -d . -f 1,2 | uniq | command tail -1)"
fi
if [ "_$NVM_IOJS_VERSION" = "_N/A" ]; then
nvm_echo 'N/A'
else
${NVM_ADD_PREFIX_COMMAND} "${NVM_IOJS_VERSION}"
fi
return $EXIT_CODE
;;
"${NVM_NODE_PREFIX}")
nvm_echo 'stable'
return
;;
*)
NVM_COMMAND="nvm_ls_remote"
if [ "_$1" = "_local" ]; then
NVM_COMMAND="nvm_ls node"
fi
nvm_is_zsh && setopt local_options shwordsplit
LAST_TWO=$($NVM_COMMAND | nvm_grep -e '^v' | command cut -c2- | command cut -d . -f 1,2 | uniq)
;;
esac
local MINOR
local STABLE
local UNSTABLE
local MOD
local NORMALIZED_VERSION
nvm_is_zsh && setopt local_options shwordsplit
for MINOR in $LAST_TWO; do
NORMALIZED_VERSION="$(nvm_normalize_version "$MINOR")"
if [ "_0${NORMALIZED_VERSION#?}" != "_$NORMALIZED_VERSION" ]; then
STABLE="$MINOR"
else
MOD="$(awk 'BEGIN { print int(ARGV[1] / 1000000) % 2 ; exit(0) }' "${NORMALIZED_VERSION}")"
if [ "${MOD}" -eq 0 ]; then
STABLE="${MINOR}"
elif [ "${MOD}" -eq 1 ]; then
UNSTABLE="${MINOR}"
fi
fi
done
if [ "_$2" = '_stable' ]; then
nvm_echo "${STABLE}"
elif [ "_$2" = '_unstable' ]; then
nvm_echo "${UNSTABLE:-"N/A"}"
fi
}
nvm_get_os() {
# dash's `local` keeps the caller's value, so these must start empty
local NVM_OS
NVM_OS=''
local NVM_UNAME
local NVM_OS_RELEASE_PATH
local NVM_OS_RELEASE_LINE
local NVM_OS_RELEASE_ID
NVM_OS_RELEASE_ID=''
local NVM_OS_KERNEL_PATH
local NVM_OS_KERNEL_TYPE
NVM_OS_KERNEL_TYPE=''
# `/etc/os-release` is available on Linux, FreeBSD 13.2+, and the MSYS2 and
# Cygwin runtimes; where it is readable, its `ID` names the OS without
# spawning `uname`. The file is read, not sourced, so nothing in it runs.
# systems without the file (macOS, OpenBSD, ...) and files without an `ID`
# fall through to `uname -a` below.
NVM_OS_RELEASE_PATH="${NVM_OS_RELEASE:-/etc/os-release}"
if [ -r "${NVM_OS_RELEASE_PATH}" ]; then
while IFS= read -r NVM_OS_RELEASE_LINE || [ -n "${NVM_OS_RELEASE_LINE}" ]; do
case "${NVM_OS_RELEASE_LINE}" in
ID=*)
NVM_OS_RELEASE_ID="${NVM_OS_RELEASE_LINE#ID=}"
break
;;
esac
done < "${NVM_OS_RELEASE_PATH}"
# an `ID` is a single word, which may be quoted and followed by
# whitespace (including a CR) or a comment
NVM_OS_RELEASE_ID="${NVM_OS_RELEASE_ID%%[[:space:]#]*}"
NVM_OS_RELEASE_ID="${NVM_OS_RELEASE_ID#[\"\']}"
NVM_OS_RELEASE_ID="${NVM_OS_RELEASE_ID%[\"\']}"
case "${NVM_OS_RELEASE_ID}" in
freebsd) NVM_OS=freebsd ;;
cygwin* | mingw* | msys*) NVM_OS=win ;;
# illumos distributions and Oracle Solaris report `SunOS` from
# `uname -a`, and GhostBSD reports `FreeBSD`; map these directly instead
# of forking `uname`
solaris | omnios | openindiana | smartos | illumos) NVM_OS=sunos ;;
ghostbsd) NVM_OS=freebsd ;;
# no `ID`, or one with no `nvm` OS of its own (DragonFly BSD): let
# `uname -a` decide
'' | dragonfly) NVM_OS='' ;;
# any other `ID` is a Linux distribution's only if the kernel says so;
# unlisted BSD and illumos derivatives (e.g. HardenedBSD, Helios) let
# `uname -a` decide
*)
NVM_OS_KERNEL_PATH="${NVM_OS_KERNEL_OSTYPE:-/proc/sys/kernel/ostype}"
if [ -r "${NVM_OS_KERNEL_PATH}" ] && IFS= read -r NVM_OS_KERNEL_TYPE < "${NVM_OS_KERNEL_PATH}" && [ "${NVM_OS_KERNEL_TYPE}" = 'Linux' ]; then
NVM_OS=linux
fi
;;
esac
fi
if [ -z "${NVM_OS-}" ]; then
NVM_UNAME="$(command uname -a)"
case "${NVM_UNAME}" in
Linux\ *) NVM_OS=linux ;;
Darwin\ *) NVM_OS=darwin ;;
SunOS\ *) NVM_OS=sunos ;;
FreeBSD\ *) NVM_OS=freebsd ;;
OpenBSD\ *) NVM_OS=openbsd ;;
AIX\ *) NVM_OS=aix ;;
CYGWIN* | MSYS* | MINGW*) NVM_OS=win ;;
esac
fi
nvm_echo "${NVM_OS-}"
}
nvm_get_arch() {
local HOST_ARCH
local NVM_OS
local EXIT_CODE
local LONG_BIT
NVM_OS="$(nvm_get_os)"
# If the OS is SunOS, first try to use pkgsrc to guess
# the most appropriate arch. If it's not available, use
# isainfo to get the instruction set supported by the
# kernel.
if [ "_${NVM_OS}" = "_sunos" ]; then
if HOST_ARCH=$(pkg_info -Q MACHINE_ARCH pkg_install); then
HOST_ARCH=$(nvm_echo "${HOST_ARCH}" | command tail -1)
else
HOST_ARCH=$(isainfo -n)
fi
elif [ "_${NVM_OS}" = "_aix" ]; then
HOST_ARCH=ppc64
else
HOST_ARCH="$(command uname -m)"
LONG_BIT="$(getconf LONG_BIT 2>/dev/null)"
fi
local NVM_ARCH
case "${HOST_ARCH}" in
x86_64 | amd64) NVM_ARCH="x64" ;;
i*86) NVM_ARCH="x86" ;;
aarch64 | armv8l) NVM_ARCH="arm64" ;;
loongarch64) NVM_ARCH="loong64" ;;
*) NVM_ARCH="${HOST_ARCH}" ;;
esac
# If running inside a 32Bit docker container the kernel still is 64bit
# change ARCH to 32bit if LONG_BIT is 32
if [ "_${LONG_BIT}" = "_32" ] && [ "${NVM_ARCH}" = "x64" ]; then
NVM_ARCH="x86"
fi
# If running a 64bit ARM kernel but a 32bit ARM userland,
# change ARCH to 32bit ARM (armv7l) if /sbin/init is 32bit executable
if [ "$(command uname)" = "Linux" ] \
&& [ "${NVM_ARCH}" = arm64 ] \
&& [ "$(command od -An -t x1 -j 4 -N 1 "/sbin/init" 2>/dev/null)" = ' 01' ]\
; then
NVM_ARCH=armv7l
HOST_ARCH=armv7l
fi
if [ -f "/etc/alpine-release" ] && [ "_${NVM_OS}" = "_linux" ]; then
# Alpine Linux uses musl libc; map to musl variants where available
# See https://unofficial-builds.nodejs.org/download/release/
case "${NVM_ARCH}" in
x64) NVM_ARCH=x64-musl ;;
arm64) NVM_ARCH=arm64-musl ;;
esac
fi
nvm_echo "${NVM_ARCH}"
}
nvm_get_minor_version() {
local VERSION
VERSION="$1"
if [ -z "${VERSION}" ]; then
nvm_err 'a version is required'
return 1
fi
case "${VERSION}" in
v | .* | *..* | v*[!.0123456789]* | [!v]*[!.0123456789]* | [!v0123456789]* | v[!0123456789]*)
nvm_err 'invalid version number'
return 2
;;
esac
local PREFIXED_VERSION
PREFIXED_VERSION="$(nvm_format_version "${VERSION}")"
local MINOR
MINOR="$(nvm_echo "${PREFIXED_VERSION}" | nvm_grep -e '^v' | command cut -c2- | command cut -d . -f 1,2)"
if [ -z "${MINOR}" ]; then
nvm_err 'invalid version number! (please report this)'
return 3
fi
nvm_echo "${MINOR}"
}
nvm_ensure_default_set() {
local VERSION
VERSION="$1"
if [ -z "${VERSION}" ]; then
nvm_err 'nvm_ensure_default_set: a version is required'
return 1
elif nvm_alias default >/dev/null 2>&1; then
# default already set
return 0
fi
local OUTPUT
OUTPUT="$(nvm alias default "${VERSION}")"
local EXIT_CODE
EXIT_CODE="$?"
nvm_echo "Creating default alias: ${OUTPUT}"
return $EXIT_CODE
}
nvm_is_merged_node_version() {
nvm_version_greater_than_or_equal_to "$1" v4.0.0
}
nvm_get_mirror() {
local NVM_MIRROR
NVM_MIRROR=''
case "${1}-${2}" in
node-std) NVM_MIRROR="${NVM_NODEJS_ORG_MIRROR:-https://nodejs.org/dist}" ;;
iojs-std) NVM_MIRROR="${NVM_IOJS_ORG_MIRROR:-https://iojs.org/dist}" ;;
*)
nvm_err 'unknown type of node.js or io.js release'
return 1
;;
esac
case "${NVM_MIRROR}" in
*\`* | *\\* | *\'* | *\(* | *' '* )
nvm_err '$NVM_NODEJS_ORG_MIRROR and $NVM_IOJS_ORG_MIRROR may only contain a URL'
return 2
;;
esac
# Allow RFC 3986 `unreserved` (A-Za-z0-9-._~) plus the authority and path
# punctuation a mirror URL legitimately needs: `:` for a port, `@` for
# userinfo, `[`/`]` for an IPv6 literal host, `%` for percent-encoding.
# `sub-delims` (!$&'()*+,;=) and the query/fragment delimiters (?#) stay out:
# nvm appends a path to this value, so a query string could never work anyway,
# and several of those characters are shell metacharacters.
# Note: in a bracket expression `]` must come first and `-` last to be literal.
if ! nvm_echo "${NVM_MIRROR}" | command awk '{ if ($0 !~ /^https?:\/\/[]a-zA-Z0-9._~:\/@%[-]+$/) exit 1 }'; then
nvm_err '$NVM_NODEJS_ORG_MIRROR and $NVM_IOJS_ORG_MIRROR may only contain a URL'
return 2
fi
nvm_echo "${NVM_MIRROR}"
}
# args: os, prefixed version, version, tarball, extract directory
nvm_install_binary_extract() {
if [ "$#" -ne 5 ]; then
nvm_err 'nvm_install_binary_extract needs 5 parameters'
return 1
fi
local NVM_OS
local PREFIXED_VERSION
local VERSION
local TARBALL
local TMPDIR
NVM_OS="${1}"
PREFIXED_VERSION="${2}"
VERSION="${3}"
TARBALL="${4}"
TMPDIR="${5}"
local VERSION_PATH
[ -n "${TMPDIR-}" ] && \
command mkdir -p "${TMPDIR}" && \
VERSION_PATH="$(nvm_version_path "${PREFIXED_VERSION}")" || return 1
# For Windows system (Git Bash with MSYS, Cygwin)
if [ "${NVM_OS}" = 'win' ]; then
VERSION_PATH="${VERSION_PATH}/bin"
command unzip -q "${TARBALL}" -d "${TMPDIR}" || return 1
# Replace any pre-existing (possibly broken or partial) install so the
# move below cannot collide with leftover files. Safe here: the archive
# has already downloaded and unzipped successfully into TMPDIR.
command rm -rf "${VERSION_PATH}"
command mkdir -p "${VERSION_PATH}" || return 1
command mv "${TMPDIR}/"*/* "${VERSION_PATH}/" || return 1
command chmod +x "${VERSION_PATH}"/node.exe || return 1
command chmod +x "${VERSION_PATH}"/npm || return 1
command chmod +x "${VERSION_PATH}"/npx 2>/dev/null
command rm -rf "${TMPDIR}"
return 0
fi
# For non-Windows systems (including WSL running on Windows)
nvm_extract_tarball "${NVM_OS}" "${VERSION}" "${TARBALL}" "${TMPDIR}" || return 1
# Install atomically: replace any pre-existing version directory with a
# single rename, so a partial or broken tree is never observed as installed.
# A leftover directory without a working bin/node otherwise wedges the
# install - the per-entry `mv` refuses to overwrite the non-empty bin/, lib/,
# ... subdirectories and leaves a half-updated tree behind. Removing it first
# is safe: the tarball has already downloaded and extracted into TMPDIR.
command rm -rf "${VERSION_PATH}" || return 1
command mkdir -p "$(dirname "${VERSION_PATH}")" || return 1
if command mv "${TMPDIR}" "${VERSION_PATH}" 2>/dev/null; then
return 0
fi
# Fall back to a per-entry move when a single rename is not possible (e.g.
# TMPDIR and the versions directory are on different filesystems).
command rm -rf "${VERSION_PATH}"
command mkdir -p "${VERSION_PATH}" || return 1
command mv "${TMPDIR}/"* "${VERSION_PATH}" || return 1
command rm -rf "${TMPDIR}"
return 0
}
# args: flavor, type, version, reinstall
nvm_install_binary() {
local FLAVOR
case "${1-}" in
node | iojs) FLAVOR="${1}" ;;
*)
nvm_err 'supported flavors: node, iojs'
return 4
;;
esac
local TYPE
TYPE="${2-}"
local PREFIXED_VERSION
PREFIXED_VERSION="${3-}"
if [ -z "${PREFIXED_VERSION}" ]; then
nvm_err 'A version number is required.'
return 3
fi
local nosource
nosource="${4-}"
local VERSION
VERSION="$(nvm_strip_iojs_prefix "${PREFIXED_VERSION}")"
local NVM_OS
NVM_OS="$(nvm_get_os)"
if [ -z "${NVM_OS}" ]; then
return 2
fi
# dash's `local` keeps the caller's value, and TMPDIR is usually set: it is
# later removed with `rm -rf`, so it must not start as the system temp dir
local TARBALL
TARBALL=''
local TMPDIR
TMPDIR=''
local PROGRESS_BAR
local NODE_OR_IOJS
if [ "${FLAVOR}" = 'node' ]; then
NODE_OR_IOJS="${FLAVOR}"
elif [ "${FLAVOR}" = 'iojs' ]; then
NODE_OR_IOJS="io.js"
fi
if [ "${NVM_NO_PROGRESS-}" = "1" ]; then
# --silent, --show-error, use short option as @samrocketman mentions the compatibility issue.
PROGRESS_BAR="-sS"
else
PROGRESS_BAR="--progress-bar"
fi
nvm_echo "Downloading and installing ${NODE_OR_IOJS-} ${VERSION}..."
TARBALL="$(PROGRESS_BAR="${PROGRESS_BAR}" nvm_download_artifact "${FLAVOR}" binary "${TYPE-}" "${VERSION}")" || TARBALL=''
if nvm_is_cached_artifact "${TARBALL}"; then
TMPDIR="$(dirname "${TARBALL}")/files"
fi
if nvm_install_binary_extract "${NVM_OS}" "${PREFIXED_VERSION}" "${VERSION}" "${TARBALL}" "${TMPDIR}"; then
if [ -n "${ALIAS-}" ]; then
nvm alias "${ALIAS}" "${provided_version}"
fi
return 0
fi
# Read nosource from arguments
if [ "${nosource-}" = '1' ]; then
nvm_err 'Binary download failed. Download from source aborted.'
return 2
fi
nvm_err 'Binary download failed, trying source.'
if [ -n "${TMPDIR-}" ]; then
command rm -rf "${TMPDIR}"
fi
return 1
}
# args: flavor, kind, version
nvm_get_download_slug() {
local FLAVOR
case "${1-}" in
node | iojs) FLAVOR="${1}" ;;
*)
nvm_err 'supported flavors: node, iojs'
return 1
;;
esac
local KIND
case "${2-}" in
binary | source) KIND="${2}" ;;
*)
nvm_err 'supported kinds: binary, source'
return 2
;;
esac
local VERSION
VERSION="${3-}"
local NVM_OS
NVM_OS="$(nvm_get_os)"
local NVM_ARCH
NVM_ARCH="$(nvm_get_arch)"
if ! nvm_is_merged_node_version "${VERSION}"; then
if [ "${NVM_ARCH}" = 'armv6l' ] || [ "${NVM_ARCH}" = 'armv7l' ]; then
NVM_ARCH="arm-pi"
fi
fi
# If running MAC M1 :: ARM64 binaries are not available for Node < 16.0.0
# https://github.com/nodejs/node/issues/40126 (binary distributions aren't available until v16)
if nvm_version_greater '16.0.0' "${VERSION}" && [ "_${NVM_OS}" = '_darwin' ] && [ "${NVM_ARCH}" = 'arm64' ]; then
NVM_ARCH=x64
fi
if [ "${KIND}" = 'binary' ]; then
nvm_echo "${FLAVOR}-${VERSION}-${NVM_OS}-${NVM_ARCH}"
elif [ "${KIND}" = 'source' ]; then
nvm_echo "${FLAVOR}-${VERSION}"
fi
}
nvm_get_artifact_compression() {
local VERSION
VERSION="${1-}"
local NVM_OS
NVM_OS="$(nvm_get_os)"
local COMPRESSION
COMPRESSION='tar.gz'
if [ "_${NVM_OS}" = '_win' ]; then
COMPRESSION='zip'
elif nvm_supports_xz "${VERSION}"; then
COMPRESSION='tar.xz'
fi
nvm_echo "${COMPRESSION}"
}
# args: flavor, kind, type, version
nvm_download_artifact() {
local FLAVOR
case "${1-}" in
node | iojs) FLAVOR="${1}" ;;
*)
nvm_err 'supported flavors: node, iojs'
return 1
;;
esac
local KIND
case "${2-}" in
binary | source) KIND="${2}" ;;
*)
nvm_err 'supported kinds: binary, source'
return 1
;;
esac
local TYPE
TYPE="${3-}"
local MIRROR
MIRROR="$(nvm_get_mirror "${FLAVOR}" "${TYPE}")"
if [ -z "${MIRROR}" ]; then
return 2
fi
local VERSION
VERSION="${4}"
case "${VERSION}" in
'')
nvm_err 'A version number is required.'
return 3
;;
*[!0-9A-Za-z._+-]*)
nvm_err 'Invalid version: contains disallowed characters'
return 3
;;
esac
if [ "${KIND}" = 'binary' ] && ! nvm_binary_available "${VERSION}"; then
nvm_err "No precompiled binary available for ${VERSION}."
return
fi
local SLUG
SLUG="$(nvm_get_download_slug "${FLAVOR}" "${KIND}" "${VERSION}")"
local COMPRESSION
COMPRESSION="$(nvm_get_artifact_compression "${VERSION}")"
local tmpdir
if [ "${KIND}" = 'binary' ]; then
tmpdir="$(nvm_cache_dir)/bin/${SLUG}"
else
tmpdir="$(nvm_cache_dir)/src/${SLUG}"
fi
local TARBALL
TARBALL="${tmpdir}/${SLUG}.${COMPRESSION}"
if [ "${NVM_OFFLINE-}" = 1 ]; then
# In offline mode, use cached tarball without checksum or download
if [ -r "${TARBALL}" ]; then
nvm_err "Offline: using cached archive $(nvm_sanitize_path "${TARBALL}")"
nvm_echo "${TARBALL}"
return 0
fi
nvm_err "Offline: no cached archive found for ${SLUG}"
return 4
fi
local CHECKSUM
CHECKSUM="$(nvm_get_checksum "${FLAVOR}" "${TYPE}" "${VERSION}" "${SLUG}" "${COMPRESSION}")"
command mkdir -p "${tmpdir}/files" || {
nvm_err "creating directory ${tmpdir}/files failed"
return 3
}
local TARBALL_URL
if nvm_version_greater_than_or_equal_to "${VERSION}" 0.1.14; then
TARBALL_URL="${MIRROR}/${VERSION}/${SLUG}.${COMPRESSION}"
else
# node <= 0.1.13 does not have a directory
TARBALL_URL="${MIRROR}/${SLUG}.${COMPRESSION}"
fi
if [ -r "${TARBALL}" ]; then
nvm_err "Local cache found: $(nvm_sanitize_path "${TARBALL}")"
if nvm_compare_checksum "${TARBALL}" "${CHECKSUM}" >/dev/null 2>&1; then
nvm_err "Checksums match! Using existing downloaded archive $(nvm_sanitize_path "${TARBALL}")"
nvm_echo "${TARBALL}"
return 0
fi
nvm_compare_checksum "${TARBALL}" "${CHECKSUM}"
nvm_err "Checksum check failed!"
nvm_err "Removing the broken local cache..."
command rm -rf "${TARBALL}"
fi
nvm_err "Downloading $(nvm_sanitize_url "${TARBALL_URL}")..."
# stdout is reserved for the tarball path, so nothing the downloader prints may reach it
nvm_download -L -C - "${PROGRESS_BAR}" "${TARBALL_URL}" -o "${TARBALL}" >&2 || {
command rm -rf "${TARBALL}" "${tmpdir}"
nvm_err "download from $(nvm_sanitize_url "${TARBALL_URL}") failed"
return 4
}
if nvm_grep '404 Not Found' "${TARBALL}" >/dev/null; then
command rm -rf "${TARBALL}" "${tmpdir}"
nvm_err "HTTP 404 at URL $(nvm_sanitize_url "${TARBALL_URL}")"
return 5
fi
nvm_compare_checksum "${TARBALL}" "${CHECKSUM}" || {
command rm -rf "${tmpdir}/files"
return 6
}
nvm_echo "${TARBALL}"
}
# a tarball path from nvm_download_artifact is only usable if it is an existing file in nvm's cache
nvm_is_cached_artifact() {
case "${1-}" in
"$(nvm_cache_dir)"/*) [ -f "${1}" ] ;;
*) return 1 ;;
esac
}
# args: nvm_os, version, tarball, tmpdir
nvm_extract_tarball() {
if [ "$#" -ne 4 ]; then
nvm_err 'nvm_extract_tarball requires exactly 4 arguments'
return 5
fi
local NVM_OS
NVM_OS="${1-}"
local VERSION
VERSION="${2-}"
local TARBALL
TARBALL="${3-}"
local TMPDIR
TMPDIR="${4-}"
local tar_compression_flag
tar_compression_flag='z'
if nvm_supports_xz "${VERSION}"; then
tar_compression_flag='J'
fi
local tar
tar='tar'
if [ "${NVM_OS}" = 'aix' ]; then
tar='gtar'
fi
if [ "${NVM_OS}" = 'openbsd' ]; then
if [ "${tar_compression_flag}" = 'J' ]; then
command xzcat "${TARBALL}" | "${tar}" -xf - -C "${TMPDIR}" -s '/[^\/]*\///' || return 1
else
command "${tar}" -x${tar_compression_flag}f "${TARBALL}" -C "${TMPDIR}" -s '/[^\/]*\///' || return 1
fi
else
command "${tar}" -x${tar_compression_flag}f "${TARBALL}" -C "${TMPDIR}" --strip-components 1 --no-same-owner || return 1
fi
}
nvm_get_make_jobs() {
if nvm_is_natural_num "${1-}"; then
NVM_MAKE_JOBS="$1"
nvm_echo "number of \`make\` jobs: ${NVM_MAKE_JOBS}"
return
elif [ -n "${1-}" ]; then
unset NVM_MAKE_JOBS
nvm_err "$1 is invalid for number of \`make\` jobs, must be a natural number"
fi
local NVM_OS
NVM_OS="$(nvm_get_os)"
local NVM_CPU_CORES
case "_${NVM_OS}" in
"_linux")
NVM_CPU_CORES="$(nvm_grep -c -E '^processor.+: [0-9]+' /proc/cpuinfo)"
;;
"_freebsd" | "_darwin" | "_openbsd")
NVM_CPU_CORES="$(sysctl -n hw.ncpu)"
;;
"_sunos")
# some `wc`s pad the count with whitespace
NVM_CPU_CORES="$(psrinfo | wc -l | command tr -d '[:space:]')"
;;
"_aix")
NVM_CPU_CORES="$(pmcycles -m | wc -l | command tr -d '[:space:]')"
;;
*)
# `_NPROCESSORS_ONLN` is how glibc, FreeBSD, macOS, and Cygwin spell it;
# the unprefixed name is what POSIX.1-2024 standardizes, and what NetBSD
# and Solaris answer to. Windows shells inherit `NUMBER_OF_PROCESSORS`;
# the smallest ones ship neither `getconf` nor `nproc`.
NVM_CPU_CORES="$(command getconf _NPROCESSORS_ONLN 2>/dev/null \
|| command getconf NPROCESSORS_ONLN 2>/dev/null \
|| command nproc 2>/dev/null \
|| nvm_echo "${NUMBER_OF_PROCESSORS-}")"
;;
esac
if ! nvm_is_natural_num "${NVM_CPU_CORES}"; then
nvm_err 'Can not determine how many core(s) are available, running in single-threaded mode.'
nvm_err 'Please report an issue on GitHub to help us make nvm run faster on your computer!'
NVM_MAKE_JOBS=1
else
nvm_echo "Detected that you have ${NVM_CPU_CORES} CPU core(s)"
if [ "${NVM_CPU_CORES}" -gt 2 ]; then
NVM_MAKE_JOBS=$((NVM_CPU_CORES - 1))
nvm_echo "Running with ${NVM_MAKE_JOBS} threads to speed up the build"
else
NVM_MAKE_JOBS=1
nvm_echo 'Number of CPU core(s) less than or equal to 2, running in single-threaded mode'
fi
fi
}
# args: flavor, type, version, make jobs, additional
nvm_install_source() {
local FLAVOR
case "${1-}" in
node | iojs) FLAVOR="${1}" ;;
*)
nvm_err 'supported flavors: node, iojs'
return 4
;;
esac
local TYPE
TYPE="${2-}"
local PREFIXED_VERSION
PREFIXED_VERSION="${3-}"
if [ -z "${PREFIXED_VERSION}" ]; then
nvm_err 'A version number is required.'
return 3
fi
local VERSION
VERSION="$(nvm_strip_iojs_prefix "${PREFIXED_VERSION}")"
local NVM_MAKE_JOBS
NVM_MAKE_JOBS="${4-}"
local ADDITIONAL_PARAMETERS
ADDITIONAL_PARAMETERS="${5-}"
local NVM_ARCH
NVM_ARCH="$(nvm_get_arch)"
if [ "${NVM_ARCH}" = 'armv6l' ] || [ "${NVM_ARCH}" = 'armv7l' ]; then
if [ -n "${ADDITIONAL_PARAMETERS}" ]; then
ADDITIONAL_PARAMETERS="--without-snapshot ${ADDITIONAL_PARAMETERS}"
else
ADDITIONAL_PARAMETERS='--without-snapshot'
fi
fi
if [ -n "${ADDITIONAL_PARAMETERS}" ]; then
nvm_echo "Additional options while compiling: ${ADDITIONAL_PARAMETERS}"
fi
local NVM_OS
NVM_OS="$(nvm_get_os)"
local make
local MAKE_CXX
# For old Node.js versions (< 0.12), explicitly set SHELL=/bin/sh to avoid
# issues with zsh's strict glob handling in Makefiles with unquoted globs
local MAKE_SHELL_OVERRIDE
if nvm_version_greater "0.12.0" "${VERSION}"; then
MAKE_SHELL_OVERRIDE=' SHELL=/bin/sh'
fi
make="make${MAKE_SHELL_OVERRIDE-}"
case "${NVM_OS}" in
'freebsd' | 'openbsd')
make="gmake${MAKE_SHELL_OVERRIDE-}"
MAKE_CXX="CC=${CC:-cc} CXX=${CXX:-c++}"
;;
'darwin')
MAKE_CXX="CC=${CC:-cc} CXX=${CXX:-c++}"
;;
'aix')
make="gmake${MAKE_SHELL_OVERRIDE-}"
;;
esac
if nvm_has "clang++" && nvm_has "clang" && nvm_version_greater_than_or_equal_to "$(nvm_clang_version)" 3.5; then
if [ -z "${CC-}" ] || [ -z "${CXX-}" ]; then
nvm_echo "Clang v3.5+ detected! CC or CXX not specified, will use Clang as C/C++ compiler!"
MAKE_CXX="CC=${CC:-cc} CXX=${CXX:-c++}"
fi
fi
# see nvm_install_binary: these must not inherit TMPDIR, which is removed on failure
local TARBALL
TARBALL=''
local TMPDIR
TMPDIR=''
local VERSION_PATH
VERSION_PATH=''
if [ "${NVM_NO_PROGRESS-}" = "1" ]; then
# --silent, --show-error, use short option as @samrocketman mentions the compatibility issue.
PROGRESS_BAR="-sS"
else
PROGRESS_BAR="--progress-bar"
fi
nvm_is_zsh && setopt local_options shwordsplit
TARBALL="$(PROGRESS_BAR="${PROGRESS_BAR}" nvm_download_artifact "${FLAVOR}" source "${TYPE}" "${VERSION}")" && \
nvm_is_cached_artifact "${TARBALL}" && \
TMPDIR="$(dirname "${TARBALL}")/files" && \
if ! (
# shellcheck disable=SC2086
command mkdir -p "${TMPDIR}" && \
nvm_extract_tarball "${NVM_OS}" "${VERSION}" "${TARBALL}" "${TMPDIR}" && \
VERSION_PATH="$(nvm_version_path "${PREFIXED_VERSION}")" && \
nvm_cd "${TMPDIR}" && \
nvm_echo '$>'./configure --prefix="${VERSION_PATH}" $ADDITIONAL_PARAMETERS'<' && \
./configure --prefix="${VERSION_PATH}" $ADDITIONAL_PARAMETERS && \
$make -j "${NVM_MAKE_JOBS}" ${MAKE_CXX-} && \
command rm -f "${VERSION_PATH}" 2>/dev/null && \
$make -j "${NVM_MAKE_JOBS}" ${MAKE_CXX-} install
); then
nvm_err "nvm: install ${VERSION} failed!"
command rm -rf "${TMPDIR-}"
return 1
fi
}
nvm_use_if_needed() {
if [ "_${1-}" = "_$(nvm_ls_current)" ]; then
return
fi
nvm use "$@"
}
nvm_install_npm_if_needed() {
local VERSION
VERSION="$(nvm_ls_current)"
if ! nvm_has "npm"; then
nvm_echo 'Installing npm...'
if nvm_version_greater 0.2.0 "${VERSION}"; then
nvm_err 'npm requires node v0.2.3 or higher'
elif nvm_version_greater_than_or_equal_to "${VERSION}" 0.2.0; then
if nvm_version_greater 0.2.3 "${VERSION}"; then
nvm_err 'npm requires node v0.2.3 or higher'
else
nvm_download -L https://npmjs.org/install.sh -o - | clean=yes npm_install=0.2.19 sh
fi
else
nvm_download -L https://npmjs.org/install.sh -o - | clean=yes sh
fi
fi
return $?
}
nvm_match_version() {
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local PROVIDED_VERSION
PROVIDED_VERSION="$1"
case "_${PROVIDED_VERSION}" in
"_${NVM_IOJS_PREFIX}" | '_io.js')
nvm_version "${NVM_IOJS_PREFIX}"
;;
'_system')
nvm_echo 'system'
;;
*)
nvm_version "${PROVIDED_VERSION}"
;;
esac
}
nvm_npm_global_modules() {
local NPMLIST
local VERSION
VERSION="$1"
NPMLIST=$(nvm use "${VERSION}" >/dev/null && npm list -g --depth=0 2>/dev/null | command sed -e '1d' -e '/UNMET PEER DEPENDENCY/d')
local INSTALLS
INSTALLS=$(nvm_echo "${NPMLIST}" | command sed -e '/ -> / d' -e '/\(empty\)/ d' -e 's/^.* \(.*@[^ ]*\).*/\1/' -e '/^npm@[^ ]*.*$/ d' -e '/^corepack@[^ ]*.*$/ d' | command xargs)
local LINKS
LINKS="$(nvm_echo "${NPMLIST}" | command sed -n 's/.* -> \(.*\)/\1/ p')"
nvm_echo "${INSTALLS} //// ${LINKS}"
}
nvm_npmrc_bad_news_bears() {
local NVM_NPMRC
local NVM_NPMRC_LINE
local NVM_NPMRC_KEY
NVM_NPMRC="${1-}"
if [ -n "${NVM_NPMRC}" ] && [ -f "${NVM_NPMRC}" ]; then
# this is fork-free on purpose: it runs up to four times on every `nvm use`/`nvm install`
# avoid grepping or sub-shells as much as possible here.
while IFS= read -r NVM_NPMRC_LINE || [ -n "${NVM_NPMRC_LINE}" ]; do
case "${NVM_NPMRC_LINE}" in
*=*)
NVM_NPMRC_KEY="${NVM_NPMRC_LINE%%=*}"
;;
*)
continue
;;
esac
NVM_NPMRC_KEY="${NVM_NPMRC_KEY%"${NVM_NPMRC_KEY##*[! ]}"}"
case "${NVM_NPMRC_KEY}" in
prefix | globalconfig)
return 0
;;
esac
done < "${NVM_NPMRC}"
fi
return 1
}
nvm_die_on_prefix() {
local NVM_DELETE_PREFIX
NVM_DELETE_PREFIX="${1-}"
case "${NVM_DELETE_PREFIX}" in
0 | 1) ;;
*)
nvm_err 'First argument "delete the prefix" must be zero or one'
return 1
;;
esac
local NVM_COMMAND
NVM_COMMAND="${2-}"
local NVM_VERSION_DIR
NVM_VERSION_DIR="${3-}"
if [ -z "${NVM_COMMAND}" ] || [ -z "${NVM_VERSION_DIR}" ]; then
nvm_err 'Second argument "nvm command", and third argument "nvm version dir", must both be nonempty'
return 2
fi
# npm first looks at $PREFIX (case-sensitive)
# we do not bother to test the value here; if this env var is set, unset it to continue.
# however, `npm exec` in npm v7.2+ sets $PREFIX; if set, inherit it
if [ -n "${PREFIX-}" ] && [ "$(nvm_version_path "$(node -v)")" != "${PREFIX}" ]; then
nvm deactivate >/dev/null 2>&1
nvm_err "nvm is not compatible with the \"PREFIX\" environment variable: currently set to \"${PREFIX}\""
nvm_err 'Run `unset PREFIX` to unset it.'
return 3
fi
# npm normalizes NPM_CONFIG_-prefixed env vars
# https://github.com/npm/npmconf/blob/22827e4038d6eebaafeb5c13ed2b92cf97b8fb82/npmconf.js#L331-L348
# https://github.com/npm/npm/blob/5e426a78ca02d0044f8dd26e0c5f881217081cbd/lib/config/core.js#L343-L359
#
# here, we avoid trying to replicate "which one wins" or testing the value; if any are defined, it errors
# until none are left.
local NVM_NPM_CONFIG_x_PREFIX_ENV
NVM_NPM_CONFIG_x_PREFIX_ENV="$(command awk 'BEGIN { for (name in ENVIRON) if (toupper(name) == "NPM_CONFIG_PREFIX") { print name; break } }')"
if [ -n "${NVM_NPM_CONFIG_x_PREFIX_ENV-}" ]; then
# `$NVM_OS` is only used to translate Windows paths, but detecting the OS
# shells out to `uname`, so it is deferred until it is actually needed
local NVM_OS
NVM_OS="$(nvm_get_os)"
local NVM_CONFIG_VALUE
eval "NVM_CONFIG_VALUE=\"\$${NVM_NPM_CONFIG_x_PREFIX_ENV}\""
local NVM_CONFIG_DIR
# a prefix that does not exist yet can not be resolved, so it is checked as-is
if [ -n "${NVM_CONFIG_VALUE-}" ] && [ "_${NVM_OS}" = "_win" ] && NVM_CONFIG_DIR="$(nvm_cd "$NVM_CONFIG_VALUE" 2>/dev/null && pwd)"; then
NVM_CONFIG_VALUE="${NVM_CONFIG_DIR}"
fi
if [ -n "${NVM_CONFIG_VALUE-}" ] && ! nvm_tree_contains_path "${NVM_DIR}" "${NVM_CONFIG_VALUE}"; then
nvm deactivate >/dev/null 2>&1
nvm_err "nvm is not compatible with the \"${NVM_NPM_CONFIG_x_PREFIX_ENV}\" environment variable: currently set to \"${NVM_CONFIG_VALUE}\""
nvm_err "Run \`unset ${NVM_NPM_CONFIG_x_PREFIX_ENV}\` to unset it."
return 4
fi
fi
# here, npm config checks npmrc files.
# the stack is: cli, env, project, user, global, builtin, defaults
# cli does not apply; env is covered above, defaults don't exist for prefix
# there are 4 npmrc locations to check: project, global, user, and builtin
# project: find the closest node_modules or package.json-containing dir, `.npmrc`
# global: default prefix + `/etc/npmrc`
# user: $HOME/.npmrc
# builtin: npm install location, `npmrc`
#
# if any of them have a `prefix`, fail.
# if any have `globalconfig`, fail also, just in case, to avoid spidering configs.
local NVM_NPM_BUILTIN_NPMRC
NVM_NPM_BUILTIN_NPMRC="${NVM_VERSION_DIR}/lib/node_modules/npm/npmrc"
if nvm_npmrc_bad_news_bears "${NVM_NPM_BUILTIN_NPMRC}"; then
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
npm config --loglevel=warn delete prefix --userconfig="${NVM_NPM_BUILTIN_NPMRC}"
npm config --loglevel=warn delete globalconfig --userconfig="${NVM_NPM_BUILTIN_NPMRC}"
else
nvm_err "Your builtin npmrc file ($(nvm_sanitize_path "${NVM_NPM_BUILTIN_NPMRC}"))"
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
return 10
fi
fi
local NVM_NPM_GLOBAL_NPMRC
NVM_NPM_GLOBAL_NPMRC="${NVM_VERSION_DIR}/etc/npmrc"
if nvm_npmrc_bad_news_bears "${NVM_NPM_GLOBAL_NPMRC}"; then
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
npm config --global --loglevel=warn delete prefix
npm config --global --loglevel=warn delete globalconfig
else
nvm_err "Your global npmrc file ($(nvm_sanitize_path "${NVM_NPM_GLOBAL_NPMRC}"))"
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
return 10
fi
fi
local NVM_NPM_USER_NPMRC
NVM_NPM_USER_NPMRC="${HOME}/.npmrc"
if nvm_npmrc_bad_news_bears "${NVM_NPM_USER_NPMRC}"; then
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
npm config --loglevel=warn delete prefix --userconfig="${NVM_NPM_USER_NPMRC}"
npm config --loglevel=warn delete globalconfig --userconfig="${NVM_NPM_USER_NPMRC}"
else
nvm_err "Your user’s .npmrc file ($(nvm_sanitize_path "${NVM_NPM_USER_NPMRC}"))"
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
return 10
fi
fi
local NVM_NPM_PROJECT_NPMRC
NVM_NPM_PROJECT_NPMRC="$(nvm_find_project_dir)/.npmrc"
if nvm_npmrc_bad_news_bears "${NVM_NPM_PROJECT_NPMRC}"; then
if [ "_${NVM_DELETE_PREFIX}" = "_1" ]; then
npm config --loglevel=warn delete prefix
npm config --loglevel=warn delete globalconfig
else
nvm_err "Your project npmrc file ($(nvm_sanitize_path "${NVM_NPM_PROJECT_NPMRC}"))"
nvm_err 'has a `globalconfig` and/or a `prefix` setting, which are incompatible with nvm.'
nvm_err "Run \`${NVM_COMMAND}\` to unset it."
return 10
fi
fi
}
# Succeeds if $IOJS_VERSION represents an io.js version that has a
# Solaris binary, fails otherwise.
# Currently, only io.js 3.3.1 has a Solaris binary available, and it's the
# latest io.js version available. The expectation is that any potential io.js
# version later than v3.3.1 will also have Solaris binaries.
nvm_iojs_version_has_solaris_binary() {
local IOJS_VERSION
IOJS_VERSION="$1"
local STRIPPED_IOJS_VERSION
STRIPPED_IOJS_VERSION="$(nvm_strip_iojs_prefix "${IOJS_VERSION}")"
if [ "_${STRIPPED_IOJS_VERSION}" = "_${IOJS_VERSION}" ]; then
return 1
fi
# io.js started shipping Solaris binaries with io.js v3.3.1
nvm_version_greater_than_or_equal_to "${STRIPPED_IOJS_VERSION}" v3.3.1
}
# Succeeds if $NODE_VERSION represents a node version that has a
# Solaris binary, fails otherwise.
# Currently, node versions starting from v0.8.6 have a Solaris binary
# available.
nvm_node_version_has_solaris_binary() {
local NODE_VERSION
NODE_VERSION="$1"
# Error out if $NODE_VERSION is actually an io.js version
local STRIPPED_IOJS_VERSION
STRIPPED_IOJS_VERSION="$(nvm_strip_iojs_prefix "${NODE_VERSION}")"
if [ "_${STRIPPED_IOJS_VERSION}" != "_${NODE_VERSION}" ]; then
return 1
fi
# node (unmerged) started shipping Solaris binaries with v0.8.6 and
# node versions v1.0.0 or greater are not considered valid "unmerged" node
# versions.
nvm_version_greater_than_or_equal_to "${NODE_VERSION}" v0.8.6 \
&& ! nvm_version_greater_than_or_equal_to "${NODE_VERSION}" v1.0.0
}
# Succeeds if $VERSION represents a version (node, io.js or merged) that has a
# Solaris binary, fails otherwise.
nvm_has_solaris_binary() {
local VERSION="${1-}"
if nvm_is_merged_node_version "${VERSION}"; then
return 0 # All merged node versions have a Solaris binary
elif nvm_is_iojs_version "${VERSION}"; then
nvm_iojs_version_has_solaris_binary "${VERSION}"
else
nvm_node_version_has_solaris_binary "${VERSION}"
fi
}
# replaces every literal occurrence of $2 in $1 with $3; values go through the
# environment so awk does not interpret backslash escapes or regex characters
nvm_replace_literal() {
nvm_echo "${1-}" | NVM_FROM="${2-}" NVM_TO="${3-}" command awk '
BEGIN { from = ENVIRON["NVM_FROM"]; to = ENVIRON["NVM_TO"]; n = length(from) }
{
out = ""; s = $0
while (n > 0 && (i = index(s, from)) > 0) {
out = out substr(s, 1, i - 1) to
s = substr(s, i + n)
}
print out s
}'
}
nvm_sanitize_path() {
local SANITIZED_PATH
SANITIZED_PATH="${1-}"
if [ "_${SANITIZED_PATH}" != "_${NVM_DIR}" ]; then
SANITIZED_PATH="$(nvm_replace_literal "${SANITIZED_PATH}" "${NVM_DIR}" '${NVM_DIR}')"
fi
if [ "_${SANITIZED_PATH}" != "_${HOME}" ]; then
SANITIZED_PATH="$(nvm_replace_literal "${SANITIZED_PATH}" "${HOME}" '${HOME}')"
fi
nvm_echo "${SANITIZED_PATH}"
}
# Replace the `user:password@` part of any URL with `***@`, for printing.
# Like curl and wget, everything up to the last `@` before the path is userinfo.
nvm_sanitize_url() {
nvm_echo "${1-}" | command sed -e 's#://[^/[:space:]]*@#://***@#g'
}
nvm_is_natural_num() {
if [ -z "$1" ]; then
return 4
fi
case "$1" in
0) return 1 ;;
-*) return 3 ;; # some BSDs return false positives for double-negated args
*[!0-9]*) return 2 ;; # `-eq` also accepts signs and whitespace, and in ksh, any arithmetic expression
*)
[ "$1" -eq "$1" ] 2>/dev/null # returns 2 if it doesn't match
;;
esac
}
nvm_write_nvmrc() {
local VERSION_STRING
VERSION_STRING=$(nvm_version "${1-}")
if [ "${VERSION_STRING}" = '∞' ] || [ "${VERSION_STRING}" = 'N/A' ]; then
return 1
fi
# writing through a symlink would overwrite its target, which can be any file
if [ -L "$PWD"/.nvmrc ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "Warning: Not writing version number ($VERSION_STRING) to .nvmrc, because it is a symbolic link"
fi
return 3
fi
echo "${VERSION_STRING}" | tee "$PWD"/.nvmrc > /dev/null || {
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "Warning: Unable to write version number ($VERSION_STRING) to .nvmrc"
fi
return 3
}
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "Wrote version number ($VERSION_STRING) to .nvmrc"
fi
}
# Check version dir permissions
nvm_check_file_permissions() {
nvm_is_zsh && setopt local_options nonomatch
for FILE in "$1"/* "$1"/.[!.]* "$1"/..?* ; do
if [ -d "$FILE" ]; then
if [ -n "${NVM_DEBUG-}" ]; then
nvm_err "${FILE}"
fi
if [ ! -L "${FILE}" ] && ! nvm_check_file_permissions "${FILE}"; then
return 2
fi
elif [ -e "$FILE" ] && [ ! -w "$FILE" ] && [ -z "$(command find "${FILE}" -prune -user "$(command id -u)")" ]; then
# ^ file ownership check from https://www.shellcheck.net/wiki/SC3067
nvm_err "file is not writable or self-owned: $(nvm_sanitize_path "$FILE")"
return 1
fi
done
return 0
}
nvm_cache_dir() {
nvm_echo "${NVM_DIR}/.cache"
}
# Turn a version into a filesystem-safe lock name. Versions that reach here are
# already restricted to [0-9A-Za-z._+-], but be defensive about anything else.
nvm_install_lock_name() {
command printf '%s' "${1-}" | command tr -c '0-9A-Za-z._+-' '_'
}
# Acquire an advisory, per-version install lock so two concurrent
# `nvm install <same version>` runs cannot race on the same version directory
# (one removing/replacing it while the other reads or writes it). The lock is a
# directory created with `mkdir`, which is atomic across POSIX filesystems.
#
# Tunables (env vars):
# NVM_INSTALL_LOCK_TIMEOUT seconds to wait for a held lock (default 600)
# NVM_INSTALL_LOCK_STALE minutes after which a lock is assumed abandoned
# and stolen; 0 (default) never steals
#
# On success the lock path is recorded in NVM_INSTALL_LOCK for the matching
# nvm_release_install_lock.
nvm_acquire_install_lock() {
local VERSION
VERSION="${1-}"
if [ -z "${VERSION}" ]; then
return 0
fi
local LOCK_ROOT
LOCK_ROOT="$(nvm_cache_dir)/locks"
# If the lock directory can't be created, don't block the install over it.
command mkdir -p "${LOCK_ROOT}" 2>/dev/null || return 0
local LOCK
LOCK="${LOCK_ROOT}/$(nvm_install_lock_name "${VERSION}")"
local TIMEOUT
TIMEOUT="${NVM_INSTALL_LOCK_TIMEOUT:-600}"
local STALE
STALE="${NVM_INSTALL_LOCK_STALE:-0}"
local WAITED
WAITED=0
local ANNOUNCED
ANNOUNCED=0
while ! command mkdir "${LOCK}" 2>/dev/null; do
# Steal a lock left behind by a crashed install once it is old enough.
if [ "${STALE}" != '0' ] && [ -n "$(command find "${LOCK}" -maxdepth 0 -type d -mmin "+${STALE}" 2>/dev/null)" ]; then
nvm_err "Removing stale install lock for ${VERSION} (older than ${STALE} minute(s))"
command rm -rf "${LOCK}" 2>/dev/null
continue
fi
if [ "${WAITED}" -ge "${TIMEOUT}" ]; then
nvm_err "Timed out after ${TIMEOUT}s waiting for another install of ${VERSION} to finish."
nvm_err "If no other install is running, remove ${LOCK} and try again."
return 1
fi
if [ "${ANNOUNCED}" -eq 0 ]; then
nvm_err "Waiting for another install of ${VERSION} to finish..."
ANNOUNCED=1
fi
command sleep 1
WAITED=$((WAITED + 1))
done
NVM_INSTALL_LOCK="${LOCK}"
return 0
}
# Release the lock acquired by nvm_acquire_install_lock, if any.
nvm_release_install_lock() {
if [ -n "${NVM_INSTALL_LOCK-}" ]; then
command rmdir "${NVM_INSTALL_LOCK}" 2>/dev/null || command rm -rf "${NVM_INSTALL_LOCK}" 2>/dev/null || true
unset NVM_INSTALL_LOCK
fi
}
# args: pattern
# Lists versions available in the local cache (not yet installed).
# Returns version numbers like "v18.20.4", one per line, sorted.
nvm_ls_cached() {
local PATTERN
PATTERN="${1-}"
local NVM_CACHE_DIR
NVM_CACHE_DIR="$(nvm_cache_dir)"
local NVM_OS
NVM_OS="$(nvm_get_os)"
local NVM_ARCH
NVM_ARCH="$(nvm_get_arch)"
local SUFFIX
SUFFIX="${NVM_OS}-${NVM_ARCH}"
local NVM_CACHED_PATTERN
NVM_CACHED_PATTERN="$(nvm_ensure_version_prefix "${PATTERN%.}")"
# match dots literally, so that `20.1.1` does not also match `v20.111.1`
case "${NVM_CACHED_PATTERN}" in
'' | v) NVM_CACHED_PATTERN='.*' ;;
iojs- | iojs-v) NVM_CACHED_PATTERN='iojs-v.*' ;;
*) NVM_CACHED_PATTERN="$(nvm_echo "${NVM_CACHED_PATTERN}" | command sed 's/[][\.*^$]/\\&/g')" ;;
esac
# a release, like v27.0.0, is not one of its alphas
local NVM_CACHED_RELEASE
NVM_CACHED_RELEASE='v-'
case "${NVM_CACHED_PATTERN}" in
*-*) ;;
v[0-9]*.[0-9]*.[0-9]*) NVM_CACHED_RELEASE="${NVM_CACHED_PATTERN}" ;;
esac
{
if [ -d "${NVM_CACHE_DIR}/bin" ]; then
# shellcheck disable=SC2010
command ls -1 "${NVM_CACHE_DIR}/bin" \
| nvm_grep "^\\(node\\|iojs\\)-v[0-9][0-9.]*\\(-alpha\\.[0-9][0-9.]*\\)\\{0,1\\}-${SUFFIX}\$" \
| command sed "s/-${SUFFIX}\$//"
fi
if [ -d "${NVM_CACHE_DIR}/src" ]; then
# shellcheck disable=SC2010
command ls -1 "${NVM_CACHE_DIR}/src" \
| nvm_grep "^\\(node\\|iojs\\)-v[0-9][0-9.]*\\(-alpha\\.[0-9][0-9.]*\\)\\{0,1\\}\$"
fi
} \
| command sed 's/^node-//' \
| nvm_grep -w "${NVM_CACHED_PATTERN}" \
| nvm_grep -v "^${NVM_CACHED_RELEASE}-" \
| nvm_filter_installed_versions \
| nvm_sort_versions
}
# args: pattern
# Resolves a version pattern to a single version using only locally
# installed versions and cached downloads. No network access.
nvm_offline_version() {
local PATTERN
PATTERN="${1-}"
# First try locally installed versions
local VERSION
VERSION="$(nvm_version "${PATTERN}")"
if [ "_${VERSION}" != '_N/A' ]; then
nvm_echo "${VERSION}"
return 0
fi
# Then try cached downloads
VERSION="$(nvm_ls_cached "${PATTERN}" | command tail -1)"
if [ -n "${VERSION}" ]; then
nvm_echo "${VERSION}"
return 0
fi
nvm_echo 'N/A'
return 3
}
nvm() {
if [ "$#" -lt 1 ]; then
nvm --help
return
fi
local DEFAULT_IFS
DEFAULT_IFS=" $(nvm_echo t | command tr t \\t)
"
if [ "${-#*e}" != "$-" ]; then
set +e
local EXIT_CODE
local IFS
IFS="${DEFAULT_IFS}"
nvm "$@"
EXIT_CODE="$?"
set -e
return "$EXIT_CODE"
elif [ "${-#*a}" != "$-" ]; then
set +a
local EXIT_CODE
local IFS
IFS="${DEFAULT_IFS}"
nvm "$@"
EXIT_CODE="$?"
set -a
return "$EXIT_CODE"
elif [ -n "${BASH-}" ] && [ "${-#*E}" != "$-" ]; then
# shellcheck disable=SC3041
set +E
local EXIT_CODE
local IFS
IFS="${DEFAULT_IFS}"
nvm "$@"
EXIT_CODE="$?"
# shellcheck disable=SC3041
set -E
return "$EXIT_CODE"
elif [ "${IFS}" != "${DEFAULT_IFS}" ]; then
local IFS
IFS="${DEFAULT_IFS}"
nvm "$@"
return "$?"
fi
local i
for i in "$@"
do
case $i in
--) break ;;
'-h'|'help'|'--help')
NVM_NO_COLORS=""
for j in "$@"; do
if [ "${j}" = '--no-colors' ]; then
NVM_NO_COLORS="${j}"
break
fi
done
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
local NVM_NODE_PREFIX
NVM_NODE_PREFIX="$(nvm_node_prefix)"
NVM_VERSION="$(nvm --version)"
nvm_echo
nvm_echo "Node Version Manager (v${NVM_VERSION})"
nvm_echo
nvm_echo 'Note: <version> refers to any version-like string nvm understands. This includes:'
nvm_echo ' - full or partial version numbers, starting with an optional "v" (0.10, v0.1.2, v1)'
nvm_echo " - default (built-in) aliases: ${NVM_NODE_PREFIX}, stable, unstable, ${NVM_IOJS_PREFIX}, system"
nvm_echo ' - custom aliases you define with `nvm alias foo`'
nvm_echo
nvm_echo ' Any options that produce colorized output should respect the `--no-colors` option.'
nvm_echo
nvm_echo ' Every version belongs to one category: alpha, lts, non-lts, or iojs. Commands that select or list versions'
nvm_echo ' accept `--only=<categories>`, a comma-separated list of the categories to select from. It defaults to'
nvm_echo ' `$NVM_ONLY` when set, and otherwise to every category except alpha: `lts,non-lts,iojs`.'
nvm_echo
nvm_echo 'Usage:'
nvm_echo ' nvm --help Show this message'
nvm_echo ' --no-colors Suppress colored output'
nvm_echo ' nvm --version Print out the installed version of nvm'
nvm_echo ' nvm install [<version>] Download and install a <version>. Uses .nvmrc if version is omitted; otherwise errors.'
nvm_echo ' The following optional arguments, if provided, must appear directly after `nvm install`:'
nvm_echo ' -s Skip binary download, install from source only.'
nvm_echo ' -b Skip source download, install from binary only.'
nvm_echo ' (set NVM_NO_SOURCE_FALLBACK=1 to make this the default for every install)'
nvm_echo ' --reinstall-packages-from=<version> When installing, reinstall packages installed in <node|iojs|node version number>'
nvm_echo ' --lts When installing, only select from LTS (long-term support) versions'
nvm_echo ' --lts=<LTS name> When installing, only select from versions for a specific LTS line'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' --skip-default-packages When installing, skip the default-packages file if it exists'
nvm_echo ' --latest-npm After installing, attempt to upgrade to the latest working npm on the given node version'
nvm_echo ' --no-progress Disable the progress bar on any downloads'
nvm_echo ' --offline Install from cache only, without downloading anything'
nvm_echo ' --alias=<name> After installing, set the alias specified to the version specified. (same as: nvm alias <name> <version>)'
nvm_echo ' --default After installing, set default alias to the version specified. (same as: nvm alias default <version>)'
nvm_echo ' --save After installing, write the specified version to .nvmrc'
nvm_echo ' nvm uninstall <version> Uninstall a version'
nvm_echo ' nvm uninstall --lts Uninstall using automatic LTS (long-term support) alias `lts/*`, if available.'
nvm_echo ' nvm uninstall --lts=<LTS name> Uninstall using automatic alias for provided LTS line, if available.'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm use [current | <version>] Modify PATH to use <version>. Uses .nvmrc if version is omitted; otherwise errors.'
nvm_echo ' The following optional arguments, if provided, must appear directly after `nvm use`:'
nvm_echo ' --silent Silences stdout/stderr output'
nvm_echo ' --lts Uses automatic LTS (long-term support) alias `lts/*`, if available.'
nvm_echo ' --lts=<LTS name> Uses automatic alias for provided LTS line, if available.'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' --save Writes the specified version to .nvmrc.'
nvm_echo ' nvm exec [current | <version>] [<command>] Run <command> on <version>. Uses .nvmrc if version is omitted; otherwise errors.'
nvm_echo ' The following optional arguments, if provided, must appear directly after `nvm exec`:'
nvm_echo ' --silent Silences stdout/stderr output'
nvm_echo ' --lts Uses automatic LTS (long-term support) alias `lts/*`, if available.'
nvm_echo ' --lts=<LTS name> Uses automatic alias for provided LTS line, if available.'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm run [current | <version>] [<args>] Run `node` on <version> with <args> as arguments. Uses .nvmrc if version is omitted; otherwise errors.'
nvm_echo ' The following optional arguments, if provided, must appear directly after `nvm run`:'
nvm_echo ' --silent Silences stdout/stderr output'
nvm_echo ' --lts Uses automatic LTS (long-term support) alias `lts/*`, if available.'
nvm_echo ' --lts=<LTS name> Uses automatic alias for provided LTS line, if available.'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm current Display the active node version (resolved via $PATH; not affected by .nvmrc).'
nvm_echo ' nvm ls [<version>] List installed versions, matching a given <version> if provided'
nvm_echo ' --no-colors Suppress colored output'
nvm_echo ' --no-alias Suppress `nvm alias` output'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm ls-remote [<version>] List remote versions available for install, matching a given <version> if provided'
nvm_echo ' --lts When listing, only show LTS (long-term support) versions'
nvm_echo ' --lts=<LTS name> When listing, only show versions for a specific LTS line'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' --no-colors Suppress colored output'
nvm_echo ' nvm version <version> Resolve the given description to a single local version'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm version-remote <version> Resolve the given description to a single remote version'
nvm_echo ' --lts When listing, only select from LTS (long-term support) versions'
nvm_echo ' --lts=<LTS name> When listing, only select from versions for a specific LTS line'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm deactivate Undo effects of `nvm` on current shell'
nvm_echo ' --silent Silences stdout/stderr output'
nvm_echo ' nvm alias [<pattern>] Show all aliases beginning with <pattern>'
nvm_echo ' --no-colors Suppress colored output'
nvm_echo ' nvm alias <name> <version> Set an alias named <name> pointing to <version>'
nvm_echo ' --lts Only resolve to installed LTS (long-term support) versions'
nvm_echo ' --lts=<LTS name> Only resolve to installed versions of a specific LTS line'
nvm_echo ' --only=<categories> Only resolve to installed versions in these categories (see above)'
nvm_echo ' nvm unalias <name> Deletes the alias named <name>'
nvm_echo ' nvm install-latest-npm Attempt to upgrade to the latest working `npm` on the current node version'
nvm_echo ' nvm reinstall-packages <version> Reinstall global `npm` packages contained in <version> to current version'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm unload Unload `nvm` from shell'
nvm_echo ' nvm which [current | <version>] Display path to installed node version. Uses .nvmrc if version is omitted; otherwise errors.'
nvm_echo ' --silent Silences stdout/stderr output when a version is omitted'
nvm_echo ' --only=<categories> Only select from these version categories (see above)'
nvm_echo ' nvm cache dir Display path to the cache directory for nvm'
nvm_echo ' nvm cache clear Empty cache directory for nvm'
nvm_echo ' nvm set-colors [<color codes>] Set five text colors using format "yMeBg". Available when supported.'
nvm_print_color_legend
nvm_echo 'Example:'
nvm_echo ' nvm install 8.0.0 Install a specific version number'
nvm_echo ' nvm use 8.0 Use the latest available 8.0.x release'
nvm_echo ' nvm run 6.10.3 app.js Run app.js using node 6.10.3'
nvm_echo ' nvm exec 4.8.3 node app.js Run `node app.js` with the PATH pointing to node 4.8.3'
nvm_echo ' nvm alias default 8.1.0 Set default node version on a shell'
nvm_echo ' nvm alias default node Always default to the latest available node version on a shell'
nvm_echo
nvm_echo ' nvm install node Install the latest available version'
nvm_echo ' nvm use node Use the latest version'
nvm_echo ' nvm install --lts Install the latest LTS version'
nvm_echo ' nvm install --only=alpha 27 Install the latest alpha version of node 27'
nvm_echo ' nvm use --lts Use the latest LTS version'
nvm_echo
nvm_echo ' nvm set-colors cgYmW Set text colors to cyan, green, bold yellow, magenta, and white'
nvm_echo
nvm_echo 'Note:'
nvm_echo ' to remove, delete, or uninstall nvm - just remove the `$NVM_DIR` folder (usually `~/.nvm`)'
nvm_echo
return 0;
;;
esac
done
local COMMAND
COMMAND="${1-}"
shift
# initialize local variables
local VERSION
VERSION=''
local ADDITIONAL_PARAMETERS
ADDITIONAL_PARAMETERS=''
# the number of `--only=` arguments, and the last one's value
local NVM_ONLY_FLAG_COUNT
NVM_ONLY_FLAG_COUNT=0
local NVM_ONLY_FLAG
local NVM_ONLY_RESOLVED
case $COMMAND in
"cache")
case "${1-}" in
dir) nvm_cache_dir ;;
clear)
local DIR
DIR="$(nvm_cache_dir)"
if command rm -rf "${DIR}" && command mkdir -p "${DIR}"; then
nvm_echo 'nvm cache cleared.'
else
nvm_err "Unable to clear nvm cache: ${DIR}"
return 1
fi
;;
*)
nvm_err 'Usage: nvm cache dir'
nvm_err ' nvm cache clear'
nvm_err ' Run `nvm --help` for full help.'
return 127
;;
esac
;;
"debug")
local OS_VERSION
nvm_is_zsh && setopt local_options shwordsplit
nvm_err "nvm --version: v$(nvm --version)"
if [ -n "${TERM_PROGRAM-}" ]; then
nvm_err "\$TERM_PROGRAM: ${TERM_PROGRAM}"
fi
nvm_err "\$SHELL: ${SHELL}"
# shellcheck disable=SC2169,SC3028
nvm_err "\$SHLVL: ${SHLVL-}"
nvm_err "whoami: '$(whoami)'"
nvm_err "\${HOME}: ${HOME}"
nvm_err "\${NVM_DIR}: '$(nvm_sanitize_path "${NVM_DIR}")'"
nvm_err "\${PATH}: $(nvm_sanitize_path "${PATH}")"
nvm_err "\$PREFIX: '$(nvm_sanitize_path "${PREFIX-}")'"
nvm_err "\${NPM_CONFIG_PREFIX}: '$(nvm_sanitize_path "${NPM_CONFIG_PREFIX-}")'"
nvm_err "\$NVM_NODEJS_ORG_MIRROR: '$(nvm_sanitize_url "${NVM_NODEJS_ORG_MIRROR-}")'"
nvm_err "\$NVM_IOJS_ORG_MIRROR: '$(nvm_sanitize_url "${NVM_IOJS_ORG_MIRROR-}")'"
local NVM_SHELL_VERSION
# busybox's shells have no `--version`, and start an interactive shell instead
if command ls -l "$(command -v "${SHELL}" 2>/dev/null)" 2>/dev/null | nvm_grep -q busybox; then
NVM_SHELL_VERSION="$(${SHELL} --help 2>&1 </dev/null | command head -n 1)"
else
NVM_SHELL_VERSION="$(${SHELL} --version </dev/null | command head -n 1)"
fi
nvm_err "shell version: '${NVM_SHELL_VERSION}'"
nvm_err "uname -a: '$(command uname -a | command awk '{$2=""; print}' | command xargs)'"
nvm_err "checksum binary: '$(nvm_get_checksum_binary 2>/dev/null)'"
if [ "$(nvm_get_os)" = "darwin" ] && nvm_has sw_vers; then
OS_VERSION="$(sw_vers | command awk '{print $2}' | command xargs)"
elif [ -r "/etc/issue" ]; then
OS_VERSION="$(command head -n 1 /etc/issue | command sed 's/\\.//g')"
if [ -z "${OS_VERSION}" ] && [ -r "/etc/os-release" ]; then
# shellcheck disable=SC1091
OS_VERSION="$(. /etc/os-release && echo "${NAME}" "${VERSION}")"
fi
fi
if [ -n "${OS_VERSION}" ]; then
nvm_err "OS version: ${OS_VERSION}"
fi
if nvm_has "awk"; then
nvm_err "awk: $(nvm_command_info awk), $({ command awk --version 2>/dev/null || command awk -W version; } \
| command head -n 1)"
else
nvm_err "awk: not found"
fi
if nvm_has "curl"; then
nvm_err "curl: $(nvm_command_info curl), $(command curl -V | command head -n 1)"
else
nvm_err "curl: not found"
fi
if nvm_has "wget"; then
nvm_err "wget: $(nvm_command_info wget), $(command wget -V | command head -n 1)"
else
nvm_err "wget: not found"
fi
local TEST_TOOLS ADD_TEST_TOOLS
TEST_TOOLS="git grep"
ADD_TEST_TOOLS="sed cut basename rm mkdir xargs"
if [ "darwin" != "$(nvm_get_os)" ] && [ "freebsd" != "$(nvm_get_os)" ]; then
TEST_TOOLS="${TEST_TOOLS} ${ADD_TEST_TOOLS}"
else
for tool in ${ADD_TEST_TOOLS} ; do
if nvm_has "${tool}"; then
nvm_err "${tool}: $(nvm_command_info "${tool}")"
else
nvm_err "${tool}: not found"
fi
done
fi
for tool in ${TEST_TOOLS} ; do
local NVM_TOOL_VERSION
if nvm_has "${tool}"; then
if command ls -l "$(nvm_command_info "${tool}" | command awk '{print $1}')" | command grep -q busybox; then
NVM_TOOL_VERSION="$(command "${tool}" --help 2>&1 | command head -n 1)"
else
NVM_TOOL_VERSION="$(command "${tool}" --version 2>&1 | command head -n 1)"
fi
nvm_err "${tool}: $(nvm_command_info "${tool}"), ${NVM_TOOL_VERSION}"
else
nvm_err "${tool}: not found"
fi
unset NVM_TOOL_VERSION
done
unset TEST_TOOLS ADD_TEST_TOOLS
local NVM_DEBUG_OUTPUT
for NVM_DEBUG_COMMAND in 'nvm current' 'which node' 'which iojs' 'which npm' 'npm config get prefix' 'npm root -g'; do
NVM_DEBUG_OUTPUT="$(${NVM_DEBUG_COMMAND} 2>&1)"
nvm_err "${NVM_DEBUG_COMMAND}: $(nvm_sanitize_path "${NVM_DEBUG_OUTPUT}")"
done
return 42
;;
"install" | "i")
local version_not_provided
version_not_provided=0
local NVM_OS
NVM_OS="$(nvm_get_os)"
if [ $# -lt 1 ]; then
version_not_provided=1
fi
local nobinary
local nosource
local noprogress
local NVM_OFFLINE
nobinary=0
noprogress=0
nosource=0
NVM_OFFLINE=0
local LTS
LTS=''
local ALIAS
ALIAS=''
local NVM_UPGRADE_NPM
NVM_UPGRADE_NPM=0
local NVM_WRITE_TO_NVMRC
NVM_WRITE_TO_NVMRC=0
local PROVIDED_REINSTALL_PACKAGES_FROM
PROVIDED_REINSTALL_PACKAGES_FROM=''
local REINSTALL_PACKAGES_FROM
REINSTALL_PACKAGES_FROM=''
local SKIP_DEFAULT_PACKAGES
SKIP_DEFAULT_PACKAGES=''
while [ $# -ne 0 ]; do
case "$1" in
---*)
nvm_err 'arguments with `---` are not supported - this is likely a typo'
return 55;
;;
-s)
shift # consume "-s"
nobinary=1
if [ $nosource -eq 1 ]; then
nvm_err '-s and -b cannot be set together since they would skip install from both binary and source'
return 6
fi
;;
-b)
shift # consume "-b"
nosource=1
if [ $nobinary -eq 1 ]; then
nvm_err '-s and -b cannot be set together since they would skip install from both binary and source'
return 6
fi
;;
-j)
shift # consume "-j"
nvm_get_make_jobs "$1"
shift # consume job count
;;
--no-progress)
noprogress=1
shift
;;
--offline)
NVM_OFFLINE=1
shift
;;
--lts)
LTS='*'
shift
;;
--lts=*)
LTS="${1##--lts=}"
shift
;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
shift
;;
--latest-npm)
NVM_UPGRADE_NPM=1
shift
;;
--default)
if [ -n "${ALIAS-}" ]; then
nvm_err '--default and --alias are mutually exclusive, and may not be provided more than once'
return 6
fi
ALIAS='default'
shift
;;
--alias=*)
if [ -n "${ALIAS-}" ]; then
nvm_err '--default and --alias are mutually exclusive, and may not be provided more than once'
return 6
fi
ALIAS="${1##--alias=}"
shift
;;
--reinstall-packages-from=*)
if [ -n "${PROVIDED_REINSTALL_PACKAGES_FROM-}" ]; then
nvm_err '--reinstall-packages-from may not be provided more than once'
return 6
fi
PROVIDED_REINSTALL_PACKAGES_FROM="$(nvm_echo "$1" | command cut -c 27-)"
if [ -z "${PROVIDED_REINSTALL_PACKAGES_FROM}" ]; then
nvm_err 'If --reinstall-packages-from is provided, it must point to an installed version of node.'
return 6
fi
shift
;;
--copy-packages-from=*)
if [ -n "${PROVIDED_REINSTALL_PACKAGES_FROM-}" ]; then
nvm_err '--reinstall-packages-from may not be provided more than once, or combined with `--copy-packages-from`'
return 6
fi
PROVIDED_REINSTALL_PACKAGES_FROM="$(nvm_echo "$1" | command cut -c 22-)"
if [ -z "${PROVIDED_REINSTALL_PACKAGES_FROM}" ]; then
nvm_err 'If --copy-packages-from is provided, it must point to an installed version of node.'
return 6
fi
shift
;;
--reinstall-packages-from | --copy-packages-from)
nvm_err "If ${1} is provided, it must point to an installed version of node using \`=\`."
return 6
;;
--skip-default-packages)
SKIP_DEFAULT_PACKAGES=true
shift
;;
--save | -w)
if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then
nvm_err '--save and -w may only be provided once'
return 6
fi
NVM_WRITE_TO_NVMRC=1
shift
;;
*)
break # stop parsing args
;;
esac
done
# like `--reinstall-packages-from`, `--only` may also follow the version, but is needed to resolve it
local NVM_INSTALL_ARG
for NVM_INSTALL_ARG in "$@"; do
case "${NVM_INSTALL_ARG}" in
--only=*)
NVM_ONLY_FLAG="${NVM_INSTALL_ARG#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
esac
done
# validate early; it's resolved again once `lts/*` versions have set LTS
NVM_ONLY_RESOLVED="$(NVM_NO_LTS_STATUS=1 nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${LTS-}")" || return $?
# NVM_NO_SOURCE_FALLBACK=1 makes `nvm install` behave as if `-b` were always passed:
# a failed binary download aborts instead of silently falling back to a from-source compile.
# It is a persistent policy so callers need not thread `-b` through every invocation.
if [ "${NVM_NO_SOURCE_FALLBACK-}" = '1' ] && [ $nosource -ne 1 ]; then
if [ $nobinary -eq 1 ]; then
nvm_err '-s cannot be combined with NVM_NO_SOURCE_FALLBACK=1 since that would skip install from both binary and source'
return 6
fi
nosource=1
fi
if [ "${NVM_OFFLINE}" != 1 ] && ! nvm_has_executable "curl" && ! nvm_has_executable "wget"; then
nvm_err 'nvm needs curl or wget to proceed.'
return 1
fi
local provided_version
provided_version="${1-}"
if [ -z "${provided_version}" ]; then
if [ "_${LTS-}" = '_*' ]; then
nvm_echo 'Installing latest LTS version.'
if [ $# -gt 0 ]; then
shift
fi
elif [ "_${LTS-}" != '_' ]; then
nvm_echo "Installing with latest version of LTS line: ${LTS}"
if [ $# -gt 0 ]; then
shift
fi
else
{ provided_version="$(nvm_rc_version 3>&1 1>&4)"; } 4>&1
if [ $version_not_provided -eq 1 ] && [ -z "${provided_version}" ]; then
nvm_err 'Usage: nvm install [<version>]'
nvm_err ' Provide a <version>, or run from a directory containing an .nvmrc file.'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
fi
elif [ $# -gt 0 ]; then
shift
fi
case "${provided_version}" in
'lts/*')
LTS='*'
provided_version=''
;;
lts/*)
LTS="${provided_version##lts/}"
provided_version=''
;;
esac
# the version to reinstall packages from is already installed, so an LTS filter doesn't apply to it
# finding the version to install downloads index.tab, which records LTS status
local NVM_INSTALL_NO_LTS_STATUS
NVM_INSTALL_NO_LTS_STATUS=1
if [ "${NVM_OFFLINE}" = 1 ]; then
NVM_INSTALL_NO_LTS_STATUS=''
fi
local NVM_ONLY_INSTALLED
NVM_ONLY_INSTALLED="$(NVM_NO_LTS_STATUS="${NVM_INSTALL_NO_LTS_STATUS}" nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" '')" || return $?
NVM_ONLY_RESOLVED="$(NVM_NO_LTS_STATUS="${NVM_INSTALL_NO_LTS_STATUS}" nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${LTS-}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
local EXIT_CODE
if [ "${NVM_OFFLINE}" = 1 ]; then
local OFFLINE_PATTERN
OFFLINE_PATTERN="${provided_version}"
if [ -n "${LTS-}" ]; then
if [ "${LTS}" = '*' ]; then
OFFLINE_PATTERN="$(nvm_resolve_alias 'lts/*' 2>/dev/null || nvm_echo)"
else
OFFLINE_PATTERN="$(nvm_resolve_alias "lts/${LTS}" 2>/dev/null || nvm_echo)"
fi
if [ -z "${OFFLINE_PATTERN}" ]; then
nvm_err "LTS alias '${LTS}' not found locally. Run \`nvm ls-remote --lts\` first to populate LTS aliases."
return 3
fi
fi
VERSION="$(nvm_offline_version "${OFFLINE_PATTERN}")"
EXIT_CODE="$?"
else
VERSION="$(NVM_VERSION_ONLY=true NVM_LTS="${LTS-}" nvm_remote_version "${provided_version}")"
EXIT_CODE="$?"
fi
if [ "${VERSION}" = 'N/A' ] || [ $EXIT_CODE -ne 0 ]; then
local LTS_MSG
LTS_MSG=''
local REMOTE_CMD
if [ "${LTS-}" = '*' ]; then
LTS_MSG='(with LTS filter) '
REMOTE_CMD='nvm ls-remote --lts'
elif [ -n "${LTS-}" ]; then
LTS_MSG="(with LTS filter '${LTS}') "
REMOTE_CMD="nvm ls-remote --lts=${LTS}"
if [ -z "${provided_version}" ]; then
nvm_err "Version with LTS filter '${LTS}' not found - try \`${REMOTE_CMD}\` to browse available versions."
return 3
fi
else
if [ "${NVM_OFFLINE}" = 1 ]; then
REMOTE_CMD='nvm ls'
else
REMOTE_CMD='nvm ls-remote'
fi
fi
if [ "${NVM_OFFLINE}" = 1 ]; then
nvm_err "Version '${provided_version}' ${LTS_MSG-}not found locally or in cache - try \`${REMOTE_CMD}\` to browse available versions."
else
nvm_err "Version '${provided_version}' ${LTS_MSG-}not found - try \`${REMOTE_CMD}\` to browse available versions."
fi
# look again in only the categories that weren't selected
local NVM_EXCLUDED_CATEGORIES
NVM_EXCLUDED_CATEGORIES=''
local NVM_EXCLUDED_CATEGORY
for NVM_EXCLUDED_CATEGORY in alpha lts non-lts iojs; do
nvm_only_includes "${NVM_EXCLUDED_CATEGORY}" || NVM_EXCLUDED_CATEGORIES="${NVM_EXCLUDED_CATEGORIES:+${NVM_EXCLUDED_CATEGORIES},}${NVM_EXCLUDED_CATEGORY}"
done
# every alpha is a vN.0.0, so other versions can't match one
if [ "${NVM_EXCLUDED_CATEGORIES}" = 'alpha' ]; then
case "${provided_version#v}" in
*[!0-9.]*) ;;
*.*.*)
case "${provided_version#v}" in
*.0.0) ;;
*) NVM_EXCLUDED_CATEGORIES='' ;;
esac
;;
*.*)
case "${provided_version#v}" in
*.0) ;;
*) NVM_EXCLUDED_CATEGORIES='' ;;
esac
;;
esac
fi
if [ "${NVM_OFFLINE}" != 1 ] && [ -z "${LTS-}" ] && [ -n "${NVM_EXCLUDED_CATEGORIES}" ]; then
local NVM_EXCLUDED_VERSION
NVM_EXCLUDED_VERSION="$(NVM_ONLY_SELECTED="${NVM_EXCLUDED_CATEGORIES}" NVM_VERSION_ONLY=true nvm_remote_version "${provided_version}" 2>/dev/null)" ||:
if [ "_${NVM_EXCLUDED_VERSION:-N/A}" != '_N/A' ]; then
nvm_err "It matches ${NVM_EXCLUDED_VERSION}, which is excluded by the selected version categories (${NVM_ONLY_SELECTED})."
nvm_err 'Include its category with `--only=<categories>`, or in `$NVM_ONLY`.'
fi
fi
return 3
fi
ADDITIONAL_PARAMETERS=''
while [ $# -ne 0 ]; do
case "$1" in
--reinstall-packages-from=*)
if [ -n "${PROVIDED_REINSTALL_PACKAGES_FROM-}" ]; then
nvm_err '--reinstall-packages-from may not be provided more than once'
return 6
fi
PROVIDED_REINSTALL_PACKAGES_FROM="$(nvm_echo "$1" | command cut -c 27-)"
if [ -z "${PROVIDED_REINSTALL_PACKAGES_FROM}" ]; then
nvm_err 'If --reinstall-packages-from is provided, it must point to an installed version of node.'
return 6
fi
;;
--copy-packages-from=*)
if [ -n "${PROVIDED_REINSTALL_PACKAGES_FROM-}" ]; then
nvm_err '--reinstall-packages-from may not be provided more than once, or combined with `--copy-packages-from`'
return 6
fi
PROVIDED_REINSTALL_PACKAGES_FROM="$(nvm_echo "$1" | command cut -c 22-)"
if [ -z "${PROVIDED_REINSTALL_PACKAGES_FROM}" ]; then
nvm_err 'If --copy-packages-from is provided, it must point to an installed version of node.'
return 6
fi
;;
--reinstall-packages-from | --copy-packages-from)
nvm_err "If ${1} is provided, it must point to an installed version of node using \`=\`."
return 6
;;
--skip-default-packages)
SKIP_DEFAULT_PACKAGES=true
;;
--only=*) ;;
*)
ADDITIONAL_PARAMETERS="${ADDITIONAL_PARAMETERS} $1"
;;
esac
shift
done
if [ -n "${PROVIDED_REINSTALL_PACKAGES_FROM-}" ]; then
REINSTALL_PACKAGES_FROM="$(NVM_ONLY_SELECTED="${NVM_ONLY_INSTALLED}" nvm_version "${PROVIDED_REINSTALL_PACKAGES_FROM}")" ||:
fi
if [ -n "${PROVIDED_REINSTALL_PACKAGES_FROM-}" ] && [ "$(nvm_ensure_version_prefix "${PROVIDED_REINSTALL_PACKAGES_FROM}")" = "${VERSION}" ]; then
nvm_err "You can't reinstall global packages from the same version of node you're installing."
return 4
elif [ "${REINSTALL_PACKAGES_FROM-}" = 'N/A' ]; then
if NVM_ONLY_SELECTED="${NVM_ONLY_INSTALLED}" nvm_explain_excluded_version "${PROVIDED_REINSTALL_PACKAGES_FROM}"; then
return 5
fi
nvm_err "If --reinstall-packages-from is provided, it must point to an installed version of node."
return 5
fi
local FLAVOR
if nvm_is_iojs_version "${VERSION}"; then
FLAVOR="$(nvm_iojs_prefix)"
else
FLAVOR="$(nvm_node_prefix)"
fi
EXIT_CODE=0
if nvm_is_version_installed "${VERSION}" && nvm_validate_install "${VERSION}"; then
nvm_err "${VERSION} is already installed."
nvm use "${VERSION}"
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
if [ "${NVM_UPGRADE_NPM}" = 1 ]; then
nvm install-latest-npm
EXIT_CODE=$?
fi
if [ $EXIT_CODE -eq 0 ] && [ -z "${SKIP_DEFAULT_PACKAGES-}" ]; then
nvm_install_default_packages
fi
if [ $EXIT_CODE -eq 0 ] && [ -n "${REINSTALL_PACKAGES_FROM-}" ] && [ "_${REINSTALL_PACKAGES_FROM}" != "_N/A" ]; then
nvm reinstall-packages "--only=${NVM_ONLY_INSTALLED}" "${REINSTALL_PACKAGES_FROM}"
EXIT_CODE=$?
fi
fi
if [ -n "${LTS-}" ]; then
LTS="$(echo "${LTS}" | tr '[:upper:]' '[:lower:]')"
nvm_ensure_default_set "lts/${LTS}"
else
nvm_ensure_default_set "${provided_version}"
fi
if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then
nvm_write_nvmrc "${VERSION}"
EXIT_CODE=$?
fi
if [ $EXIT_CODE -eq 0 ] && [ -n "${ALIAS-}" ]; then
nvm alias "${ALIAS}" "${provided_version}"
EXIT_CODE=$?
fi
return $EXIT_CODE
fi
if [ -n "${NVM_INSTALL_THIRD_PARTY_HOOK-}" ]; then
nvm_err '** $NVM_INSTALL_THIRD_PARTY_HOOK env var set; dispatching to third-party installation method **'
local NVM_METHOD_PREFERENCE
NVM_METHOD_PREFERENCE='binary'
if [ $nobinary -eq 1 ]; then
NVM_METHOD_PREFERENCE='source'
fi
local VERSION_PATH
VERSION_PATH="$(nvm_version_path "${VERSION}")"
"${NVM_INSTALL_THIRD_PARTY_HOOK}" "${VERSION}" "${FLAVOR}" std "${NVM_METHOD_PREFERENCE}" "${VERSION_PATH}" || {
EXIT_CODE=$?
nvm_err '*** Third-party $NVM_INSTALL_THIRD_PARTY_HOOK env var failed to install! ***'
return $EXIT_CODE
}
if ! nvm_is_version_installed "${VERSION}"; then
nvm_err '*** Third-party $NVM_INSTALL_THIRD_PARTY_HOOK env var claimed to succeed, but failed to install! ***'
return 33
fi
EXIT_CODE=0
else
# Serialize concurrent installs of this version so two runs cannot race
# on its version directory (one replacing it while the other reads it).
if ! nvm_acquire_install_lock "${VERSION}"; then
return 1
fi
if [ "_${NVM_OS}" = "_freebsd" ]; then
# node.js and io.js do not have a FreeBSD binary
nobinary=1
nvm_err "Currently, there is no binary for FreeBSD"
elif [ "_$NVM_OS" = "_openbsd" ]; then
# node.js and io.js do not have a OpenBSD binary
nobinary=1
nvm_err "Currently, there is no binary for OpenBSD"
elif [ "_${NVM_OS}" = "_sunos" ]; then
# Not all node/io.js versions have a Solaris binary
if ! nvm_has_solaris_binary "${VERSION}"; then
nobinary=1
nvm_err "Currently, there is no binary of version ${VERSION} for SunOS"
fi
fi
# skip binary install if "nobinary" option specified.
if [ $nobinary -ne 1 ] && nvm_binary_available "${VERSION}"; then
NVM_NO_PROGRESS="${NVM_NO_PROGRESS:-${noprogress}}" NVM_OFFLINE="${NVM_OFFLINE}" nvm_install_binary "${FLAVOR}" std "${VERSION}" "${nosource}"
EXIT_CODE=$?
else
EXIT_CODE=-1
if [ $nosource -eq 1 ]; then
nvm_err "Binary download is not available for ${VERSION}"
EXIT_CODE=3
fi
fi
if [ $EXIT_CODE -ne 0 ] && [ $nosource -ne 1 ]; then
# `-j` was validated when parsed, but an inherited value was not
if ! nvm_is_natural_num "${NVM_MAKE_JOBS-}"; then
nvm_get_make_jobs "${NVM_MAKE_JOBS-}"
fi
if [ "_${NVM_OS}" = "_win" ]; then
nvm_err 'Installing from source on non-WSL Windows is not supported'
EXIT_CODE=87
else
NVM_NO_PROGRESS="${NVM_NO_PROGRESS:-${noprogress}}" NVM_OFFLINE="${NVM_OFFLINE}" nvm_install_source "${FLAVOR}" std "${VERSION}" "${NVM_MAKE_JOBS}" "${ADDITIONAL_PARAMETERS}"
EXIT_CODE=$?
fi
fi
nvm_release_install_lock
fi
if [ $EXIT_CODE -eq 0 ] && ! nvm_validate_install "${VERSION}"; then
nvm_err "The install of ${VERSION} reported success but failed verification; not activating it."
EXIT_CODE=1
fi
if [ $EXIT_CODE -eq 0 ]; then
if nvm_use_if_needed "${VERSION}" && nvm_install_npm_if_needed "${VERSION}"; then
if [ -n "${LTS-}" ]; then
nvm_ensure_default_set "lts/${LTS}"
else
nvm_ensure_default_set "${provided_version}"
fi
if [ "${NVM_UPGRADE_NPM}" = 1 ]; then
nvm install-latest-npm
EXIT_CODE=$?
fi
if [ $EXIT_CODE -eq 0 ] && [ -z "${SKIP_DEFAULT_PACKAGES-}" ]; then
nvm_install_default_packages
fi
if [ $EXIT_CODE -eq 0 ] && [ -n "${REINSTALL_PACKAGES_FROM-}" ] && [ "_${REINSTALL_PACKAGES_FROM}" != "_N/A" ]; then
nvm reinstall-packages "--only=${NVM_ONLY_INSTALLED}" "${REINSTALL_PACKAGES_FROM}"
EXIT_CODE=$?
fi
else
EXIT_CODE=$?
fi
fi
return $EXIT_CODE
;;
"uninstall")
local PATTERN
local NVM_UNINSTALL_ARGS
NVM_UNINSTALL_ARGS=0
while [ $# -ne 0 ]; do
case "${1}" in
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
*)
PATTERN="${1}"
NVM_UNINSTALL_ARGS=$((NVM_UNINSTALL_ARGS + 1))
;;
esac
shift
done
if [ "${NVM_UNINSTALL_ARGS}" -ne 1 ]; then
nvm_err 'Usage: nvm uninstall <version>'
nvm_err ' nvm uninstall --lts'
nvm_err ' nvm uninstall --lts=<LTS name>'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
case "${PATTERN}" in
--lts | --lts=* | lts/*)
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" '*')" || return $?
;;
*)
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" '')" || return $?
;;
esac
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
case "${PATTERN-}" in
--) ;;
--lts | 'lts/*')
VERSION="$(nvm_match_version "lts/*")"
;;
lts/*)
VERSION="$(nvm_match_version "lts/${PATTERN##lts/}")"
;;
--lts=*)
VERSION="$(nvm_match_version "lts/${PATTERN##--lts=}")"
;;
*)
VERSION="$(nvm_version "${PATTERN}")"
;;
esac
if [ "_${VERSION}" = "_$(nvm_ls_current)" ]; then
if nvm_is_iojs_version "${VERSION}"; then
nvm_err "nvm: Cannot uninstall currently-active io.js version, ${VERSION} (inferred from ${PATTERN})."
else
nvm_err "nvm: Cannot uninstall currently-active node version, ${VERSION} (inferred from ${PATTERN})."
fi
return 1
fi
if ! nvm_is_version_installed "${VERSION}"; then
if nvm_explain_excluded_version "${PATTERN}"; then
return 1
fi
local REQUESTED_VERSION
REQUESTED_VERSION="${PATTERN}"
if [ "_${VERSION}" != "_N/A" ] && [ "_${VERSION}" != "_${PATTERN}" ]; then
nvm_err "Version '${VERSION}' (inferred from ${PATTERN}) is not installed."
else
nvm_err "Version '${REQUESTED_VERSION}' is not installed."
fi
return
fi
local SLUG_BINARY
local SLUG_SOURCE
if nvm_is_iojs_version "${VERSION}"; then
SLUG_BINARY="$(nvm_get_download_slug iojs binary std "${VERSION}")"
SLUG_SOURCE="$(nvm_get_download_slug iojs source std "${VERSION}")"
else
SLUG_BINARY="$(nvm_get_download_slug node binary std "${VERSION}")"
SLUG_SOURCE="$(nvm_get_download_slug node source std "${VERSION}")"
fi
local NVM_SUCCESS_MSG
if nvm_is_iojs_version "${VERSION}"; then
NVM_SUCCESS_MSG="Uninstalled io.js $(nvm_strip_iojs_prefix "${VERSION}")"
else
NVM_SUCCESS_MSG="Uninstalled node ${VERSION}"
fi
local VERSION_PATH
VERSION_PATH="$(nvm_version_path "${VERSION}")"
if ! nvm_check_file_permissions "${VERSION_PATH}"; then
nvm_err 'Cannot uninstall, incorrect permissions on installation folder.'
nvm_err 'This is usually caused by running `npm install -g` as root. Run the following commands as root to fix the permissions and then try again.'
nvm_err
nvm_err " chown -R $(whoami) \"$(nvm_sanitize_path "${VERSION_PATH}")\""
nvm_err " chmod -R u+w \"$(nvm_sanitize_path "${VERSION_PATH}")\""
return 1
fi
# Delete all files related to target version.
local CACHE_DIR
CACHE_DIR="$(nvm_cache_dir)"
command rm -rf \
"${CACHE_DIR}/bin/${SLUG_BINARY}/files" \
"${CACHE_DIR}/src/${SLUG_SOURCE}/files" \
"${VERSION_PATH}" 2>/dev/null
nvm_echo "${NVM_SUCCESS_MSG}"
# rm any aliases that point to uninstalled version.
nvm_is_zsh && setopt local_options nonomatch
local NVM_ALIAS_FILE
local NVM_ALIAS_TARGET
for NVM_ALIAS_FILE in "$(nvm_alias_path)"/*; do
if [ ! -f "${NVM_ALIAS_FILE}" ]; then
continue
fi
NVM_ALIAS_TARGET="$(nvm_print_alias_file "${NVM_ALIAS_FILE}" | command head -n 1)"
# flags, like `--lts`, precede the target
while :; do
case "${NVM_ALIAS_TARGET}" in
--*' '*) NVM_ALIAS_TARGET="${NVM_ALIAS_TARGET#* }" ;;
*) break ;;
esac
done
if [ "_${NVM_ALIAS_TARGET}" = "_${VERSION}" ]; then
nvm unalias "$(command basename "${NVM_ALIAS_FILE}")"
fi
done
;;
"deactivate")
local NVM_SILENT
NVM_SILENT=''
while [ $# -ne 0 ]; do
case "${1}" in
--silent) NVM_SILENT=1 ;;
--) ;;
esac
shift
done
local NEWPATH
NEWPATH="$(nvm_strip_path "${PATH}" "/bin")"
if [ "_${PATH}" = "_${NEWPATH}" ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "Could not find ${NVM_DIR}/*/bin in \${PATH}"
fi
else
export PATH="${NEWPATH}"
nvm_hash_reset
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "${NVM_DIR}/*/bin removed from \${PATH}"
fi
fi
if [ -n "${MANPATH-}" ]; then
NEWPATH="$(nvm_strip_path "${MANPATH}" "/share/man")"
if [ "_${MANPATH}" = "_${NEWPATH}" ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "Could not find ${NVM_DIR}/*/share/man in \${MANPATH}"
fi
else
# `man` treats both of these as unset anyway, so leave nothing behind
case "${NEWPATH}" in
'' | ':') unset MANPATH ;;
*) export MANPATH="${NEWPATH}" ;;
esac
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "${NVM_DIR}/*/share/man removed from \${MANPATH}"
fi
fi
fi
if [ -n "${NODE_PATH-}" ]; then
NEWPATH="$(nvm_strip_path "${NODE_PATH}" "/lib/node_modules")"
if [ "_${NODE_PATH}" != "_${NEWPATH}" ]; then
export NODE_PATH="${NEWPATH}"
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "${NVM_DIR}/*/lib/node_modules removed from \${NODE_PATH}"
fi
fi
fi
unset NVM_BIN
unset NVM_INC
;;
"use")
local PROVIDED_VERSION
PROVIDED_VERSION=''
local NVM_SILENT
NVM_SILENT=''
local NVM_SILENT_ARG
NVM_SILENT_ARG=''
local NVM_DELETE_PREFIX
NVM_DELETE_PREFIX=0
local NVM_LTS
NVM_LTS=''
local IS_VERSION_FROM_NVMRC
IS_VERSION_FROM_NVMRC=0
local NVM_WRITE_TO_NVMRC
NVM_WRITE_TO_NVMRC=0
local NVM_USE_EXACT_INSTALLED
NVM_USE_EXACT_INSTALLED=0
while [ $# -ne 0 ]; do
case "$1" in
--silent)
NVM_SILENT=1
NVM_SILENT_ARG='--silent'
;;
--delete-prefix) NVM_DELETE_PREFIX=1 ;;
--)
if [ -n "${2-}" ]; then
PROVIDED_VERSION="$2"
fi
break
;;
--lts) NVM_LTS='*' ;;
--lts=*) NVM_LTS="${1##--lts=}" ;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
--save | -w)
if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then
nvm_err '--save and -w may only be provided once'
return 6
fi
NVM_WRITE_TO_NVMRC=1
;;
--*) ;;
*)
if [ -n "${1-}" ]; then
PROVIDED_VERSION="$1"
fi
;;
esac
shift
done
# an `lts/` version is an LTS selection, like `--lts`
local NVM_LTS_REQUEST
NVM_LTS_REQUEST=''
case "${PROVIDED_VERSION-}" in
lts/*) NVM_LTS_REQUEST='*' ;;
esac
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_LTS:-${NVM_LTS_REQUEST}}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
if [ -n "${NVM_LTS-}" ]; then
VERSION="$(nvm_match_version "lts/${NVM_LTS:-*}")"
elif [ -z "${PROVIDED_VERSION-}" ]; then
{ PROVIDED_VERSION="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1
if [ -n "${PROVIDED_VERSION}" ]; then
IS_VERSION_FROM_NVMRC=1
nvm_select_lts_from_nvmrc "${PROVIDED_VERSION}" || return $?
VERSION="$(nvm_version "${PROVIDED_VERSION}")"
fi
if [ -z "${VERSION}" ]; then
nvm_err 'Please see `nvm --help` or https://github.com/nvm-sh/nvm#nvmrc for more information.'
return 127
fi
elif nvm_is_installed_exact_version "${PROVIDED_VERSION}"; then
VERSION="${PROVIDED_VERSION}"
NVM_USE_EXACT_INSTALLED=1
else
VERSION="$(nvm_match_version "${PROVIDED_VERSION}")"
fi
# a version that resolved, maybe through an alias with its own flags, to an installed one is used as is
if nvm_is_version_installed "${VERSION}"; then
NVM_USE_EXACT_INSTALLED=1
fi
if [ -z "${VERSION}" ]; then
nvm_err 'Usage: nvm use [<version>]'
nvm_err ' Provide a <version>, or run from a directory containing an .nvmrc file.'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then
nvm_write_nvmrc "${VERSION}"
# .nvmrc can't store the categories that selected this version
if ! NVM_ONLY_SELECTED='' nvm_is_version_selected "${VERSION}" 2>/dev/null; then
nvm_err "Warning: ${VERSION} is not in the default version categories (${NVM_ONLY:-lts,non-lts,iojs}), so using .nvmrc needs \`--only=\`, or \`\$NVM_ONLY\`, to include it."
fi
fi
if [ "_${VERSION}" = '_system' ]; then
if nvm_has_system_node && nvm deactivate "${NVM_SILENT_ARG-}" >/dev/null 2>&1; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "Now using system version of node: $(node -v 2>/dev/null)$(nvm_print_npm_version)"
fi
return
elif nvm_has_system_iojs && nvm deactivate "${NVM_SILENT_ARG-}" >/dev/null 2>&1; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "Now using system version of io.js: $(iojs --version 2>/dev/null)$(nvm_print_npm_version)"
fi
return
elif [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err 'System version of node not found.'
fi
return 127
elif [ "_${VERSION}" = '_∞' ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err "The alias \"${PROVIDED_VERSION}\" leads to an infinite loop. Aborting."
fi
return 8
fi
if [ "${VERSION}" = 'N/A' ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_ensure_version_installed "${PROVIDED_VERSION}" "${IS_VERSION_FROM_NVMRC}"
fi
return 3
# an exact, already-installed version needs no further resolution or checks
elif [ "${NVM_USE_EXACT_INSTALLED}" -ne 1 ]; then
nvm_ensure_version_installed "${VERSION}" "${IS_VERSION_FROM_NVMRC}" || return $?
fi
local NVM_VERSION_DIR
NVM_VERSION_DIR="$(nvm_version_path "${VERSION}")"
# Change current version
PATH="$(nvm_change_path "${PATH}" "/bin" "${NVM_VERSION_DIR}")"
if nvm_has manpath; then
MANPATH="$(nvm_change_path "${MANPATH-}" "/share/man" "${NVM_VERSION_DIR}")"
# `man` consults its configured default path only where the list has an
# empty entry; a trailing one keeps nvm's directory ahead of it
case "${MANPATH}" in
:* | *::* | *:) ;;
*) MANPATH="${MANPATH}:" ;;
esac
export MANPATH
fi
export PATH
nvm_hash_reset
export NVM_BIN="${NVM_VERSION_DIR}/bin"
export NVM_INC="${NVM_VERSION_DIR}/include/node"
if [ "${NVM_SYMLINK_CURRENT-}" = true ]; then
command rm -f "${NVM_DIR}/current" && ln -s "${NVM_VERSION_DIR}" "${NVM_DIR}/current"
fi
local NVM_USE_OUTPUT
NVM_USE_OUTPUT=''
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
if nvm_is_iojs_version "${VERSION}"; then
NVM_USE_OUTPUT="Now using io.js $(nvm_strip_iojs_prefix "${VERSION}")$(nvm_print_npm_version)"
else
NVM_USE_OUTPUT="Now using node ${VERSION}$(nvm_print_npm_version)"
fi
fi
if [ "_${VERSION}" != "_system" ]; then
local NVM_USE_CMD
NVM_USE_CMD="nvm use --delete-prefix"
if [ -n "${PROVIDED_VERSION}" ]; then
NVM_USE_CMD="${NVM_USE_CMD} ${VERSION}"
fi
if [ "${NVM_SILENT:-0}" -eq 1 ]; then
NVM_USE_CMD="${NVM_USE_CMD} --silent"
fi
if ! nvm_die_on_prefix "${NVM_DELETE_PREFIX}" "${NVM_USE_CMD}" "${NVM_VERSION_DIR}"; then
return 11
fi
fi
if [ -n "${NVM_USE_OUTPUT-}" ] && [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_echo "${NVM_USE_OUTPUT}"
fi
;;
"run")
local provided_version
provided_version=''
local has_checked_nvmrc
has_checked_nvmrc=0
local IS_VERSION_FROM_NVMRC
IS_VERSION_FROM_NVMRC=0
# run given version of node
local NVM_SILENT
NVM_SILENT=''
local NVM_SILENT_ARG
NVM_SILENT_ARG=''
local NVM_LTS
NVM_LTS=''
while [ $# -gt 0 ]; do
case "$1" in
--silent)
NVM_SILENT=1
NVM_SILENT_ARG='--silent'
shift
;;
--lts) NVM_LTS='*' ; shift ;;
--lts=*) NVM_LTS="${1##--lts=}" ; shift ;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
shift
;;
*)
if [ -n "$1" ]; then
break
else
shift
fi
;; # stop processing arguments
esac
done
# an `lts/` version is an LTS selection, like `--lts`
local NVM_LTS_REQUEST
NVM_LTS_REQUEST=''
case "${1-}" in
lts/*) NVM_LTS_REQUEST='*' ;;
esac
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_LTS:-${NVM_LTS_REQUEST}}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
if [ $# -lt 1 ] && [ -z "${NVM_LTS-}" ]; then
local NVM_RC_VERSION
NVM_RC_VERSION=''
{ NVM_RC_VERSION="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1 && has_checked_nvmrc=1
if [ -n "${NVM_RC_VERSION}" ]; then
nvm_select_lts_from_nvmrc "${NVM_RC_VERSION}" || return $?
VERSION="$(nvm_version "${NVM_RC_VERSION}")" ||:
fi
if [ "${VERSION:-N/A}" = 'N/A' ]; then
if [ -n "${NVM_RC_VERSION}" ] && nvm_explain_excluded_version "${NVM_RC_VERSION}"; then
return 127
fi
nvm_err 'Usage: nvm run [<version>] [<args>]'
nvm_err ' Provide a <version>, or run from a directory containing an .nvmrc file.'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
fi
if [ -z "${NVM_LTS-}" ]; then
provided_version="$1"
if [ -n "${provided_version}" ]; then
VERSION="$(nvm_version "${provided_version}")" ||:
if [ "_${VERSION:-N/A}" = '_N/A' ] && ! nvm_is_valid_version "${provided_version}"; then
provided_version=''
if [ $has_checked_nvmrc -ne 1 ]; then
{ NVM_RC_VERSION="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1 && has_checked_nvmrc=1
fi
if [ -z "${NVM_RC_VERSION-}" ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err 'WARNING: `nvm run` was invoked without a version argument and without an .nvmrc file.'
nvm_err ' Falling back to the active node version; this will become an error in a future release.'
nvm_err ' Pass `current` explicitly (e.g. `nvm run current ...`) to silence this warning.'
fi
NVM_RC_VERSION="$(nvm_version current)" ||:
fi
provided_version="${NVM_RC_VERSION}"
IS_VERSION_FROM_NVMRC=1
nvm_select_lts_from_nvmrc "${NVM_RC_VERSION}" || return $?
VERSION="$(nvm_version "${NVM_RC_VERSION}")" ||:
else
shift
fi
fi
fi
local NVM_IOJS
NVM_IOJS=''
if nvm_is_iojs_version "${VERSION}"; then
NVM_IOJS=true
fi
local EXIT_CODE
nvm_is_zsh && setopt local_options shwordsplit
local LTS_ARG
LTS_ARG=''
if [ -n "${NVM_LTS-}" ]; then
LTS_ARG="--lts=${NVM_LTS-}"
VERSION=''
fi
if [ -n "${VERSION}" ] && [ "_${VERSION}" != '_N/A' ]; then
# the version is selected, maybe by an alias's own flags, so using it needs no other check
NVM_ONLY_SELECTED='alpha,lts,non-lts,iojs'
fi
if [ "_${VERSION}" = "_N/A" ]; then
nvm_ensure_version_installed "${provided_version}" "${IS_VERSION_FROM_NVMRC}"
elif [ "${NVM_IOJS}" = true ]; then
nvm exec "${NVM_SILENT_ARG-}" "${LTS_ARG-}" "${VERSION}" iojs "$@"
else
nvm exec "${NVM_SILENT_ARG-}" "${LTS_ARG-}" "${VERSION}" node "$@"
fi
EXIT_CODE="$?"
return $EXIT_CODE
;;
"exec")
local NVM_SILENT
NVM_SILENT=''
local NVM_LTS
NVM_LTS=''
while [ $# -gt 0 ]; do
case "$1" in
--silent) NVM_SILENT=1 ; shift ;;
--lts) NVM_LTS='*' ; shift ;;
--lts=*) NVM_LTS="${1##--lts=}" ; shift ;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
shift
;;
--) break ;;
--*)
nvm_err "Unsupported option \"$1\"."
return 55
;;
*)
if [ -n "$1" ]; then
break
else
shift
fi
;; # stop processing arguments
esac
done
# an `lts/` version is an LTS selection, like `--lts`
local NVM_LTS_REQUEST
NVM_LTS_REQUEST=''
case "${1-}" in
lts/*) NVM_LTS_REQUEST='*' ;;
esac
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_LTS:-${NVM_LTS_REQUEST}}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
local provided_version
provided_version="$1"
local VERSION_SOURCE
VERSION_SOURCE=''
if [ "${NVM_LTS-}" != '' ]; then
provided_version="lts/${NVM_LTS:-*}"
VERSION="${provided_version}"
VERSION_SOURCE='lts'
elif [ -n "${provided_version}" ]; then
VERSION="$(nvm_version "${provided_version}")" ||:
if [ "_${VERSION}" = '_N/A' ] && ! nvm_is_valid_version "${provided_version}"; then
{ provided_version="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1 && has_checked_nvmrc=1
nvm_select_lts_from_nvmrc "${provided_version}" || return $?
VERSION="$(nvm_version "${provided_version}")" ||:
if [ -n "${provided_version}" ]; then
VERSION_SOURCE='nvmrc'
fi
else
VERSION_SOURCE='arg'
shift
fi
fi
if [ -z "${VERSION_SOURCE}" ]; then
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
nvm_err 'WARNING: `nvm exec` was invoked without a version argument and without an .nvmrc file.'
nvm_err ' Falling back to the active node version; this will become an error in a future release.'
nvm_err ' Pass `current` explicitly (e.g. `nvm exec current ...`) to silence this warning.'
fi
provided_version='current'
VERSION="$(nvm_version current)" ||:
fi
nvm_ensure_version_installed "${provided_version}"
EXIT_CODE=$?
if [ "${EXIT_CODE}" != "0" ]; then
# shellcheck disable=SC2086
return $EXIT_CODE
fi
# the version is selected, maybe by an alias's own flags, so using it needs no other check
NVM_ONLY_SELECTED='alpha,lts,non-lts,iojs'
if [ "${NVM_SILENT:-0}" -ne 1 ]; then
if [ "${NVM_LTS-}" = '*' ]; then
nvm_echo "Running node latest LTS -> $(nvm_version "${VERSION}")$(nvm use --silent "${VERSION}" && nvm_print_npm_version)"
elif [ -n "${NVM_LTS-}" ]; then
nvm_echo "Running node LTS \"${NVM_LTS-}\" -> $(nvm_version "${VERSION}")$(nvm use --silent "${VERSION}" && nvm_print_npm_version)"
elif nvm_is_iojs_version "${VERSION}"; then
nvm_echo "Running io.js $(nvm_strip_iojs_prefix "${VERSION}")$(nvm use --silent "${VERSION}" && nvm_print_npm_version)"
else
nvm_echo "Running node ${VERSION}$(nvm use --silent "${VERSION}" && nvm_print_npm_version)"
fi
fi
NVM_ONLY_SELECTED="${NVM_ONLY_SELECTED}" NODE_VERSION="${VERSION}" "${NVM_DIR}/nvm-exec" "$@"
;;
"ls" | "list")
local PATTERN
PATTERN=''
local NVM_NO_COLORS
NVM_NO_COLORS=''
local NVM_NO_ALIAS
NVM_NO_ALIAS=''
while [ $# -gt 0 ]; do
case "${1}" in
--) ;;
--no-colors) NVM_NO_COLORS="${1}" ;;
--no-alias) NVM_NO_ALIAS="${1}" ;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
--*)
nvm_err "Unsupported option \"${1}\"."
return 55
;;
*)
PATTERN="${PATTERN:-$1}"
;;
esac
shift
done
if [ -n "${PATTERN-}" ] && [ -n "${NVM_NO_ALIAS-}" ]; then
nvm_err '`--no-alias` is not supported when a pattern is provided.'
return 55
fi
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
local NVM_LS_OUTPUT
local NVM_LS_EXIT_CODE
NVM_LS_OUTPUT=$(nvm_ls "${PATTERN-}")
NVM_LS_EXIT_CODE=$?
NVM_NO_COLORS="${NVM_NO_COLORS-}" nvm_print_versions "${NVM_LS_OUTPUT}"
if [ -z "${NVM_NO_ALIAS-}" ] && [ -z "${PATTERN-}" ]; then
if [ -n "${NVM_NO_COLORS-}" ]; then
nvm alias --no-colors
else
nvm alias
fi
fi
return $NVM_LS_EXIT_CODE
;;
"ls-remote" | "list-remote")
local NVM_LTS
NVM_LTS=''
local PATTERN
PATTERN=''
local NVM_NO_COLORS
NVM_NO_COLORS=''
while [ $# -gt 0 ]; do
case "${1-}" in
--) ;;
--lts)
NVM_LTS='*'
;;
--lts=*)
NVM_LTS="${1##--lts=}"
;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
--no-colors) NVM_NO_COLORS="${1}" ;;
--*)
nvm_err "Unsupported option \"${1}\"."
return 55
;;
*)
if [ -z "${PATTERN-}" ]; then
PATTERN="${1-}"
if [ -z "${NVM_LTS-}" ]; then
case "${PATTERN}" in
'lts/*')
NVM_LTS='*'
PATTERN=''
;;
lts/*)
NVM_LTS="${PATTERN##lts/}"
PATTERN=''
;;
esac
fi
fi
;;
esac
shift
done
NVM_ONLY_RESOLVED="$(NVM_NO_LTS_STATUS=1 nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_LTS-}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
local NVM_OUTPUT
local EXIT_CODE
NVM_OUTPUT="$(NVM_LTS="${NVM_LTS-}" nvm_remote_versions "${PATTERN-}" &&:)"
EXIT_CODE=$?
if [ -n "${NVM_OUTPUT}" ]; then
local NVM_REMOTE_LATEST_ALIAS
NVM_REMOTE_LATEST_ALIAS=''
local NVM_REMOTE_NAMED_ALIASES
NVM_REMOTE_NAMED_ALIASES=''
if [ "${EXIT_CODE}" -eq 0 ] && [ -z "${NVM_LTS-}" ] && [ -z "${PATTERN-}" ]; then
NVM_REMOTE_LATEST_ALIAS="$(nvm_node_prefix)"
NVM_REMOTE_NAMED_ALIASES="$(nvm_get_remote_aliases)"
fi
NVM_NO_COLORS="${NVM_NO_COLORS-}" nvm_print_versions "${NVM_OUTPUT}" "${NVM_REMOTE_LATEST_ALIAS}" "${NVM_REMOTE_NAMED_ALIASES}"
return $EXIT_CODE
fi
NVM_NO_COLORS="${NVM_NO_COLORS-}" nvm_print_versions "N/A"
return 3
;;
"current")
nvm_version current
;;
"which")
local NVM_SILENT
NVM_SILENT=''
local provided_version
provided_version=''
while [ $# -ne 0 ]; do
case "${1}" in
--silent) NVM_SILENT=1 ;;
--) ;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
*) provided_version="${1-}" ;;
esac
shift
done
# an `lts/` version is an LTS selection, like `--lts`
local NVM_LTS_REQUEST
NVM_LTS_REQUEST=''
case "${provided_version-}" in
lts/*) NVM_LTS_REQUEST='*' ;;
esac
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_LTS_REQUEST}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
if [ -z "${provided_version-}" ]; then
{ provided_version="$(NVM_SILENT="${NVM_SILENT:-0}" nvm_rc_version 3>&1 1>&4)"; } 4>&1
if [ -n "${provided_version}" ]; then
nvm_select_lts_from_nvmrc "${provided_version}" || return $?
VERSION=$(nvm_version "${provided_version}") ||:
fi
elif [ "${provided_version}" != 'system' ]; then
VERSION="$(nvm_version "${provided_version}")" ||:
else
VERSION="${provided_version-}"
fi
if [ -z "${VERSION}" ]; then
nvm_err 'Usage: nvm which [current | <version>]'
nvm_err ' Provide a <version>, or run from a directory containing an .nvmrc file.'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
if [ "_${VERSION}" = '_system' ]; then
if nvm_has_system_iojs >/dev/null 2>&1 || nvm_has_system_node >/dev/null 2>&1; then
local NVM_BIN
NVM_BIN="$(nvm use system >/dev/null 2>&1 && command which node)"
if [ -n "${NVM_BIN}" ]; then
nvm_echo "${NVM_BIN}"
return
fi
return 1
fi
nvm_err 'System version of node not found.'
return 127
elif [ "${VERSION}" = '∞' ]; then
nvm_err "The alias \"${provided_version}\" leads to an infinite loop. Aborting."
return 8
fi
nvm_ensure_version_installed "${provided_version}"
EXIT_CODE=$?
if [ "${EXIT_CODE}" != "0" ]; then
# shellcheck disable=SC2086
return $EXIT_CODE
fi
local NVM_VERSION_DIR
NVM_VERSION_DIR="$(nvm_version_path "${VERSION}")"
nvm_echo "${NVM_VERSION_DIR}/bin/node"
;;
"alias")
local NVM_ALIAS_DIR
NVM_ALIAS_DIR="$(nvm_alias_path)"
local NVM_CURRENT
NVM_CURRENT="$(nvm_ls_current)"
command mkdir -p "${NVM_ALIAS_DIR}/lts"
local ALIAS
local TARGET
local NVM_NO_COLORS
NVM_NO_COLORS=''
local NVM_ALIAS_FLAGS
NVM_ALIAS_FLAGS=''
ALIAS='--'
TARGET='--'
while [ $# -gt 0 ]; do
case "${1-}" in
--) ;;
--no-colors) NVM_NO_COLORS="${1}" ;;
--lts=)
nvm_err '`--lts=` needs an LTS name.'
return 55
;;
--lts | --lts=*)
if [ -n "${NVM_ALIAS_FLAGS}" ]; then
nvm_err '`--lts` may only be provided once.'
return 55
fi
case "${1#--lts=}" in
*[!abcdefghijklmnopqrstuvwxyz0123456789._-]*)
nvm_err 'LTS names must be lowercase'
return 3
;;
esac
NVM_ALIAS_FLAGS="${1}"
;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
--*)
nvm_err "Unsupported option \"${1}\"."
return 55
;;
*)
if [ "${ALIAS}" = '--' ]; then
ALIAS="${1-}"
elif [ "${TARGET}" = '--' ]; then
TARGET="${1-}"
fi
;;
esac
shift
done
# resolving the alias's target checks for recorded LTS status, if it needs it
NVM_ONLY_RESOLVED="$(NVM_NO_LTS_STATUS=1 nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_ALIAS_FLAGS}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
if [ -z "${TARGET}" ]; then
# for some reason the empty string was explicitly passed as the target
# so, unalias it.
nvm unalias "${ALIAS}"
return $?
elif echo "${ALIAS}" | grep -q "#"; then
nvm_err 'Aliases with a comment delimiter (#) are not supported.'
return 1
elif [ "${TARGET}" != '--' ]; then
# a target was passed: create an alias
if [ "${ALIAS#*\/}" != "${ALIAS}" ]; then
nvm_err 'Aliases in subdirectories are not supported.'
return 1
fi
if [ "${NVM_ONLY_FLAG_COUNT}" -gt 0 ]; then
NVM_ALIAS_FLAGS="--only=$(nvm_normalize_only "${NVM_ONLY_FLAG}" '`--only`')${NVM_ALIAS_FLAGS:+ ${NVM_ALIAS_FLAGS}}"
fi
TARGET="${NVM_ALIAS_FLAGS:+${NVM_ALIAS_FLAGS} }${TARGET}"
VERSION="$(nvm_version "${TARGET}")" ||:
if [ "${VERSION}" = 'N/A' ] && ! nvm_explain_excluded_version "${TARGET}"; then
nvm_err "! WARNING: Version '${TARGET}' does not exist."
fi
nvm_make_alias "${ALIAS}" "${TARGET}"
NVM_NO_COLORS="${NVM_NO_COLORS-}" NVM_CURRENT="${NVM_CURRENT-}" DEFAULT=false nvm_print_formatted_alias "${ALIAS}" "${TARGET}" "${VERSION}"
elif [ -n "${NVM_ALIAS_FLAGS}" ]; then
nvm_err "\`${NVM_ALIAS_FLAGS}\` needs a target version, like \`nvm alias ${ALIAS#--} ${NVM_ALIAS_FLAGS} node\`."
return 55
else
if [ "${ALIAS-}" = '--' ]; then
unset ALIAS
fi
nvm_list_aliases "${ALIAS-}"
fi
;;
"unalias")
local NVM_ALIAS_DIR
NVM_ALIAS_DIR="$(nvm_alias_path)"
command mkdir -p "${NVM_ALIAS_DIR}"
if [ $# -ne 1 ]; then
nvm_err 'Usage: nvm unalias <name>'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
if [ "${1#*\/}" != "${1-}" ]; then
nvm_err 'Aliases in subdirectories are not supported.'
return 1
fi
local NVM_IOJS_PREFIX
local NVM_NODE_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
NVM_NODE_PREFIX="$(nvm_node_prefix)"
local NVM_ALIAS_EXISTS
NVM_ALIAS_EXISTS=0
if [ -f "${NVM_ALIAS_DIR}/${1-}" ]; then
NVM_ALIAS_EXISTS=1
fi
if [ $NVM_ALIAS_EXISTS -eq 0 ]; then
case "$1" in
"stable" | "unstable" | "${NVM_IOJS_PREFIX}" | "${NVM_NODE_PREFIX}" | "system")
nvm_err "${1-} is a default (built-in) alias and cannot be deleted."
return 1
;;
esac
nvm_err "Alias ${1-} doesn't exist!"
return
fi
local NVM_ALIAS_ORIGINAL
NVM_ALIAS_ORIGINAL="$(nvm_alias "${1}")"
command rm -f "${NVM_ALIAS_DIR}/${1}"
# flags, like `--lts`, are separate arguments, before the quoted target
local NVM_ALIAS_ORIGINAL_FLAGS
NVM_ALIAS_ORIGINAL_FLAGS=''
while :; do
case "${NVM_ALIAS_ORIGINAL}" in
--*' '*)
NVM_ALIAS_ORIGINAL_FLAGS="${NVM_ALIAS_ORIGINAL_FLAGS}${NVM_ALIAS_ORIGINAL%% *} "
NVM_ALIAS_ORIGINAL="${NVM_ALIAS_ORIGINAL#* }"
;;
*) break ;;
esac
done
nvm_echo "Deleted alias ${1} - restore it with \`nvm alias \"${1}\" ${NVM_ALIAS_ORIGINAL_FLAGS}\"${NVM_ALIAS_ORIGINAL}\"\`"
;;
"install-latest-npm")
if [ $# -ne 0 ]; then
nvm_err 'Usage: nvm install-latest-npm'
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
nvm_install_latest_npm
;;
"reinstall-packages" | "copy-packages")
local PROVIDED_VERSION
local NVM_REINSTALL_ARGS
NVM_REINSTALL_ARGS=0
while [ $# -ne 0 ]; do
case "${1}" in
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
*)
PROVIDED_VERSION="${1}"
NVM_REINSTALL_ARGS=$((NVM_REINSTALL_ARGS + 1))
;;
esac
shift
done
if [ "${NVM_REINSTALL_ARGS}" -ne 1 ]; then
nvm_err "Usage: nvm ${COMMAND} <version>"
nvm_err ' Run `nvm --help` for full help.'
return 127
fi
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
if [ "${PROVIDED_VERSION}" = "$(nvm_ls_current)" ] || [ "$(nvm_version "${PROVIDED_VERSION}" ||:)" = "$(nvm_ls_current)" ]; then
nvm_err 'Can not reinstall packages from the current version of node.'
return 2
fi
if [ "_${PROVIDED_VERSION}" = "_system" ]; then
if ! nvm_has_system_node && ! nvm_has_system_iojs; then
nvm_err 'No system version of node or io.js detected.'
return 3
fi
VERSION="system"
else
VERSION="$(nvm_version "${PROVIDED_VERSION}")" ||:
if [ "_${VERSION}" = '_N/A' ] && nvm_explain_excluded_version "${PROVIDED_VERSION}"; then
return 3
fi
fi
local NPMLIST
NPMLIST="$(nvm_npm_global_modules "${VERSION}")"
local INSTALLS
local LINKS
INSTALLS="${NPMLIST%% //// *}"
LINKS="${NPMLIST##* //// }"
nvm_echo "Reinstalling global packages from ${VERSION}..."
if [ -n "${INSTALLS}" ]; then
nvm_echo "${INSTALLS}" | command xargs npm install -g --quiet
else
nvm_echo "No installed global packages found..."
fi
nvm_echo "Linking global packages from ${VERSION}..."
if [ -n "${LINKS}" ]; then
(
set -f; IFS='
' # necessary to turn off variable expansion except for newlines
for LINK in ${LINKS}; do
set +f; unset IFS # restore variable expansion
if [ -n "${LINK}" ]; then
case "${LINK}" in
'/'*) (nvm_cd "${LINK}" && npm link) ;;
*) (nvm_cd "$(npm root -g)/../${LINK}" && npm link)
esac
fi
done
)
else
nvm_echo "No linked global packages found..."
fi
;;
"clear-cache")
command rm -f "${NVM_DIR}/v*" "$(nvm_version_dir)" 2>/dev/null
nvm_echo 'nvm cache cleared.'
;;
"version")
local PATTERN
PATTERN=''
while [ $# -gt 0 ]; do
case "${1}" in
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
*) PATTERN="${PATTERN:-${1}}" ;;
esac
shift
done
NVM_ONLY_RESOLVED="$(nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
nvm_version "${PATTERN-}"
;;
"version-remote")
local NVM_LTS
NVM_LTS=''
local PATTERN
PATTERN=''
while [ $# -gt 0 ]; do
case "${1-}" in
--) ;;
--lts)
NVM_LTS='*'
;;
--lts=*)
NVM_LTS="${1##--lts=}"
;;
--only=*)
NVM_ONLY_FLAG="${1#--only=}"
NVM_ONLY_FLAG_COUNT=$((NVM_ONLY_FLAG_COUNT + 1))
;;
--*)
nvm_err "Unsupported option \"${1}\"."
return 55
;;
*)
PATTERN="${PATTERN:-${1}}"
;;
esac
shift
done
case "${PATTERN-}" in
'lts/*')
NVM_LTS='*'
unset PATTERN
;;
lts/*)
NVM_LTS="${PATTERN##lts/}"
unset PATTERN
;;
esac
NVM_ONLY_RESOLVED="$(NVM_NO_LTS_STATUS=1 nvm_resolve_only "${NVM_ONLY_FLAG_COUNT}" "${NVM_ONLY_FLAG-}" "${NVM_LTS-}")" || return $?
local NVM_ONLY_SELECTED
NVM_ONLY_SELECTED="${NVM_ONLY_RESOLVED}"
NVM_VERSION_ONLY=true NVM_LTS="${NVM_LTS-}" nvm_remote_version "${PATTERN:-node}"
;;
"--version" | "-v")
nvm_echo '0.40.8'
;;
"unload")
nvm deactivate >/dev/null 2>&1
unset -f nvm \
nvm_iojs_prefix nvm_node_prefix \
nvm_add_iojs_prefix nvm_strip_iojs_prefix \
nvm_is_iojs_version nvm_is_alias nvm_has_non_aliased \
nvm_ls_remote nvm_ls_remote_iojs nvm_ls_remote_index_tab nvm_get_remote_aliases \
nvm_ls nvm_remote_version nvm_remote_versions nvm_sort_versions \
nvm_lts_status_path nvm_record_lts_status nvm_ensure_lts_status nvm_filter_lts_versions \
nvm_is_alpha_version nvm_normalize_only nvm_resolve_only nvm_only_includes nvm_explain_excluded_version nvm_select_lts_from_nvmrc \
nvm_needs_lts_status nvm_filter_installed_versions nvm_is_version_selected \
nvm_install_binary nvm_install_source nvm_clang_version \
nvm_get_mirror nvm_get_download_slug nvm_download_artifact nvm_is_cached_artifact \
nvm_install_npm_if_needed nvm_use_if_needed nvm_check_file_permissions \
nvm_print_versions nvm_compute_checksum \
nvm_get_checksum_binary \
nvm_get_checksum_alg nvm_get_checksum nvm_compare_checksum \
nvm_version nvm_rc_version nvm_match_version \
nvm_ensure_default_set nvm_get_arch nvm_get_os \
nvm_print_implicit_alias nvm_validate_implicit_alias \
nvm_resolve_alias nvm_ls_current nvm_alias \
nvm_binary_available nvm_change_path nvm_strip_path \
nvm_num_version_groups nvm_format_version nvm_ensure_version_prefix \
nvm_normalize_version nvm_is_valid_version nvm_normalize_lts \
nvm_ensure_version_installed nvm_cache_dir nvm_ls_cached nvm_offline_version \
nvm_version_path nvm_alias_path nvm_version_dir \
nvm_find_nvmrc nvm_find_up nvm_find_project_dir nvm_tree_contains_path \
nvm_version_greater nvm_version_greater_than_or_equal_to \
nvm_print_npm_version nvm_install_latest_npm nvm_npm_global_modules \
nvm_has_system_node nvm_has_system_iojs \
nvm_download nvm_get_latest nvm_has nvm_has_executable nvm_install_default_packages nvm_get_default_packages \
nvm_curl_use_compression nvm_curl_version \
nvm_auto nvm_supports_xz \
nvm_echo nvm_err nvm_grep nvm_cd \
nvm_die_on_prefix nvm_get_make_jobs nvm_get_minor_version \
nvm_has_solaris_binary nvm_is_merged_node_version \
nvm_is_natural_num nvm_is_installed_exact_version nvm_is_version_installed nvm_validate_install \
nvm_install_lock_name nvm_acquire_install_lock nvm_release_install_lock \
nvm_list_aliases nvm_make_alias nvm_print_alias_file nvm_print_alias_path \
nvm_print_default_alias nvm_print_formatted_alias nvm_resolve_local_alias \
nvm_replace_literal nvm_sanitize_path nvm_sanitize_url nvm_has_colors nvm_has_italics nvm_process_parameters \
nvm_node_version_has_solaris_binary nvm_iojs_version_has_solaris_binary \
nvm_curl_libz_support nvm_command_info nvm_is_zsh nvm_stdout_is_terminal \
nvm_npmrc_bad_news_bears nvm_sanitize_auth_header nvm_auth_header_applies_to \
nvm_wget_is_gnu nvm_url_origin nvm_wget_same_origin \
nvm_get_colors nvm_set_colors nvm_print_color_code nvm_wrap_with_color_code \
nvm_print_color_legend \
nvm_echo_with_colors nvm_err_with_colors \
nvm_get_artifact_compression nvm_install_binary_extract nvm_extract_tarball \
nvm_process_nvmrc nvm_process_nvmrc_content nvm_nvmrc_invalid_msg nvm_is_version_or_alias \
nvm_write_nvmrc nvm_hash_reset \
>/dev/null 2>&1
unset NVM_NODEJS_ORG_MIRROR NVM_IOJS_ORG_MIRROR NVM_DIR \
NVM_CD_FLAGS NVM_BIN NVM_INC NVM_MAKE_JOBS NVM_INSTALL_LOCK \
NVM_COLORS INSTALLED_COLOR SYSTEM_COLOR \
CURRENT_COLOR NOT_INSTALLED_COLOR DEFAULT_COLOR LTS_COLOR \
>/dev/null 2>&1
;;
"set-colors")
local EXIT_CODE
nvm_set_colors "${1-}"
EXIT_CODE=$?
if [ "$EXIT_CODE" -eq 17 ]; then
>&2 nvm --help
nvm_echo
nvm_err_with_colors "\033[1;37mPlease pass in five \033[1;31mvalid color codes\033[1;37m. Choose from: rRgGbBcCyYmMkKeW\033[0m"
fi
;;
*)
>&2 nvm --help
return 127
;;
esac
}
nvm_get_default_packages() {
local NVM_DEFAULT_PACKAGE_FILE
NVM_DEFAULT_PACKAGE_FILE="${NVM_DIR}/default-packages"
if [ -f "${NVM_DEFAULT_PACKAGE_FILE}" ]; then
command awk '
/^[ \t]*#/ { next } # Skip lines that begin with #
/^[ \t]*$/ { next } # Skip empty lines
/[ \t]/ && !/^[ \t]*#/ {
print "Only one package per line is allowed in `" FILENAME "`. Please remove any lines with multiple space-separated values." > "/dev/stderr"
err = 1
exit 1
}
{
if (NR > 1 && !prev_space) printf " "
printf "%s", $0
prev_space = 0
}
' "${NVM_DEFAULT_PACKAGE_FILE}"
fi
}
nvm_install_default_packages() {
local DEFAULT_PACKAGES
DEFAULT_PACKAGES="$(nvm_get_default_packages)"
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ] || [ -z "${DEFAULT_PACKAGES}" ]; then
return $EXIT_CODE
fi
nvm_echo "Installing default global packages from ${NVM_DIR}/default-packages..."
nvm_echo "npm install -g --quiet ${DEFAULT_PACKAGES}"
if ! nvm_echo "${DEFAULT_PACKAGES}" | command xargs npm install -g --quiet; then
nvm_err "Failed installing default packages. Please check if your default-packages file or a package in it has problems!"
return 1
fi
}
nvm_supports_xz() {
if [ -z "${1-}" ]; then
return 1
fi
local NVM_OS
NVM_OS="$(nvm_get_os)"
if [ "_${NVM_OS}" = '_darwin' ]; then
local MACOS_VERSION
MACOS_VERSION="$(sw_vers -productVersion)"
if nvm_version_greater "10.9.0" "${MACOS_VERSION}"; then
# macOS 10.8 and earlier doesn't support extracting xz-compressed tarballs with tar
return 1
fi
elif [ "_${NVM_OS}" = '_freebsd' ]; then
if ! [ -e '/usr/lib/liblzma.so' ]; then
# FreeBSD without /usr/lib/liblzma.so doesn't support extracting xz-compressed tarballs with tar
return 1
fi
else
if ! command which xz >/dev/null 2>&1; then
# Most OSes without xz on the PATH don't support extracting xz-compressed tarballs with tar
# (Should correctly handle Linux, SmartOS, maybe more)
return 1
fi
fi
# all node versions v4.0.0 and later have xz
if nvm_is_merged_node_version "${1}"; then
return 0
fi
# 0.12x: node v0.12.10 and later have xz
if nvm_version_greater_than_or_equal_to "${1}" "0.12.10" && nvm_version_greater "0.13.0" "${1}"; then
return 0
fi
# 0.10x: node v0.10.42 and later have xz
if nvm_version_greater_than_or_equal_to "${1}" "0.10.42" && nvm_version_greater "0.11.0" "${1}"; then
return 0
fi
case "${NVM_OS}" in
darwin)
# darwin only has xz for io.js v2.3.2 and later
nvm_version_greater_than_or_equal_to "${1}" "2.3.2"
;;
*)
nvm_version_greater_than_or_equal_to "${1}" "1.0.0"
;;
esac
return $?
}
nvm_auto() {
local NVM_MODE
NVM_MODE="${1-}"
case "${NVM_MODE}" in
none) return 0 ;;
use)
# don't download anything while a shell starts up
local NVM_INDEX_NO_FETCH
NVM_INDEX_NO_FETCH=1
if [ -n "${NVM_ONLY-}" ] && ! nvm_normalize_only "${NVM_ONLY}" '`$NVM_ONLY`' >/dev/null; then
return 55
fi
if nvm_needs_lts_status "${NVM_ONLY-}" && [ ! -f "$(nvm_lts_status_path)" ]; then
nvm_err 'The LTS status of installed versions is not recorded yet; run `nvm ls-remote` to record it.'
return 3
fi
local VERSION
local NVM_CURRENT
NVM_CURRENT="$(nvm_ls_current)"
if [ "_${NVM_CURRENT}" = '_none' ] || [ "_${NVM_CURRENT}" = '_system' ]; then
VERSION="$(nvm_resolve_local_alias default 2>/dev/null || nvm_echo)"
if [ -n "${VERSION}" ]; then
if [ "_${VERSION}" != '_N/A' ] && nvm_is_valid_version "${VERSION}"; then
# the default alias, and any flags it stores, have already selected this version
nvm use --silent --only=alpha,lts,non-lts,iojs "${VERSION}" >/dev/null
else
# a default alias whose flags need recorded LTS status can't get it while a shell starts up
local NVM_DEFAULT_TARGET
NVM_DEFAULT_TARGET="$(nvm_resolve_alias default 2>/dev/null ||:)"
local NVM_DEFAULT_NEEDS_LTS_STATUS
NVM_DEFAULT_NEEDS_LTS_STATUS=0
local NVM_DEFAULT_ONLY
while :; do
case "${NVM_DEFAULT_TARGET}" in
'--lts '* | --lts=*' '*) NVM_DEFAULT_NEEDS_LTS_STATUS=1 ;;
--only=*' '*)
NVM_DEFAULT_ONLY="${NVM_DEFAULT_TARGET%% *}"
if nvm_needs_lts_status "${NVM_DEFAULT_ONLY#--only=}"; then
NVM_DEFAULT_NEEDS_LTS_STATUS=1
fi
;;
*) break ;;
esac
NVM_DEFAULT_TARGET="${NVM_DEFAULT_TARGET#* }"
done
# zsh 5.1's `set -e` exits on a failing `cmd || :` in an `else`, but not on a failing condition
if [ "${NVM_DEFAULT_NEEDS_LTS_STATUS}" = 1 ] && [ ! -f "$(nvm_lts_status_path)" ]; then
nvm_err 'The default alias needs the LTS status of installed versions, which is not recorded yet; run `nvm ls-remote` to record it.'
elif nvm_explain_excluded_version default; then
:
fi
return 0
fi
elif nvm_rc_version 3>/dev/null >/dev/null 2>&1; then
nvm use --silent >/dev/null
fi
else
nvm use --silent --only=alpha,lts,non-lts,iojs "${NVM_CURRENT}" >/dev/null
fi
;;
install)
local VERSION
VERSION="$(nvm_alias default 2>/dev/null || nvm_echo)"
# flags stored in the alias, like `--lts`, are arguments to `nvm install`
set --
while :; do
case "${VERSION}" in
--*' '*)
set -- "$@" "${VERSION%% *}"
VERSION="${VERSION#* }"
;;
*) break ;;
esac
done
if [ -n "${VERSION}" ] && [ "_${VERSION}" != '_N/A' ] && nvm_is_valid_version "${VERSION}"; then
nvm install "$@" "${VERSION}" >/dev/null
elif nvm_rc_version 3>/dev/null >/dev/null 2>&1; then
nvm install >/dev/null
else
return 0
fi
;;
*)
nvm_err 'Invalid auto mode supplied.'
return 1
;;
esac
}
nvm_process_parameters() {
local NVM_AUTO_MODE
NVM_AUTO_MODE='use'
while [ "$#" -ne 0 ]; do
case "$1" in
--install) NVM_AUTO_MODE='install' ;;
--no-use) NVM_AUTO_MODE='none' ;;
esac
shift
done
nvm_auto "${NVM_AUTO_MODE}"
}
nvm_process_parameters "$@"
} # this ensures the entire script is downloaded #