mirror of
https://github.com/nvm-sh/nvm.git
synced 2026-08-25 00:00:22 +08:00
Compare commits
16
Commits
e2e612e722
...
3a8b51c46c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a8b51c46c | ||
|
|
ebada63259 | ||
|
|
0a9dead76d | ||
|
|
304a22ad59 | ||
|
|
d22bf7f538 | ||
|
|
dd61ae4bc8 | ||
|
|
59cf9a4ef6 | ||
|
|
21d33ef04a | ||
|
|
82315e2b18 | ||
|
|
ab77712867 | ||
|
|
0c1243a7ea | ||
|
|
9142a92cdc | ||
|
|
04fef13bdc | ||
|
|
cb0e0ba8ed | ||
|
|
b16fb6ece9 | ||
|
|
190cb9458b |
@@ -49,7 +49,6 @@ jobs:
|
||||
contents: read
|
||||
needs: [matrix]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ matrix.ref == 'v0.40.0' }} # https://github.com/nvm-sh/nvm/issues/3405
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -81,12 +80,19 @@ jobs:
|
||||
set -e
|
||||
export NVM_INSTALL_VERSION="${ref}"
|
||||
curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/${ref}/install.sh" | bash
|
||||
# v0.40.0 with an .nvmrc present is expected to fail (https://github.com/nvm-sh/nvm/issues/3405):
|
||||
# the steps below tolerate failure for that combination, and the final step
|
||||
# turns the job red only if the expected failure did NOT happen.
|
||||
- name: nvm --version
|
||||
id: nvm-version
|
||||
continue-on-error: ${{ matrix.ref == 'v0.40.0' && matrix.has-nvmrc == 'nvmrc' }}
|
||||
run: |
|
||||
set +e
|
||||
. $NVM_DIR/nvm.sh && nvm --version
|
||||
- name: nvm install in 1 shell level, ${{ matrix.has-nvmrc }}
|
||||
id: install-1
|
||||
if: ${{ matrix.shell-level == '1 shlvl' }}
|
||||
continue-on-error: ${{ matrix.ref == 'v0.40.0' && matrix.has-nvmrc == 'nvmrc' }}
|
||||
run: |
|
||||
set -ex
|
||||
. $NVM_DIR/nvm.sh
|
||||
@@ -96,13 +102,29 @@ jobs:
|
||||
nvm install
|
||||
fi
|
||||
- name: nvm install in 2 shell levels, ${{ matrix.has-nvmrc }}
|
||||
id: install-2
|
||||
if: ${{ matrix.shell-level == '2 shlvls' }}
|
||||
continue-on-error: ${{ matrix.ref == 'v0.40.0' && matrix.has-nvmrc == 'nvmrc' }}
|
||||
run: |
|
||||
if [ '${{ matrix.has-nvmrc }}' == 'nvmrc' ]; then
|
||||
bash -c "set -ex && . $NVM_DIR/nvm.sh && echo nvm.sh sourced && nvm --version && nvm install"
|
||||
else
|
||||
bash -c "set -ex && . $NVM_DIR/nvm.sh && echo nvm.sh sourced && nvm --version"
|
||||
fi
|
||||
- name: 'confirm the expected failure happened (v0.40.0 + nvmrc)'
|
||||
if: ${{ matrix.ref == 'v0.40.0' && matrix.has-nvmrc == 'nvmrc' }}
|
||||
env:
|
||||
SOURCE_OUTCOME: ${{ steps.nvm-version.outcome }}
|
||||
INSTALL_1_OUTCOME: ${{ steps.install-1.outcome }}
|
||||
INSTALL_2_OUTCOME: ${{ steps.install-2.outcome }}
|
||||
run: |
|
||||
echo "nvm --version: ${SOURCE_OUTCOME}; install (1 shlvl): ${INSTALL_1_OUTCOME}; install (2 shlvls): ${INSTALL_2_OUTCOME}"
|
||||
if [ "${SOURCE_OUTCOME}" = 'failure' ] || [ "${INSTALL_1_OUTCOME}" = 'failure' ] || [ "${INSTALL_2_OUTCOME}" = 'failure' ]; then
|
||||
echo 'v0.40.0 failed as expected: https://github.com/nvm-sh/nvm/issues/3405'
|
||||
else
|
||||
echo '::error::v0.40.0 with an .nvmrc was expected to fail (https://github.com/nvm-sh/nvm/issues/3405), but every step succeeded. If v0.40.0 somehow works now, remove the expected-failure handling from this workflow.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
finisher:
|
||||
permissions:
|
||||
|
||||
@@ -998,13 +998,13 @@ export NVM_DIR="$HOME/.nvm"
|
||||
|
||||
## Docker For Development Environment
|
||||
|
||||
To make the development and testing work easier, we have a Dockerfile for development usage, which is based on Ubuntu 18.04 base image, prepared with essential and useful tools for `nvm` development, to build the docker image of the environment, run the docker command at the root of `nvm` repository:
|
||||
To make development and testing work easier we supply a Dockerfile for development usage. It's based on an Ubuntu base image prepared with essential and useful tools for `nvm` development. To build the docker image of the environment, do a Docker build at the root of `nvm` repository:
|
||||
|
||||
```sh
|
||||
$ docker build -t nvm-dev .
|
||||
```
|
||||
|
||||
This will package your current nvm repository with our pre-defined development environment into a docker image named `nvm-dev`, once it's built with success, validate your image via `docker images`:
|
||||
This will package your current nvm working copy with our pre-defined development environment into a Docker image named `nvm-dev`. After the build you should see it appear in the list of images:
|
||||
|
||||
```sh
|
||||
$ docker images
|
||||
@@ -1013,7 +1013,7 @@ REPOSITORY TAG IMAGE ID CREATED S
|
||||
nvm-dev latest 9ca4c57a97d8 7 days ago 650 MB
|
||||
```
|
||||
|
||||
If you got no error message, now you can easily involve in:
|
||||
To start and enter a container based on this image:
|
||||
|
||||
```sh
|
||||
$ docker run -h nvm-dev -it nvm-dev
|
||||
@@ -1021,12 +1021,9 @@ $ docker run -h nvm-dev -it nvm-dev
|
||||
nvm@nvm-dev:~/.nvm$
|
||||
```
|
||||
|
||||
Please note that it'll take about 8 minutes to build the image and the image size would be about 650MB, so it's not suitable for production usage.
|
||||
It takes several minutes to build the image and the image size is about 650MB, so it's not suitable for production usage.
|
||||
|
||||
For more information and documentation about docker, please refer to its official website:
|
||||
|
||||
- https://www.docker.com/
|
||||
- https://docs.docker.com/
|
||||
For more information and documentation about Docker, please refer to its [official website][docker-www] and [documentation][docker-docs]:
|
||||
|
||||
## Problems
|
||||
|
||||
@@ -1205,3 +1202,7 @@ See [LICENSE.md](./LICENSE.md).
|
||||
|
||||
Copyright [OpenJS Foundation](https://openjsf.org) and `nvm` contributors. All rights reserved. The [OpenJS Foundation](https://openjsf.org) has registered trademarks and uses trademarks. For a list of trademarks of the [OpenJS Foundation](https://openjsf.org), please see our [Trademark Policy](https://trademark-policy.openjsf.org/) and [Trademark List](https://trademark-list.openjsf.org/). Trademarks and logos not indicated on the [list of OpenJS Foundation trademarks](https://trademark-list.openjsf.org) are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
|
||||
[The OpenJS Foundation](https://openjsf.org/) | [Terms of Use](https://terms-of-use.openjsf.org/) | [Privacy Policy](https://privacy-policy.openjsf.org/) | [Bylaws](https://bylaws.openjsf.org/) | [Code of Conduct](https://code-of-conduct.openjsf.org) | [Trademark Policy](https://trademark-policy.openjsf.org/) | [Trademark List](https://trademark-list.openjsf.org/) | [Cookie Policy](https://www.linuxfoundation.org/cookies/)
|
||||
|
||||
<!-------------------------------------------------------------------->
|
||||
[docker-docs]: https://docs.docker.com/
|
||||
[docker-www]: https://www.docker.com/
|
||||
|
||||
+19
-7
@@ -6,6 +6,18 @@ 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_echo() {
|
||||
command printf %s\\n "$*" 2>/dev/null
|
||||
}
|
||||
@@ -105,9 +117,9 @@ nvm_node_version() {
|
||||
}
|
||||
|
||||
nvm_download() {
|
||||
if nvm_has "curl"; then
|
||||
curl --fail --compressed -q "$@"
|
||||
elif nvm_has "wget"; then
|
||||
if nvm_has_executable "curl"; then
|
||||
command curl --fail --compressed -q "$@"
|
||||
elif nvm_has_executable "wget"; then
|
||||
# Emulate curl with wget
|
||||
ARGS=$(nvm_echo "$@" | command sed -e 's/--progress-bar /--progress=bar /' \
|
||||
-e 's/--compressed //' \
|
||||
@@ -119,7 +131,7 @@ nvm_download() {
|
||||
-e 's/-o /-O /' \
|
||||
-e 's/-C - /-c /')
|
||||
# shellcheck disable=SC2086
|
||||
eval wget $ARGS
|
||||
eval command wget $ARGS
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -401,7 +413,7 @@ nvm_do_install() {
|
||||
# Autodetect install method
|
||||
if nvm_has git; then
|
||||
install_nvm_from_git
|
||||
elif nvm_has curl || nvm_has wget; then
|
||||
elif nvm_has_executable curl || nvm_has_executable wget; then
|
||||
install_nvm_as_script
|
||||
else
|
||||
nvm_echo >&2 'You need git, curl, or wget to install nvm'
|
||||
@@ -414,7 +426,7 @@ nvm_do_install() {
|
||||
fi
|
||||
install_nvm_from_git
|
||||
elif [ "${METHOD}" = 'script' ]; then
|
||||
if ! nvm_has curl && ! nvm_has wget; then
|
||||
if ! nvm_has_executable curl && ! nvm_has_executable wget; then
|
||||
nvm_echo >&2 "You need curl or wget to install nvm"
|
||||
exit 1
|
||||
fi
|
||||
@@ -496,7 +508,7 @@ nvm_do_install() {
|
||||
# during the execution of the install script
|
||||
#
|
||||
nvm_reset() {
|
||||
unset -f nvm_has nvm_install_dir nvm_latest_version nvm_profile_is_bash_or_zsh \
|
||||
unset -f nvm_has nvm_has_executable nvm_install_dir nvm_latest_version nvm_profile_is_bash_or_zsh \
|
||||
nvm_source nvm_node_version nvm_download install_nvm_from_git nvm_install_node \
|
||||
install_nvm_as_script nvm_try_profile nvm_detect_profile nvm_check_global_modules \
|
||||
nvm_do_install nvm_reset nvm_default_install_dir nvm_grep
|
||||
|
||||
@@ -49,6 +49,18 @@ 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-}"
|
||||
}
|
||||
@@ -87,7 +99,7 @@ nvm_has_colors() {
|
||||
}
|
||||
|
||||
nvm_curl_libz_support() {
|
||||
curl -V 2>/dev/null | nvm_grep "^Features:" | nvm_grep -q "libz"
|
||||
command curl -V 2>/dev/null | nvm_grep "^Features:" | nvm_grep -q "libz"
|
||||
}
|
||||
|
||||
nvm_curl_use_compression() {
|
||||
@@ -97,13 +109,13 @@ nvm_curl_use_compression() {
|
||||
nvm_get_latest() {
|
||||
local NVM_LATEST_URL
|
||||
local CURL_COMPRESSED_FLAG
|
||||
if nvm_has "curl"; then
|
||||
if nvm_has_executable "curl"; then
|
||||
if nvm_curl_use_compression; then
|
||||
CURL_COMPRESSED_FLAG="--compressed"
|
||||
fi
|
||||
NVM_LATEST_URL="$(curl ${CURL_COMPRESSED_FLAG:-} -q -w "%{url_effective}\\n" -L -s -S https://latest.nvm.sh -o /dev/null)"
|
||||
elif nvm_has "wget"; then
|
||||
NVM_LATEST_URL="$(wget -q https://latest.nvm.sh --server-response -O /dev/null 2>&1 | command awk '/^ Location: /{DEST=$2} END{ print DEST }')"
|
||||
NVM_LATEST_URL="$(command curl ${CURL_COMPRESSED_FLAG:-} -q -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
|
||||
@@ -127,13 +139,13 @@ nvm_download() {
|
||||
|
||||
local NVM_DOWNLOADER
|
||||
NVM_DOWNLOADER=''
|
||||
if nvm_has "curl"; then
|
||||
if nvm_has_executable "curl"; then
|
||||
NVM_DOWNLOADER='curl'
|
||||
set -- -q --fail "$@"
|
||||
if nvm_curl_use_compression; then
|
||||
set -- --compressed "$@"
|
||||
fi
|
||||
elif nvm_has "wget"; then
|
||||
elif nvm_has_executable "wget"; then
|
||||
NVM_DOWNLOADER='wget'
|
||||
# Emulate curl with wget
|
||||
local NVM_DOWNLOAD_WGET_COUNT
|
||||
@@ -170,12 +182,17 @@ nvm_download() {
|
||||
set -- "$@" --header "Authorization: ${sanitized_header}"
|
||||
fi
|
||||
|
||||
"${NVM_DOWNLOADER}" "$@"
|
||||
command "${NVM_DOWNLOADER}" "$@"
|
||||
}
|
||||
|
||||
nvm_sanitize_auth_header() {
|
||||
# Remove potentially dangerous characters
|
||||
nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -]//g'
|
||||
# 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.
|
||||
# token68's '~' is still stripped.
|
||||
# Note: '-' must be at the end of the bracket expression to be treated as a literal.
|
||||
nvm_echo "$1" | command sed 's/[^a-zA-Z0-9 :_.+/=-]//g'
|
||||
}
|
||||
|
||||
nvm_has_system_node() {
|
||||
@@ -548,12 +565,12 @@ ${1}"
|
||||
$(nvm_wrap_with_color_code 'y' "${warn_text}")"
|
||||
}
|
||||
|
||||
nvm_process_nvmrc() {
|
||||
local NVMRC_PATH
|
||||
NVMRC_PATH="$1"
|
||||
nvm_process_nvmrc_content() {
|
||||
local NVMRC_CONTENT
|
||||
NVMRC_CONTENT="${1-}"
|
||||
local lines
|
||||
|
||||
lines=$(command sed 's/#.*//' "$NVMRC_PATH" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | nvm_grep -v '^$')
|
||||
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}"
|
||||
@@ -617,6 +634,13 @@ EOF
|
||||
nvm_echo "${unpaired_line}"
|
||||
}
|
||||
|
||||
nvm_process_nvmrc() {
|
||||
local NVMRC_PATH
|
||||
NVMRC_PATH="$1"
|
||||
|
||||
nvm_process_nvmrc_content "$(command cat "${NVMRC_PATH}")"
|
||||
}
|
||||
|
||||
nvm_rc_version() {
|
||||
local NVMRC_PATH
|
||||
NVMRC_PATH="$(nvm_find_nvmrc)"
|
||||
@@ -649,7 +673,7 @@ nvm_clang_version() {
|
||||
}
|
||||
|
||||
nvm_curl_version() {
|
||||
curl -V | command awk '{ if ($1 == "curl") print $2 }' | command sed 's/-.*$//g'
|
||||
command curl -V | command awk '{ if ($1 == "curl") print $2 }' | command sed 's/-.*$//g'
|
||||
}
|
||||
|
||||
nvm_version_greater() {
|
||||
@@ -1343,7 +1367,24 @@ nvm_alias() {
|
||||
return 2
|
||||
fi
|
||||
|
||||
command sed 's/#.*//; s/[[:space:]]*$//' "${NVM_ALIAS_PATH}" | command awk 'NF'
|
||||
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
|
||||
|
||||
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 < "${NVM_ALIAS_PATH}"
|
||||
}
|
||||
|
||||
nvm_ls_current() {
|
||||
@@ -1376,24 +1417,32 @@ nvm_resolve_alias() {
|
||||
local ALIAS
|
||||
ALIAS="${PATTERN}"
|
||||
local ALIAS_TEMP
|
||||
local ALIAS_OUTPUT
|
||||
|
||||
local SEEN_ALIASES
|
||||
SEEN_ALIASES="${ALIAS}"
|
||||
local NVM_ALIAS_INDEX
|
||||
NVM_ALIAS_INDEX=1
|
||||
SEEN_ALIASES="
|
||||
${ALIAS}
|
||||
"
|
||||
while true; do
|
||||
ALIAS_TEMP="$( (nvm_alias "${ALIAS}" 2>/dev/null | command head -n "${NVM_ALIAS_INDEX}" | command tail -n 1) || nvm_echo)"
|
||||
ALIAS_OUTPUT="$(nvm_alias "${ALIAS}" 2>/dev/null)" || ALIAS_OUTPUT=''
|
||||
ALIAS_TEMP="${ALIAS_OUTPUT%%
|
||||
*}"
|
||||
|
||||
if [ -z "${ALIAS_TEMP}" ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
if command printf '%b' "${SEEN_ALIASES}" | nvm_grep -q -e "^${ALIAS_TEMP}$"; then
|
||||
ALIAS="∞"
|
||||
break
|
||||
fi
|
||||
case "${SEEN_ALIASES}" in
|
||||
*"
|
||||
${ALIAS_TEMP}
|
||||
"*)
|
||||
ALIAS="∞"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
SEEN_ALIASES="${SEEN_ALIASES}\\n${ALIAS_TEMP}"
|
||||
SEEN_ALIASES="${SEEN_ALIASES}${ALIAS_TEMP}
|
||||
"
|
||||
ALIAS="${ALIAS_TEMP}"
|
||||
done
|
||||
|
||||
@@ -1474,6 +1523,17 @@ nvm_strip_iojs_prefix() {
|
||||
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
|
||||
@@ -2171,6 +2231,7 @@ nvm_get_arch() {
|
||||
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
|
||||
|
||||
@@ -2438,15 +2499,10 @@ nvm_get_download_slug() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# If running MAC M1 :: Node v14.17.0 was the first version to offer official experimental support:
|
||||
# https://github.com/nodejs/node/issues/40126 (although binary distributions aren't available until v16)
|
||||
if \
|
||||
nvm_version_greater '14.17.0' "${VERSION}" \
|
||||
|| (nvm_version_greater_than_or_equal_to "${VERSION}" '15.0.0' && nvm_version_greater '16.0.0' "${VERSION}") \
|
||||
; then
|
||||
if [ "_${NVM_OS}" = '_darwin' ] && [ "${NVM_ARCH}" = 'arm64' ]; then
|
||||
NVM_ARCH=x64
|
||||
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
|
||||
@@ -3574,7 +3630,7 @@ nvm() {
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "${NVM_OFFLINE}" != 1 ] && ! nvm_has "curl" && ! nvm_has "wget"; then
|
||||
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
|
||||
@@ -4693,7 +4749,7 @@ nvm() {
|
||||
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_install_default_packages nvm_get_default_packages \
|
||||
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 \
|
||||
@@ -4709,7 +4765,7 @@ nvm() {
|
||||
nvm_get_colors nvm_set_colors nvm_print_color_code nvm_wrap_with_color_code nvm_format_help_message_colors \
|
||||
nvm_echo_with_colors nvm_err_with_colors \
|
||||
nvm_get_artifact_compression nvm_install_binary_extract nvm_extract_tarball \
|
||||
nvm_process_nvmrc nvm_nvmrc_invalid_msg \
|
||||
nvm_process_nvmrc nvm_process_nvmrc_content nvm_nvmrc_invalid_msg \
|
||||
nvm_write_nvmrc \
|
||||
>/dev/null 2>&1
|
||||
unset NVM_NODEJS_ORG_MIRROR NVM_IOJS_ORG_MIRROR NVM_DIR \
|
||||
|
||||
@@ -50,6 +50,39 @@ make_echo() {
|
||||
chmod a+x "$1"
|
||||
}
|
||||
|
||||
# `command curl` bypasses shell functions and aliases, so tests that mock curl
|
||||
# must provide an actual executable on the PATH: this creates one in the given
|
||||
# directory. Invoked as `curl -V`, it prints ${VERSION_MESSAGE} (exported here
|
||||
# on the mock's behalf); any other invocation runs the body given as the
|
||||
# second argument, or fails.
|
||||
make_fake_curl() {
|
||||
local FAKE_BIN_DIR
|
||||
FAKE_BIN_DIR="${1-}"
|
||||
[ -n "${FAKE_BIN_DIR}" ] || return 1
|
||||
|
||||
local FAKE_CURL_BODY
|
||||
FAKE_CURL_BODY="${2-}"
|
||||
if [ -z "${FAKE_CURL_BODY}" ]; then
|
||||
FAKE_CURL_BODY='echo >&2 "This fake curl only takes one parameter, -V"
|
||||
exit 1'
|
||||
fi
|
||||
|
||||
mkdir -p "${FAKE_BIN_DIR}" || return 2
|
||||
|
||||
{
|
||||
echo '#!/bin/sh'
|
||||
echo 'if [ "$#" -eq 1 ] && [ "$1" = "-V" ]; then'
|
||||
echo ' echo "${VERSION_MESSAGE}"'
|
||||
echo ' exit 0'
|
||||
echo 'fi'
|
||||
printf '%s\n' "${FAKE_CURL_BODY}"
|
||||
} > "${FAKE_BIN_DIR}/curl"
|
||||
chmod +x "${FAKE_BIN_DIR}/curl"
|
||||
|
||||
# the fake curl reads VERSION_MESSAGE from the environment
|
||||
export VERSION_MESSAGE
|
||||
}
|
||||
|
||||
make_fake_node() {
|
||||
local VERSION
|
||||
VERSION="${1-}"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file whose name contains spaces
|
||||
mkdir -p ../../../alias
|
||||
printf 'v22.1.0\n' > "../../../alias/test edge spaces"
|
||||
ACTUAL="$(nvm_alias "test edge spaces")"
|
||||
EXPECTED='v22.1.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
rm -f "../../../alias/test edge spaces"
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file where the first line has a valid version
|
||||
# followed by a second line of binary-like data
|
||||
printf 'v22.1.0\n' > ../../../alias/test-edge-binary
|
||||
printf '\001\002\003\377\n' >> ../../../alias/test-edge-binary
|
||||
ACTUAL="$(nvm_alias test-edge-binary)"
|
||||
# nvm_alias emits every non-blank, non-comment line — first line should be the version
|
||||
FIRST_LINE="$(nvm_echo "${ACTUAL}" | command head -n 1)"
|
||||
EXPECTED='v22.1.0'
|
||||
[ "${FIRST_LINE}" = "${EXPECTED}" ] || die "expected first line >${EXPECTED}<, got >${FIRST_LINE}<"
|
||||
|
||||
rm -f ../../../alias/test-edge-binary
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file with Windows-style line endings (CRLF)
|
||||
printf 'v22.1.0\r\n' > ../../../alias/test-edge-cr
|
||||
ACTUAL="$(nvm_alias test-edge-cr)"
|
||||
EXPECTED='v22.1.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
# Create an alias file with bare carriage return (no newline)
|
||||
printf 'v22.2.0\r' > ../../../alias/test-edge-cr-bare
|
||||
ACTUAL="$(nvm_alias test-edge-cr-bare)"
|
||||
EXPECTED='v22.2.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for bare CR, got >${ACTUAL}<"
|
||||
|
||||
rm -f ../../../alias/test-edge-cr ../../../alias/test-edge-cr-bare
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file containing only comments
|
||||
printf '# this is a comment\n# another comment\n' > ../../../alias/test-edge-comments
|
||||
ACTUAL="$(nvm_alias test-edge-comments 2>/dev/null)"
|
||||
EXIT_CODE="$(nvm_alias test-edge-comments 2>/dev/null; echo $?)"
|
||||
[ -z "${ACTUAL}" ] || die "expected empty output for comment-only alias file, got >${ACTUAL}<"
|
||||
[ "${EXIT_CODE}" = '0' ] || die "expected exit code 0, got ${EXIT_CODE}"
|
||||
|
||||
rm -f ../../../alias/test-edge-comments
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file with an embedded NUL byte after the version.
|
||||
# NUL handling varies by shell: some stop at NUL, others read through it.
|
||||
# The function must not crash, and must emit output starting with the version.
|
||||
printf 'v22.1.0\000garbage\n' > ../../../alias/test-edge-nul
|
||||
ACTUAL="$(nvm_alias test-edge-nul)"
|
||||
EXIT_CODE=$?
|
||||
[ "${EXIT_CODE}" = '0' ] || die "expected exit code 0, got ${EXIT_CODE}"
|
||||
case "${ACTUAL}" in
|
||||
v22.1.0*) ;; # OK — starts with the version regardless of NUL handling
|
||||
*) die "expected output starting with >v22.1.0<, got >${ACTUAL}<" ;;
|
||||
esac
|
||||
|
||||
rm -f ../../../alias/test-edge-nul
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an empty alias file
|
||||
printf '' > ../../../alias/test-edge-empty
|
||||
ACTUAL="$(nvm_alias test-edge-empty 2>/dev/null)"
|
||||
EXIT_CODE="$(nvm_alias test-edge-empty 2>/dev/null; echo $?)"
|
||||
[ -z "${ACTUAL}" ] || die "expected empty output for empty alias file, got >${ACTUAL}<"
|
||||
[ "${EXIT_CODE}" = '0' ] || die "expected exit code 0, got ${EXIT_CODE}"
|
||||
|
||||
rm -f ../../../alias/test-edge-empty
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file with trailing form feed
|
||||
printf 'v22.1.0\f\n' > ../../../alias/test-edge-ff
|
||||
ACTUAL="$(nvm_alias test-edge-ff)"
|
||||
EXPECTED='v22.1.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for form feed, got >${ACTUAL}<"
|
||||
|
||||
# Create an alias file with trailing vertical tab
|
||||
printf 'v22.2.0\v\n' > ../../../alias/test-edge-vt
|
||||
ACTUAL="$(nvm_alias test-edge-vt)"
|
||||
EXPECTED='v22.2.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for vertical tab, got >${ACTUAL}<"
|
||||
|
||||
rm -f ../../../alias/test-edge-ff ../../../alias/test-edge-vt
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file with no trailing newline
|
||||
printf 'v22.1.0' > ../../../alias/test-edge-no-newline
|
||||
ACTUAL="$(nvm_alias test-edge-no-newline)"
|
||||
EXPECTED='v22.1.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
rm -f ../../../alias/test-edge-no-newline
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
cleanup() {
|
||||
chmod 644 ../../../alias/test-edge-unreadable 2>/dev/null
|
||||
rm -f ../../../alias/test-edge-unreadable
|
||||
}
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file that exists but can not be read
|
||||
echo 'v0.0.1' > ../../../alias/test-edge-unreadable
|
||||
chmod 000 ../../../alias/test-edge-unreadable
|
||||
|
||||
# root (and some containers) can read mode-000 files; nothing to assert there
|
||||
if [ -r ../../../alias/test-edge-unreadable ]; then
|
||||
cleanup
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# like the sed/awk pipeline this replaced: empty output, success status, so
|
||||
# that `nvm_ensure_default_set` does not overwrite an unreadable default alias
|
||||
OUTPUT="$(nvm_alias test-edge-unreadable 2>/dev/null)"
|
||||
EXIT_CODE=$?
|
||||
[ "${EXIT_CODE}" = '0' ] || die "expected exit code 0 for unreadable alias file, got ${EXIT_CODE}"
|
||||
[ -z "${OUTPUT}" ] || die "expected empty output for unreadable alias file, got >${OUTPUT}<"
|
||||
|
||||
STDERR="$(nvm_alias test-edge-unreadable 2>&1 >/dev/null)"
|
||||
case "${STDERR}" in
|
||||
*'not readable'*) ;;
|
||||
*) die "expected a not-readable warning on stderr, got >${STDERR}<" ;;
|
||||
esac
|
||||
|
||||
cleanup
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file with a very long line (version followed by a long comment)
|
||||
LONG_COMMENT="$(printf '%0*d' 10000 0 | command tr '0' 'x')"
|
||||
printf 'v22.1.0 #%s\n' "${LONG_COMMENT}" > ../../../alias/test-edge-long
|
||||
ACTUAL="$(nvm_alias test-edge-long)"
|
||||
EXPECTED='v22.1.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
rm -f ../../../alias/test-edge-long
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias file with trailing spaces and tabs
|
||||
printf '22.1.0 \t \n' > ../../../alias/test-edge-trailing-ws
|
||||
ACTUAL="$(nvm_alias test-edge-trailing-ws)"
|
||||
EXPECTED='22.1.0'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
rm -f ../../../alias/test-edge-trailing-ws
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# 1-hop self-reference: alias points to itself
|
||||
echo 'self' > '../../../alias/self'
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias self)"
|
||||
EXPECTED='∞'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for self-reference, got >${ACTUAL}<"
|
||||
|
||||
rm -f '../../../alias/self'
|
||||
|
||||
# Multi-hop loop: link1 -> link2 -> link3 -> link1
|
||||
echo 'link2' > '../../../alias/link1'
|
||||
echo 'link3' > '../../../alias/link2'
|
||||
echo 'link1' > '../../../alias/link3'
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias link1)"
|
||||
EXPECTED='∞'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for 3-hop cycle, got >${ACTUAL}<"
|
||||
|
||||
rm -f '../../../alias/link1' '../../../alias/link2' '../../../alias/link3'
|
||||
|
||||
# Cycle through an alias name containing a space
|
||||
echo 'midway' > '../../../alias/foo bar'
|
||||
echo 'foo bar' > '../../../alias/midway'
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias 'foo bar')"
|
||||
EXPECTED='∞'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for space-name cycle, got >${ACTUAL}<"
|
||||
|
||||
rm -f '../../../alias/foo bar' '../../../alias/midway'
|
||||
|
||||
# Non-cycle through an alias name containing a space.
|
||||
# Guards the newline-delimited SEEN_ALIASES storage: with space- or
|
||||
# token-delimited storage, seen name 'foo bar' would falsely match 'bar'.
|
||||
# Resolves: 'foo bar' -> 'midway' -> 'bar' -> 0.0.99
|
||||
echo 'midway' > '../../../alias/foo bar'
|
||||
echo 'bar' > '../../../alias/midway'
|
||||
echo '0.0.99' > '../../../alias/bar'
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias 'foo bar')"
|
||||
EXPECTED='v0.0.99'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for space-name chain, got >${ACTUAL}<"
|
||||
|
||||
rm -f '../../../alias/foo bar' '../../../alias/midway' '../../../alias/bar'
|
||||
|
||||
# Non-cycle through an alias name containing a regex metacharacter.
|
||||
# Guards the literal `case` matching: the previous grep-based detection
|
||||
# interpolated the resolved name into an anchored regex, so resolving 'axb'
|
||||
# matched the seen name 'axb' against the pattern 'a.b' and falsely
|
||||
# reported a cycle.
|
||||
# Resolves: 'axb' -> 'a.b' -> 0.0.99
|
||||
echo 'a.b' > '../../../alias/axb'
|
||||
echo '0.0.99' > '../../../alias/a.b'
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias axb)"
|
||||
EXPECTED='v0.0.99'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for metachar-name chain, got >${ACTUAL}<"
|
||||
|
||||
# ... while a genuine cycle through a metachar name is still detected
|
||||
echo 'axb' > '../../../alias/a.b'
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias axb)"
|
||||
EXPECTED='∞'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for metachar-name cycle, got >${ACTUAL}<"
|
||||
|
||||
rm -f '../../../alias/axb' '../../../alias/a.b'
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create a 4-deep alias chain: hop1 -> hop2 -> hop3 -> hop4 -> 0.0.99
|
||||
echo 'hop2' > ../../../alias/hop1
|
||||
echo 'hop3' > ../../../alias/hop2
|
||||
echo 'hop4' > ../../../alias/hop3
|
||||
echo '0.0.99' > ../../../alias/hop4
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias hop1)"
|
||||
EXPECTED='v0.0.99'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}< for 4-deep chain, got >${ACTUAL}<"
|
||||
|
||||
rm -f ../../../alias/hop1 ../../../alias/hop2 ../../../alias/hop3 ../../../alias/hop4
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
export NVM_DIR="$(cd ../../.. && pwd)"
|
||||
|
||||
: nvm.sh
|
||||
\. "${NVM_DIR}/nvm.sh"
|
||||
|
||||
# Create an alias pointing to a version that does not exist as an alias
|
||||
echo '99.99.99' > ../../../alias/test-edge-noexist
|
||||
|
||||
ACTUAL="$(nvm_resolve_alias test-edge-noexist)"
|
||||
EXPECTED='v99.99.99'
|
||||
EXIT_CODE="$(nvm_resolve_alias test-edge-noexist >/dev/null 2>&1; echo $?)"
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
[ "${EXIT_CODE}" = '0' ] || die "expected exit code 0, got ${EXIT_CODE}"
|
||||
|
||||
rm -f ../../../alias/test-edge-noexist
|
||||
@@ -17,3 +17,8 @@ rm -f "../../../alias/iojs"
|
||||
rm -f "../../../alias/default"
|
||||
rm -f "../../../alias/test-blank-lines"
|
||||
rm -f "../../../alias/test-multi-lines"
|
||||
rm -f "../../../alias/test-edge-"* "../../../alias/test edge spaces"
|
||||
rm -f "../../../alias/self" "../../../alias/link1" "../../../alias/link2" "../../../alias/link3"
|
||||
rm -f "../../../alias/foo bar" "../../../alias/midway" "../../../alias/bar"
|
||||
rm -f "../../../alias/hop1" "../../../alias/hop2" "../../../alias/hop3" "../../../alias/hop4"
|
||||
rm -f "../../../alias/axb" "../../../alias/a.b"
|
||||
|
||||
@@ -30,9 +30,10 @@ nvm_echo "$CAPTURED_STDERR" | nvm_grep -q "${EXPECTED_ERR}" \
|
||||
|
||||
# --offline should not require curl or wget
|
||||
nvm_has() { return 1; }
|
||||
nvm_has_executable() { return 1; }
|
||||
try_err nvm install --offline 999.999.999
|
||||
# Should fail with "not found" not "nvm needs curl or wget"
|
||||
nvm_echo "$CAPTURED_STDERR" | nvm_grep -q "curl or wget" \
|
||||
&& die "nvm install --offline should not require curl or wget"
|
||||
alias nvm_has='\nvm_has'
|
||||
unset -f nvm_has
|
||||
unset -f nvm_has nvm_has_executable
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
WORK="$PWD/nvm_curl_libz_support-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
|
||||
cleanup() {
|
||||
unset -f curl
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
|
||||
die() { cleanup; echo "$@" ; exit 1; }
|
||||
@@ -9,32 +13,28 @@ die() { cleanup; echo "$@" ; exit 1; }
|
||||
: nvm.sh
|
||||
\. ../../../nvm.sh
|
||||
|
||||
curl() {
|
||||
# curl with libz feature
|
||||
if [ $# -ne 1 ] || [ "$1" != "-V" ]; then
|
||||
die "This fake curl only takes one parameter -V"
|
||||
fi
|
||||
echo "
|
||||
\. ../../common.sh
|
||||
|
||||
OLDPATH="$PATH"
|
||||
|
||||
make_fake_curl "$TEST_BIN"
|
||||
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
# curl with libz feature
|
||||
VERSION_MESSAGE="
|
||||
curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
|
||||
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
|
||||
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets"
|
||||
}
|
||||
|
||||
nvm_curl_libz_support || die "nvm_curl_libz_support should return 0"
|
||||
|
||||
unset -f curl
|
||||
|
||||
curl() {
|
||||
# curl without libz feature
|
||||
if [ "$#" -ne 1 ] || [ "$1" != "-V" ]; then
|
||||
die "This fake curl only takes one parameter -V"
|
||||
fi
|
||||
echo "
|
||||
# curl without libz feature
|
||||
VERSION_MESSAGE="
|
||||
curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.32
|
||||
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
|
||||
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL TLS-SRP UnixSockets"
|
||||
}
|
||||
|
||||
! nvm_curl_libz_support || die "nvm_curl_libz_support should return 1"
|
||||
|
||||
unset -f curl
|
||||
cleanup
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
WORK="$PWD/nvm_curl_use_compression-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
|
||||
cleanup () {
|
||||
unset -f die
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
|
||||
die () { echo -e "$@" ; cleanup ; exit 1; }
|
||||
|
||||
NVM_ENV=testing \. ../../../nvm.sh
|
||||
|
||||
curl() {
|
||||
if [ "$1" = "-V" ]; then
|
||||
echo "${VERSION_MESSAGE}"
|
||||
fi
|
||||
}
|
||||
\. ../../common.sh
|
||||
|
||||
OLDPATH="$PATH"
|
||||
|
||||
make_fake_curl "$TEST_BIN"
|
||||
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
CURL_VERSION_ON_ARCHLINUX_WITH_LIBZ="curl 7.54.0 (x86_64-pc-linux-gnu) libcurl/7.54.0 OpenSSL/1.1.0f zlib/1.2.11 libpsl/0.17.0 (+libicu/59.1) libssh2/1.8.0 nghttp2/1.22.0
|
||||
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
WORK="$PWD/nvm_curl_version-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
|
||||
cleanup () {
|
||||
unset -f die
|
||||
unset -f curl
|
||||
unset -f die cleanup assert_version_is
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
|
||||
die () { echo -e "$@" ; cleanup ; exit 1; }
|
||||
|
||||
NVM_ENV=testing \. ../../../nvm.sh
|
||||
|
||||
curl() {
|
||||
if [ "$1" = "-V" ]; then
|
||||
echo "${VERSION_MESSAGE}"
|
||||
fi
|
||||
}
|
||||
\. ../../common.sh
|
||||
|
||||
OLDPATH="$PATH"
|
||||
|
||||
make_fake_curl "$TEST_BIN"
|
||||
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
assert_version_is() {
|
||||
if [ "${1}" != "${2}" ]; then
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
WORK="$PWD/shadowed-curl-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
ARGV_LOG="$WORK/argv.log"
|
||||
|
||||
cleanup () {
|
||||
unset -f die cleanup curl wget
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
NVM_ENV=testing \. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
OLDPATH="$PATH"
|
||||
|
||||
# real-looking curl on PATH; calling the shadowing shell function below instead is a failure
|
||||
make_fake_curl "$TEST_BIN" ': > "$ARGV_LOG"
|
||||
for a in "$@"; do printf "%s\n" "$a" >> "$ARGV_LOG"; done'
|
||||
|
||||
VERSION_MESSAGE="curl 7.99.0 (fake)
|
||||
Features: libz"
|
||||
|
||||
export ARGV_LOG
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
# shadowing shell functions, like aliases baked into a user's shell, must be
|
||||
# bypassed in favor of the executables on PATH (https://github.com/nvm-sh/nvm/issues/2923)
|
||||
curl() {
|
||||
echo 'curl 0.0.0-shadowed'
|
||||
return 1
|
||||
}
|
||||
wget() {
|
||||
return 1
|
||||
}
|
||||
|
||||
[ "$(nvm_curl_version)" = '7.99.0' ] || die "nvm_curl_version used the shadowing curl function; got $(nvm_curl_version)"
|
||||
|
||||
nvm_curl_libz_support || die 'nvm_curl_libz_support used the shadowing curl function'
|
||||
|
||||
nvm_download -s 'http://example.com/' -o /dev/null || die 'nvm_download used the shadowing curl function and failed'
|
||||
grep -Fxq 'http://example.com/' "$ARGV_LOG" || die "nvm_download did not invoke the curl executable; got: $(cat "$ARGV_LOG")"
|
||||
|
||||
# when no curl executable exists, a shadowing curl shell function must not fool
|
||||
# downloader selection: nvm_download must fall back to the wget executable
|
||||
WGET_ONLY_BIN="$WORK/wget-only-bin"
|
||||
mkdir -p "$WGET_ONLY_BIN"
|
||||
{
|
||||
echo '#!/bin/sh'
|
||||
echo ': > "$ARGV_LOG"'
|
||||
echo 'for a in "$@"; do printf "%s\n" "$a" >> "$ARGV_LOG"; done'
|
||||
} > "$WGET_ONLY_BIN/wget"
|
||||
chmod +x "$WGET_ONLY_BIN/wget"
|
||||
|
||||
(
|
||||
PATH="$WGET_ONLY_BIN"
|
||||
export PATH
|
||||
nvm_download -s 'http://wget-fallback.example.com/' -o /dev/null
|
||||
) || die 'nvm_download did not fall back to wget when curl is only a shell function'
|
||||
grep -Fxq 'http://wget-fallback.example.com/' "$ARGV_LOG" || die "nvm_download did not invoke the wget executable; got: $(cat "$ARGV_LOG")"
|
||||
|
||||
cleanup
|
||||
@@ -6,7 +6,7 @@ TEST_BIN="$WORK/bin"
|
||||
ARGV_LOG="$WORK/argv.log"
|
||||
|
||||
cleanup() {
|
||||
unset -f die cleanup nvm_has
|
||||
unset -f die cleanup nvm_has_executable
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
@@ -30,7 +30,7 @@ chmod +x "$TEST_BIN/wget"
|
||||
export ARGV_LOG
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
# force the wget path while keeping system tools (sed) available for sanitization
|
||||
nvm_has() { [ "$1" != curl ] && command -v "$1" >/dev/null 2>&1; }
|
||||
nvm_has_executable() { [ "$1" != curl ] && command -v "$1" >/dev/null 2>&1; }
|
||||
|
||||
# given an Authorization credential in NVM_AUTH_HEADER
|
||||
# when nvm_download uses the wget path
|
||||
|
||||
@@ -93,4 +93,6 @@ run_test amd64 osx x64
|
||||
run_test arm64 smartos x64
|
||||
run_test armv8l smartos x64
|
||||
|
||||
run_test loongarch64 linux loong64
|
||||
|
||||
cleanup
|
||||
|
||||
@@ -110,3 +110,26 @@ ACTUAL="$(nvm_get_download_slug iojs source 15.99.99)"
|
||||
EXPECTED="iojs-15.99.99"
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
|
||||
REAL_OS="$(command uname -s 2>/dev/null || echo '')"
|
||||
REAL_ARCH="$(command uname -m 2>/dev/null || echo '')"
|
||||
if [ "${REAL_OS}" = "Darwin" ] && [ "${REAL_ARCH}" = "arm64" ]; then
|
||||
# Node < 16 uses x64 on darwin-arm64
|
||||
ACTUAL="$(nvm_get_download_slug node binary 14.21.3)"
|
||||
EXPECTED='node-14.21.3-darwin-x64'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
ACTUAL="$(nvm_get_download_slug node binary 15.99.99)"
|
||||
EXPECTED='node-15.99.99-darwin-x64'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
ACTUAL="$(nvm_get_download_slug iojs binary 15.99.99)"
|
||||
EXPECTED='iojs-15.99.99-darwin-x64'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
|
||||
# Test Node >= 16 uses arm64 on darwin-arm64
|
||||
ACTUAL="$(nvm_get_download_slug node binary 16.0.0)"
|
||||
EXPECTED='node-16.0.0-darwin-arm64'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
ACTUAL="$(nvm_get_download_slug node binary 18.0.0)"
|
||||
EXPECTED='node-18.0.0-darwin-arm64'
|
||||
[ "${ACTUAL}" = "${EXPECTED}" ] || die "expected >${EXPECTED}<, got >${ACTUAL}<"
|
||||
fi
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
cleanup() {
|
||||
unset -f nvm_has
|
||||
unset -f nvm_has nvm_has_executable
|
||||
}
|
||||
|
||||
: nvm.sh
|
||||
@@ -12,6 +12,7 @@ cleanup() {
|
||||
\. ../../common.sh
|
||||
|
||||
nvm_has() { return 1 ; }
|
||||
nvm_has_executable() { return 1 ; }
|
||||
|
||||
try_err nvm_get_latest
|
||||
[ "_$CAPTURED_STDERR" = "_nvm needs curl or wget to proceed." ] \
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
cleanup() {
|
||||
rm -rf "${TEST_DIR-}"
|
||||
unset NVMRC_CONTENT OUTPUT EXIT_CODE TEST_DIR NVM_DIR
|
||||
}
|
||||
|
||||
: nvm.sh
|
||||
\. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
# an isolated NVM_DIR with a single known version, so that ambient versions
|
||||
# and aliases can not affect any assertions
|
||||
TEST_DIR="${PWD}/nvm_ls_hash_pattern_tmp"
|
||||
mkdir -p "${TEST_DIR}/versions/node/v24.13.0/bin" || die 'failed to create test version dir'
|
||||
make_echo "${TEST_DIR}/versions/node/v24.13.0/bin/node" 'v24.13.0' || die 'failed to create test node binary'
|
||||
NVM_DIR="${TEST_DIR}"
|
||||
|
||||
# Test: nvm_ls with pattern containing # should not cause sed error
|
||||
# This is a regression test for https://github.com/nvm-sh/nvm/issues/3761
|
||||
|
||||
@@ -22,3 +36,33 @@ echo "$OUTPUT" | grep -q "invalid command code" && \
|
||||
# Should return N/A with exit code 3 (not found)
|
||||
[ "$EXIT_CODE" = "3" ] || die "nvm_ls 'foo#bar' should exit with code 3, got $EXIT_CODE"
|
||||
echo "$OUTPUT" | grep -q "N/A" || die "nvm_ls 'foo#bar' should output N/A, got: $OUTPUT"
|
||||
|
||||
NVMRC_CONTENT='v24.13.0
|
||||
# krypton is the codename for Node.js v24.x'
|
||||
|
||||
OUTPUT="$(nvm_ls "${NVMRC_CONTENT}" 2>&1)"
|
||||
EXIT_CODE=$?
|
||||
|
||||
[ "$EXIT_CODE" = "0" ] || die "nvm_ls with .nvmrc comments should exit with code 0, got $EXIT_CODE"
|
||||
[ "$OUTPUT" = "v24.13.0" ] || die "nvm_ls with .nvmrc comments should output v24.13.0, got: $OUTPUT"
|
||||
|
||||
OUTPUT="$(nvm_version "${NVMRC_CONTENT}" 2>&1)"
|
||||
[ "$OUTPUT" = "v24.13.0" ] || die "nvm_version with .nvmrc comments should output v24.13.0, got: $OUTPUT"
|
||||
|
||||
# a partial version reaches nvm_ls's find/sed pipeline, which is where multiline
|
||||
# patterns used to break sed ("unterminated regular expression" on BSD sed,
|
||||
# "unterminated address regex" on GNU sed); a full x.y.z version takes the
|
||||
# explicit-version fast path and never reaches it
|
||||
NVMRC_CONTENT='24
|
||||
# krypton is the codename for Node.js v24.x'
|
||||
|
||||
OUTPUT="$(nvm_ls "${NVMRC_CONTENT}" 2>&1)"
|
||||
EXIT_CODE=$?
|
||||
|
||||
echo "$OUTPUT" | grep -q "unterminated" && \
|
||||
die "nvm_ls with partial version + comments caused a sed error: $OUTPUT"
|
||||
|
||||
[ "$EXIT_CODE" = "0" ] || die "nvm_ls with partial version + comments should exit with code 0, got $EXIT_CODE"
|
||||
[ "$OUTPUT" = "v24.13.0" ] || die "nvm_ls with partial version + comments should output v24.13.0, got: $OUTPUT"
|
||||
|
||||
cleanup
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
\. ../../../nvm.sh
|
||||
|
||||
set -ex
|
||||
|
||||
# Test 1: all standard base64 characters (RFC 4648) are preserved
|
||||
STANDARD_B64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
|
||||
RESULT=$(nvm_sanitize_auth_header "${STANDARD_B64}")
|
||||
[ "${RESULT}" = "${STANDARD_B64}" ] || die "FAIL: standard base64 chars were stripped. Got: '${RESULT}'"
|
||||
|
||||
# Test 2: all base64url characters (RFC 4648 §5) are preserved
|
||||
B64URL="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="
|
||||
RESULT=$(nvm_sanitize_auth_header "${B64URL}")
|
||||
[ "${RESULT}" = "${B64URL}" ] || die "FAIL: base64url chars were stripped. Got: '${RESULT}'"
|
||||
|
||||
# Test 3: a real JWT Bearer token (base64url-encoded header.payload.signature) is preserved
|
||||
JWT_TOKEN="Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
|
||||
RESULT=$(nvm_sanitize_auth_header "${JWT_TOKEN}")
|
||||
[ "${RESULT}" = "${JWT_TOKEN}" ] || die "FAIL: JWT Bearer token chars were stripped. Got: '${RESULT}'"
|
||||
|
||||
# Test 4: Basic auth (base64-encoded user:pass) is preserved
|
||||
BASIC_TOKEN="Basic dXNlcm5hbWU6cGFzc3dvcmQ="
|
||||
RESULT=$(nvm_sanitize_auth_header "${BASIC_TOKEN}")
|
||||
[ "${RESULT}" = "${BASIC_TOKEN}" ] || die "FAIL: Basic auth base64 token chars were stripped. Got: '${RESULT}'"
|
||||
|
||||
# Test 5: dangerous shell metacharacters are removed
|
||||
DANGEROUS="Bearer token;\`evil\`-cmd \$(inject)"
|
||||
RESULT=$(nvm_sanitize_auth_header "${DANGEROUS}")
|
||||
case "${RESULT}" in
|
||||
*";"*|*"\`"*|*'$'*|*"("*|*")"*)
|
||||
die "FAIL: dangerous shell metacharacters survived sanitization. Got: '${RESULT}'"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "All nvm_sanitize_auth_header tests passed"
|
||||
Regular → Executable
+2
-2
@@ -32,9 +32,9 @@ fi
|
||||
# Test 2: Verify that sanitized header still works for legitimate requests
|
||||
# The sanitized header should only contain safe characters
|
||||
SANITIZED=$(nvm_sanitize_auth_header "${MALICIOUS_HEADER}")
|
||||
# Verify that dangerous characters were removed
|
||||
# Verify that dangerous shell metacharacters were removed
|
||||
case "${SANITIZED}" in
|
||||
*";"*|*"touch"*|*"/tmp"*)
|
||||
*";"*|*'$'*|*"\`"*)
|
||||
die "SECURITY FAILURE: Sanitization did not remove dangerous characters properly"
|
||||
;;
|
||||
esac
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
if [ "_$1" = "_-m" ]; then
|
||||
echo "loongarch64"
|
||||
else
|
||||
echo "Linux foo 6.12.54-16k #0 SMP PREEMPT_DYNAMIC Fri Dec 5 12:35:43 UTC loongarch64 GNU/Linux"
|
||||
fi
|
||||
@@ -2,37 +2,46 @@
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
WORK="$PWD/nvm_get_latest-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
|
||||
cleanup() {
|
||||
unset -f curl wget nvm_has
|
||||
unset -f curl wget
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
|
||||
\. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
OLDPATH="$PATH"
|
||||
|
||||
EXPECTED_VERSION="v12.3.456"
|
||||
URL="https://github.com/nvm-sh/nvm/releases/tag/$EXPECTED_VERSION"
|
||||
EXPECTED_CURL_ARGS="--compressed -q -w %{url_effective}\n -L -s -S https://latest.nvm.sh -o /dev/null"
|
||||
EXPECTED_WGET_ARGS="-q https://latest.nvm.sh --server-response -O /dev/null"
|
||||
export URL EXPECTED_CURL_ARGS EXPECTED_WGET_ARGS
|
||||
|
||||
curl() {
|
||||
if [ $# -eq 1 ] && [ "$1" = "-V" ]; then
|
||||
echo "
|
||||
VERSION_MESSAGE="
|
||||
curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
|
||||
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
|
||||
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets"
|
||||
elif [ "_$*" != "_$EXPECTED_CURL_ARGS" ]; then
|
||||
echo >&2 "expected args ($EXPECTED_CURL_ARGS), got ($*)"
|
||||
return 1
|
||||
else
|
||||
echo $URL
|
||||
fi
|
||||
}
|
||||
wget() {
|
||||
if [ "_$*" != "_$EXPECTED_WGET_ARGS" ]; then
|
||||
echo >&2 "expected args ($EXPECTED_WGET_ARGS), got ($*)"
|
||||
return 1
|
||||
else
|
||||
local WGET_CONTENTS
|
||||
WGET_CONTENTS="
|
||||
|
||||
# fake curl/wget: `command curl` bypasses shell functions, so the mocks must be executables on PATH
|
||||
make_fake_curl "$TEST_BIN" 'if [ "_$*" != "_$EXPECTED_CURL_ARGS" ]; then
|
||||
echo >&2 "expected args ($EXPECTED_CURL_ARGS), got ($*)"
|
||||
exit 1
|
||||
fi
|
||||
echo "$URL"'
|
||||
|
||||
cat > "$TEST_BIN/wget" <<'OUTER'
|
||||
#!/bin/sh
|
||||
if [ "_$*" != "_$EXPECTED_WGET_ARGS" ]; then
|
||||
echo >&2 "expected args ($EXPECTED_WGET_ARGS), got ($*)"
|
||||
exit 1
|
||||
fi
|
||||
cat >&2 <<CONTENTS
|
||||
HTTP/1.1 301 Moved Permanently
|
||||
Location: https://github.com/nvm-sh/nvm/releases/latest
|
||||
Content-Type: text/html; charset=utf-8
|
||||
@@ -82,15 +91,22 @@ wget() {
|
||||
X-Content-Type-Options: nosniff
|
||||
Vary: Accept-Encoding
|
||||
X-Served-By: 926b734ea1992f8ee1f88ab967a93dac
|
||||
"
|
||||
"$WGET_CONTENTS" | while read line
|
||||
do
|
||||
>&2 echo "$line"
|
||||
done
|
||||
fi
|
||||
}
|
||||
CONTENTS
|
||||
OUTER
|
||||
chmod +x "$TEST_BIN/wget"
|
||||
|
||||
\. ../../common.sh
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
# shadowing shell functions, like aliases baked into a user's shell, must be
|
||||
# bypassed in favor of the executables on PATH (https://github.com/nvm-sh/nvm/issues/2923)
|
||||
curl() {
|
||||
echo >&2 'the shadowing curl function was called'
|
||||
return 1
|
||||
}
|
||||
wget() {
|
||||
echo >&2 'the shadowing wget function was called'
|
||||
return 1
|
||||
}
|
||||
|
||||
try nvm_get_latest
|
||||
[ "_$CAPTURED_STDOUT" = "_$EXPECTED_VERSION" ] \
|
||||
|
||||
@@ -2,20 +2,26 @@
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
WORK="$PWD/nvm_get_latest_failed_redirect-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
|
||||
cleanup() {
|
||||
unset -f curl wget
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
}
|
||||
|
||||
\. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
curl() {
|
||||
return 1
|
||||
}
|
||||
wget() {
|
||||
return 1
|
||||
}
|
||||
OLDPATH="$PATH"
|
||||
|
||||
# fake curl/wget: `command curl` bypasses shell functions, so the mocks must be executables on PATH
|
||||
make_fake_curl "$TEST_BIN" 'exit 1'
|
||||
printf '#!/bin/sh\nexit 1\n' > "$TEST_BIN/wget"
|
||||
chmod +x "$TEST_BIN/wget"
|
||||
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
try_err nvm_get_latest
|
||||
[ "_$CAPTURED_STDERR" = "_https://latest.nvm.sh did not redirect to the latest release on GitHub" ] \
|
||||
|
||||
Reference in New Issue
Block a user