mirror of
https://github.com/nvm-sh/nvm.git
synced 2026-10-11 00:00:13 +08:00
Compare commits
12
Commits
v0.40.7
...
80e700ec21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80e700ec21 | ||
|
|
25b378323c | ||
|
|
3a72926f4a | ||
|
|
38f0f2cfdf | ||
|
|
812a76bb41 | ||
|
|
26fef4fe1a | ||
|
|
17f12a1207 | ||
|
|
ab83657ba6 | ||
|
|
10a277ec47 | ||
|
|
dd0f702fb1 | ||
|
|
6798d1dbc9 | ||
|
|
df7a936157 |
@@ -35,5 +35,6 @@ jobs:
|
||||
run: echo proceed | make TAG=99.99.99 release
|
||||
env:
|
||||
GIT_EDITOR: "sed -i '1 s/^/99.99.99 make release test/'"
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Ensure tag is created
|
||||
run: git tag | grep v99.99.99
|
||||
|
||||
@@ -190,9 +190,10 @@ nvm_sanitize_auth_header() {
|
||||
# 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.
|
||||
# '~' 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 bracket expression to be treated as a literal.
|
||||
nvm_echo "$1" | command sed 's/[^a-zA-Z0-9 :_.+/=-]//g'
|
||||
nvm_echo "$1" | command sed 's/[^a-zA-Z0-9 :_.+/=~-]//g'
|
||||
}
|
||||
|
||||
nvm_has_system_node() {
|
||||
@@ -1128,6 +1129,8 @@ nvm_set_colors() {
|
||||
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); }')"
|
||||
@@ -1138,6 +1141,7 @@ nvm_set_colors() {
|
||||
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"
|
||||
@@ -1175,13 +1179,38 @@ nvm_wrap_with_color_code() {
|
||||
CODE="$(nvm_print_color_code "${1}" 2>/dev/null ||:)"
|
||||
local TEXT
|
||||
TEXT="${2-}"
|
||||
if nvm_has_colors && [ -n "${CODE}" ]; then
|
||||
# `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 ;;
|
||||
@@ -1360,7 +1389,7 @@ nvm_list_aliases() {
|
||||
NVM_HAS_COLORS=1
|
||||
fi
|
||||
|
||||
nvm_is_zsh && unsetopt local_options nomatch
|
||||
nvm_is_zsh && setopt local_options nonomatch
|
||||
(
|
||||
local ALIAS_PATH
|
||||
for ALIAS_PATH in "${NVM_ALIAS_DIR}/${ALIAS}"*; do
|
||||
@@ -1398,6 +1427,23 @@ nvm_list_aliases() {
|
||||
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-}"
|
||||
@@ -1428,16 +1474,7 @@ nvm_alias() {
|
||||
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_print_alias_file "${NVM_ALIAS_PATH}"
|
||||
}
|
||||
|
||||
nvm_ls_current() {
|
||||
@@ -1656,7 +1693,7 @@ nvm_ls() {
|
||||
esac
|
||||
|
||||
nvm_is_zsh && setopt local_options shwordsplit
|
||||
nvm_is_zsh && unsetopt local_options markdirs
|
||||
nvm_is_zsh && setopt local_options nomarkdirs
|
||||
|
||||
local NVM_DIRS_TO_SEARCH1
|
||||
NVM_DIRS_TO_SEARCH1=''
|
||||
@@ -2387,7 +2424,14 @@ nvm_get_mirror() {
|
||||
esac
|
||||
|
||||
|
||||
if ! nvm_echo "${NVM_MIRROR}" | command awk '{ if ($0 !~ /^https?:\/\/[a-zA-Z0-9.\/_-]+$/) exit 1 }'; then
|
||||
# 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
|
||||
@@ -3492,17 +3536,7 @@ nvm() {
|
||||
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_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_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'
|
||||
@@ -4935,13 +4969,14 @@ nvm() {
|
||||
nvm_has_solaris_binary nvm_is_merged_node_version \
|
||||
nvm_is_natural_num 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_path \
|
||||
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_sanitize_path nvm_has_colors nvm_process_parameters \
|
||||
nvm_node_version_has_solaris_binary nvm_iojs_version_has_solaris_binary \
|
||||
nvm_curl_libz_support nvm_command_info nvm_is_zsh nvm_stdout_is_terminal \
|
||||
nvm_npmrc_bad_news_bears nvm_sanitize_auth_header \
|
||||
nvm_get_colors nvm_set_colors nvm_print_color_code nvm_wrap_with_color_code nvm_format_help_message_colors \
|
||||
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 \
|
||||
|
||||
Executable
+153
@@ -0,0 +1,153 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Generates release notes for an nvm release, in the format used in the
|
||||
# annotated release tags and version bump commits.
|
||||
#
|
||||
# Usage: ./release-notes.sh <new-version> [<prev-ref>] [<end-ref>]
|
||||
# <new-version> the version being released, e.g. `v0.40.7` (the leading `v` is optional)
|
||||
# <prev-ref> list commits since this ref; defaults to the most recent `vX.Y.Z` tag
|
||||
# <end-ref> list commits up to this ref; defaults to HEAD
|
||||
#
|
||||
# Commits from <prev-ref> to <end-ref> are grouped into sections by the leading
|
||||
# `[bracket]` tag of their subject line, in `git log` order (newest first).
|
||||
# Category tags ([New], [Fix], ...) are stripped from the bullet text;
|
||||
# context tags ([readme], [actions], [meta], ...) are kept.
|
||||
# Commits without a recognized tag land under "Misc", with a warning on stderr.
|
||||
#
|
||||
# Each bullet gets a ` (#123)` reference to the pull request that introduced
|
||||
# the commit, looked up via `gh` from GitHub's commit->PR association, unless
|
||||
# the subject already ends with one. Set NVM_RELEASE_NOTES_SKIP_PRS to a
|
||||
# nonempty value to skip the lookup (references will be omitted).
|
||||
|
||||
NEW_VERSION="${1-}"
|
||||
PREV_REF="${2-}"
|
||||
END_REF="${3:-HEAD}"
|
||||
|
||||
if [ -z "${NEW_VERSION}" ]; then
|
||||
printf >&2 'Usage: %s <new-version> [<prev-ref>] [<end-ref>]\n' "$0"
|
||||
exit 2
|
||||
fi
|
||||
case "${NEW_VERSION}" in
|
||||
v*) ;;
|
||||
*) NEW_VERSION="v${NEW_VERSION}" ;;
|
||||
esac
|
||||
|
||||
if [ -z "${PREV_REF}" ]; then
|
||||
PREV_REF="$(git describe --abbrev=0 --tags --match 'v[0-9]*.[0-9]*.[0-9]*')" || {
|
||||
printf >&2 'release-notes: failed to determine the previous version tag.\n'
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
for REF in "${PREV_REF}" "${END_REF}"; do
|
||||
git rev-parse --quiet --verify "${REF}^{commit}" >/dev/null || {
|
||||
# shellcheck disable=SC2016
|
||||
printf >&2 'release-notes: `%s` is not a valid ref.\n' "${REF}"
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
LOOKUP_PRS=1
|
||||
if [ -n "${NVM_RELEASE_NOTES_SKIP_PRS-}" ]; then
|
||||
LOOKUP_PRS=0
|
||||
elif ! command -v gh >/dev/null 2>&1; then
|
||||
# shellcheck disable=SC2016
|
||||
printf >&2 'release-notes: `gh` is not available; PR references will be omitted.\n'
|
||||
LOOKUP_PRS=0
|
||||
fi
|
||||
|
||||
# the repo to look up commit->PR associations in, e.g. `nvm-sh/nvm`
|
||||
REPO_SLUG="${GH_REPO-}"
|
||||
if [ -z "${REPO_SLUG}" ]; then
|
||||
ORIGIN_URL="$(git remote get-url origin 2>/dev/null)" || ORIGIN_URL=''
|
||||
case "${ORIGIN_URL}" in
|
||||
*github.com[:/]*) REPO_SLUG="$(printf '%s' "${ORIGIN_URL}" | sed 's#^.*github\.com[:/]##;s#\.git$##')" ;;
|
||||
esac
|
||||
fi
|
||||
: "${REPO_SLUG:=nvm-sh/nvm}"
|
||||
|
||||
TAB="$(printf '\t')"
|
||||
|
||||
COMMITS_FILE="$(mktemp)" || exit 1
|
||||
GH_ERR_FILE="$(mktemp)" || exit 1
|
||||
trap 'rm -f "${COMMITS_FILE}" "${GH_ERR_FILE}"' EXIT
|
||||
|
||||
# each line: <section key> TAB <sha> TAB <bullet text>, in git log order
|
||||
git log --no-merges --format='%H %s' "${PREV_REF}..${END_REF}" | while IFS=' ' read -r SHA SUBJECT; do
|
||||
LOWERED="$(printf '%s' "${SUBJECT}" | tr '[:upper:]' '[:lower:]')"
|
||||
STRIPPED="${SUBJECT#\[*\] }"
|
||||
case "${LOWERED}" in
|
||||
v[0-9]*.[0-9]*.[0-9]*)
|
||||
case "${SUBJECT}" in
|
||||
*' '*) # not a bump commit, just a subject that starts with a version
|
||||
printf >&2 'release-notes: no category prefix, filing under Misc: %s\n' "${SUBJECT}"
|
||||
KEY='misc' TEXT="${SUBJECT}"
|
||||
;;
|
||||
*) continue ;; # a version bump commit
|
||||
esac
|
||||
;;
|
||||
'[new] '*) KEY='new' TEXT="${STRIPPED}" ;;
|
||||
'[fix] '* | '[patch] '*) KEY='fix' TEXT="${STRIPPED}" ;;
|
||||
'[refactor] '*) KEY='refactor' TEXT="${STRIPPED}" ;;
|
||||
'[shellcheck] '*) KEY='refactor' TEXT="${SUBJECT}" ;;
|
||||
'[robustness] '*) KEY='robustness' TEXT="${STRIPPED}" ;;
|
||||
'[perf] '* | '[performance] '*) KEY='perf' TEXT="${STRIPPED}" ;;
|
||||
'[dockerfile] '*) KEY='dockerfile' TEXT="${STRIPPED}" ;;
|
||||
'[docs] '* | '[doc] '*) KEY='docs' TEXT="${STRIPPED}" ;;
|
||||
'[readme] '*) KEY='docs' TEXT="${SUBJECT}" ;;
|
||||
'[meta] '* | '[security] '* | '[dev deps] '*)
|
||||
KEY='misc' TEXT="${SUBJECT}" ;;
|
||||
'[tests] '* | '[test] '*) KEY='tests' TEXT="${STRIPPED}" ;;
|
||||
'[actions] '* | '[debug] '*) KEY='tests' TEXT="${SUBJECT}" ;;
|
||||
*)
|
||||
printf >&2 'release-notes: no category prefix, filing under Misc: %s\n' "${SUBJECT}"
|
||||
KEY='misc' TEXT="${SUBJECT}"
|
||||
;;
|
||||
esac
|
||||
printf '%s\t%s\t%s\n' "${KEY}" "${SHA}" "${TEXT}"
|
||||
done > "${COMMITS_FILE}"
|
||||
|
||||
if ! [ -s "${COMMITS_FILE}" ]; then
|
||||
printf >&2 'release-notes: no commits found in %s..HEAD.\n' "${PREV_REF}"
|
||||
fi
|
||||
|
||||
print_section() {
|
||||
if ! grep -q "^$1${TAB}" "${COMMITS_FILE}"; then
|
||||
return 0
|
||||
fi
|
||||
printf '\n%s\n\n' "$2"
|
||||
grep "^$1${TAB}" "${COMMITS_FILE}" | while IFS="${TAB}" read -r _KEY SHA TEXT; do
|
||||
REF=''
|
||||
case "${TEXT}" in
|
||||
*'(#'[0-9]*')') ;; # the subject already carries a reference
|
||||
*)
|
||||
if [ "${LOOKUP_PRS}" = 1 ]; then
|
||||
PR="$(gh api "repos/${REPO_SLUG}/commits/${SHA}/pulls" --jq '.[0].number // empty' 2>"${GH_ERR_FILE}")" || {
|
||||
if grep -q 'No commit found' "${GH_ERR_FILE}"; then
|
||||
PR='' # not pushed to GitHub yet, so it can not have come from a PR
|
||||
else
|
||||
printf >&2 'release-notes: failed to look up the PR for commit %s:\n' "${SHA}"
|
||||
cat >&2 "${GH_ERR_FILE}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
case "${PR}" in
|
||||
'' | *[!0-9]*) ;;
|
||||
*) REF=" (#${PR})" ;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
printf ' - %s%s\n' "${TEXT}" "${REF}"
|
||||
done || exit 1
|
||||
}
|
||||
|
||||
printf '%s\n' "${NEW_VERSION}"
|
||||
print_section 'new' 'New Stuff' &&
|
||||
print_section 'fix' 'Bug Fixes' &&
|
||||
print_section 'refactor' 'Refactors' &&
|
||||
print_section 'robustness' 'Robustness' &&
|
||||
print_section 'perf' 'Performance' &&
|
||||
print_section 'dockerfile' 'Dockerfile' &&
|
||||
print_section 'docs' 'Docs' &&
|
||||
print_section 'misc' 'Misc' &&
|
||||
print_section 'tests' 'Tests'
|
||||
@@ -39,5 +39,11 @@ NVM_AUTH_HEADER='Bearer test-token' nvm_download "https://nodejs.org/dist/x" -o
|
||||
grep -Fxqe '--header' "$ARGV_LOG" || die "wget did not receive --header; got: $(cat "$ARGV_LOG")"
|
||||
grep -Fxq 'Authorization: Bearer test-token' "$ARGV_LOG" || die "wget did not receive a well-formed Authorization header; got: $(cat "$ARGV_LOG")"
|
||||
|
||||
# given a credential using every character RFC 7235 token68 permits, including '~'
|
||||
# when nvm_download uses the wget path
|
||||
NVM_AUTH_HEADER='Bearer mF_9.B5f-4.1JqM~+/=' nvm_download "https://nodejs.org/dist/x" -o - || die 'nvm_download (wget) returned nonzero for a token68 credential'
|
||||
# then it reaches wget byte-for-byte, with no character silently dropped
|
||||
grep -Fxq 'Authorization: Bearer mF_9.B5f-4.1JqM~+/=' "$ARGV_LOG" || die "wget did not receive the token68 credential intact; got: $(cat "$ARGV_LOG")"
|
||||
|
||||
cleanup
|
||||
echo "nvm_download wget Authorization header: passed"
|
||||
|
||||
@@ -52,3 +52,26 @@ testMirrors 'not a url'
|
||||
testMirrors 'ftp://wrong-scheme'
|
||||
testMirrors 'http://'
|
||||
testMirrors 'javascript:alert(1)'
|
||||
|
||||
# a query string can never work, since nvm appends a path to the mirror
|
||||
testMirrors 'https://nodejs.org/dist?token=abc'
|
||||
testMirrors 'https://nodejs.org/dist#frag'
|
||||
|
||||
testAcceptedMirrors() {
|
||||
NVM_NODEJS_ORG_MIRROR="${1-}"
|
||||
[ "$(nvm_get_mirror node std)" = "${1-}" ] || die "NVM_NODEJS_ORG_MIRROR should accept ${1-}"
|
||||
unset NVM_NODEJS_ORG_MIRROR
|
||||
|
||||
NVM_IOJS_ORG_MIRROR="${1-}"
|
||||
[ "$(nvm_get_mirror iojs std)" = "${1-}" ] || die "NVM_IOJS_ORG_MIRROR should accept ${1-}"
|
||||
unset NVM_IOJS_ORG_MIRROR
|
||||
}
|
||||
|
||||
# a private mirror on a non-default port is a URL, and must not be rejected
|
||||
testAcceptedMirrors 'https://mirror.internal:8443/dist'
|
||||
testAcceptedMirrors 'http://localhost:8080/dist'
|
||||
# an IPv6 literal host, userinfo, percent-encoding, and `~` are all legal too
|
||||
testAcceptedMirrors 'http://[::1]:8080/dist'
|
||||
testAcceptedMirrors 'https://user:pw@nexus.corp.example.com/repository/nodejs-dist'
|
||||
testAcceptedMirrors 'https://mirror.internal/a%20b/dist'
|
||||
testAcceptedMirrors 'https://mirror.internal/~dist'
|
||||
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
cleanup () {
|
||||
rm -rf "${TEST_DIR-}"
|
||||
unset TEST_DIR OUTPUT EXPECTED
|
||||
}
|
||||
|
||||
: nvm.sh
|
||||
\. ../../../nvm.sh
|
||||
|
||||
TEST_DIR="${PWD}/nvm_print_alias_file_tmp"
|
||||
mkdir -p "${TEST_DIR}" || die 'failed to create test dir'
|
||||
|
||||
printf 'v0.10 # inline comment\n' > "${TEST_DIR}/inline"
|
||||
OUTPUT="$(nvm_print_alias_file "${TEST_DIR}/inline")"
|
||||
[ "_${OUTPUT}" = '_v0.10' ] || die "inline comment not stripped; got '${OUTPUT}'"
|
||||
|
||||
printf '# leading comment\nv0.11\n' > "${TEST_DIR}/comment-first"
|
||||
OUTPUT="$(nvm_print_alias_file "${TEST_DIR}/comment-first")"
|
||||
[ "_${OUTPUT}" = '_v0.11' ] || die "comment-only line not skipped; got '${OUTPUT}'"
|
||||
|
||||
printf 'v0.12\t \nv0.13\n' > "${TEST_DIR}/trailing-space"
|
||||
OUTPUT="$(nvm_print_alias_file "${TEST_DIR}/trailing-space")"
|
||||
EXPECTED="$(printf 'v0.12\nv0.13')"
|
||||
[ "_${OUTPUT}" = "_${EXPECTED}" ] || die "trailing whitespace not stripped, or a line was dropped; got '${OUTPUT}'"
|
||||
|
||||
printf '\n \n\t\n# only a comment\n' > "${TEST_DIR}/nothing-usable"
|
||||
OUTPUT="$(nvm_print_alias_file "${TEST_DIR}/nothing-usable")"
|
||||
[ "_${OUTPUT}" = '_' ] || die "blank and comment-only lines should produce no output; got '${OUTPUT}'"
|
||||
|
||||
nvm_print_alias_file "${TEST_DIR}/nothing-usable" >/dev/null 2>&1 \
|
||||
|| die 'a file with no usable lines should still exit zero'
|
||||
|
||||
printf 'v0.14' > "${TEST_DIR}/no-trailing-newline"
|
||||
OUTPUT="$(nvm_print_alias_file "${TEST_DIR}/no-trailing-newline")"
|
||||
[ "_${OUTPUT}" = '_v0.14' ] || die "a final line with no trailing newline should be read; got '${OUTPUT}'"
|
||||
|
||||
# a `#` pattern is a repetition operator under zsh's `extendedglob`, which is what
|
||||
# made `nvm_alias` print nothing at all: https://github.com/nvm-sh/nvm/issues/3885
|
||||
if [ -n "${ZSH_VERSION-}" ]; then
|
||||
setopt extendedglob || die 'enabling extendedglob failed'
|
||||
OUTPUT="$(nvm_print_alias_file "${TEST_DIR}/inline")"
|
||||
[ "_${OUTPUT}" = '_v0.10' ] || die "with extendedglob set, expected 'v0.10', got '${OUTPUT}'"
|
||||
[[ -o extendedglob ]] || die 'nvm_print_alias_file left extendedglob unset'
|
||||
|
||||
unsetopt extendedglob
|
||||
nvm_print_alias_file "${TEST_DIR}/inline" > /dev/null
|
||||
[[ -o extendedglob ]] && die 'nvm_print_alias_file left extendedglob set'
|
||||
fi
|
||||
|
||||
cleanup
|
||||
Executable
+197
@@ -0,0 +1,197 @@
|
||||
#!/bin/sh
|
||||
|
||||
ONESHOT=''
|
||||
cleanup () {
|
||||
if [ -n "${ONESHOT}" ]; then
|
||||
command rm -f "${ONESHOT}"
|
||||
fi
|
||||
}
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
\. ../../../nvm.sh
|
||||
|
||||
set -e
|
||||
|
||||
# assert about nvm, not about the caller's environment
|
||||
NVM_HAS_COLORS_WAS="${NVM_HAS_COLORS-}"
|
||||
unset NVM_HAS_COLORS
|
||||
|
||||
ESC="$(printf '\033')"
|
||||
# The legend's letters are wrapped in color codes when the terminal supports
|
||||
# them, so every text assertion below compares against the output with any
|
||||
# escapes removed. That keeps these checks about structure and alignment only.
|
||||
strip_colors() { command sed "s/${ESC}\[[0-9;]*m//g"; }
|
||||
|
||||
# Exact whole-line match against an already-captured string. Deliberately
|
||||
# pipe-free: `grep -q` exits at its first match and hands SIGPIPE to whatever
|
||||
# feeds it, which BSD sed swallows but GNU sed reports as "couldn't flush
|
||||
# stdout", polluting the test's stderr.
|
||||
contains_line () {
|
||||
case "
|
||||
${2}
|
||||
" in
|
||||
*"
|
||||
${1}
|
||||
"*) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# This test file is itself an executable named `nvm_print_color_legend`, so a
|
||||
# plain `command -v` keeps finding it long after the function is gone. Emptying
|
||||
# `PATH` for the lookup is the only reliable way to ask about the function
|
||||
# alone: filtering on a `/` is not enough, because dash and zsh report a bare
|
||||
# name for a current-directory match reached through an empty `PATH` component.
|
||||
is_function () {
|
||||
[ -n "$(PATH=/nonexistent command -v "${1}" 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
is_function nvm_print_color_legend \
|
||||
|| die 'nvm_print_color_legend is not defined'
|
||||
|
||||
OUTPUT="$(nvm_print_color_legend)"
|
||||
|
||||
LINES="$(nvm_echo "${OUTPUT}" | command wc -l | command tr -d ' ')"
|
||||
[ "${LINES}" = 11 ] || die "expected 11 legend lines, got ${LINES}: ${OUTPUT}"
|
||||
|
||||
PLAIN="$(nvm_echo "${OUTPUT}" | strip_colors)"
|
||||
|
||||
# the two labels are literal, and their indentation lines the legend up under
|
||||
# the `nvm set-colors` entry in the help output
|
||||
contains_line ' Initial colors are:' "${PLAIN}" \
|
||||
|| die "the 'Initial colors are:' label is missing or misaligned: ${PLAIN}"
|
||||
contains_line ' Color codes:' "${PLAIN}" \
|
||||
|| die "the 'Color codes:' label is missing or misaligned: ${PLAIN}"
|
||||
|
||||
# the default-palette sample, indented one level deeper than its label
|
||||
contains_line ' bygre' "${PLAIN}" \
|
||||
|| die "the initial-colors sample is missing or misaligned: ${PLAIN}"
|
||||
|
||||
# all eight rows of the code table, in order, each with both letter forms
|
||||
for ROW in \
|
||||
'r/R = red / bold red' \
|
||||
'g/G = green / bold green' \
|
||||
'b/B = blue / bold blue' \
|
||||
'c/C = cyan / bold cyan' \
|
||||
'm/M = magenta / bold magenta' \
|
||||
'y/Y = yellow / bold yellow' \
|
||||
'k/K = black / bold black' \
|
||||
'e/W = light grey / white' \
|
||||
; do
|
||||
contains_line " ${ROW}" "${PLAIN}" \
|
||||
|| die "color code row '${ROW}' is missing or misaligned: ${PLAIN}"
|
||||
done
|
||||
|
||||
# the extracted function has to stay wired into the help output
|
||||
HELP_PLAIN="$(nvm --help | strip_colors)"
|
||||
contains_line ' Color codes:' "${HELP_PLAIN}" \
|
||||
|| die 'nvm --help no longer includes the color legend'
|
||||
|
||||
# --- the fix: colors have to survive command substitution ------------------
|
||||
|
||||
# the bug condition: inside `$( )`, `[ -t 1 ]` sees the capture pipe, so
|
||||
# `nvm_has_colors` always fails
|
||||
nvm_has_colors () { return 1; }
|
||||
|
||||
WRAPPED="$(nvm_wrap_with_color_code 'b' 'b')"
|
||||
case "${WRAPPED}" in
|
||||
*"${ESC}"*) die "expected plain text when colors are unsupported, got >${WRAPPED}<" ;;
|
||||
esac
|
||||
|
||||
NVM_HAS_COLORS=1
|
||||
export NVM_HAS_COLORS
|
||||
WRAPPED="$(nvm_wrap_with_color_code 'b' 'b')"
|
||||
[ "${WRAPPED}" = "${ESC}[0;34mb${ESC}[0m" ] \
|
||||
|| die "expected a colored 'b' with NVM_HAS_COLORS=1, got >${WRAPPED}<"
|
||||
|
||||
WRAPPED="$(nvm_wrap_with_color_code 'X' 'X')"
|
||||
[ "${WRAPPED}" = 'X' ] \
|
||||
|| die "expected plain text for an unknown color code, got >${WRAPPED}<"
|
||||
unset NVM_HAS_COLORS
|
||||
|
||||
# `0` is what the resolving callers start from, so it must not read as truthy
|
||||
NVM_HAS_COLORS=0
|
||||
export NVM_HAS_COLORS
|
||||
WRAPPED="$(nvm_wrap_with_color_code 'b' 'b')"
|
||||
case "${WRAPPED}" in
|
||||
*"${ESC}"*) die "NVM_HAS_COLORS=0 must not enable colors, got >${WRAPPED}<" ;;
|
||||
esac
|
||||
unset NVM_HAS_COLORS
|
||||
|
||||
UNSUPPORTED="$(nvm_print_color_legend)"
|
||||
case "${UNSUPPORTED}" in
|
||||
*"${ESC}"*) die "the legend emitted colors while unsupported: ${UNSUPPORTED}" ;;
|
||||
esac
|
||||
|
||||
# Model the real asymmetry: yes to the first, direct call, no to every later
|
||||
# one. The state has to live in a file, because each `$( )` is a fresh subshell
|
||||
# that would take its own copy of an in-shell counter and answer yes every time.
|
||||
ONESHOT="$(command mktemp)"
|
||||
oneshot_reset () { nvm_echo 0 > "${ONESHOT}"; }
|
||||
nvm_has_colors () {
|
||||
if [ "$(command cat "${ONESHOT}")" = 0 ]; then
|
||||
nvm_echo 1 > "${ONESHOT}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
oneshot_reset
|
||||
COLORED_OUTPUT="$(nvm_print_color_legend)"
|
||||
# `grep -c` drains its input, so it cannot SIGPIPE its producer
|
||||
COLORED="$(nvm_echo "${COLORED_OUTPUT}" | nvm_grep -c "${ESC}" || true)"
|
||||
[ "${COLORED}" = 9 ] \
|
||||
|| die "expected all 9 legend lines colored, got ${COLORED}: ${COLORED_OUTPUT}"
|
||||
|
||||
# the sample specifically, which is the case #3896 reports
|
||||
case "${COLORED_OUTPUT}" in
|
||||
*"${ESC}[0;34mb${ESC}[0m${ESC}[0;33my${ESC}[0m"*) : ;;
|
||||
*) die "the initial-colors sample was not colored: ${COLORED_OUTPUT}" ;;
|
||||
esac
|
||||
|
||||
# in a substitution, so `nvm_set_colors`' `export NVM_COLORS` stays contained
|
||||
oneshot_reset
|
||||
SET_COLORS_OUTPUT="$(nvm_set_colors 'bygre')"
|
||||
case "${SET_COLORS_OUTPUT}" in
|
||||
*"${ESC}"*) : ;;
|
||||
*) die "nvm_set_colors did not color its confirmation line: ${SET_COLORS_OUTPUT}" ;;
|
||||
esac
|
||||
|
||||
# coloring must change only the escapes, never the text or the alignment
|
||||
COLORED_STRIPPED="$(nvm_echo "${COLORED_OUTPUT}" | strip_colors)"
|
||||
[ "${COLORED_STRIPPED}" = "${PLAIN}" ] \
|
||||
|| die 'the colored legend does not match the plain legend once escapes are stripped'
|
||||
|
||||
# called directly rather than in a substitution, so a leak is observable at all
|
||||
oneshot_reset
|
||||
nvm_print_color_legend >/dev/null
|
||||
[ -z "${NVM_HAS_COLORS-}" ] \
|
||||
|| die "nvm_print_color_legend leaked NVM_HAS_COLORS=${NVM_HAS_COLORS}"
|
||||
|
||||
# And `nvm unload` has to clean it up, the way it does its sibling helpers.
|
||||
# `set +e` inside the subshell so a non-zero `nvm unload` cannot abort it before
|
||||
# the lookup runs; its status is reported separately, so "unload failed" can
|
||||
# never be misreported as "the function survived".
|
||||
UNLOAD_OUT="$(
|
||||
set +e
|
||||
nvm unload >/dev/null 2>&1
|
||||
# plain `echo`: `nvm unload` has just unset `nvm_echo`
|
||||
echo "unload_rc=$?"
|
||||
if is_function nvm_print_color_legend; then
|
||||
echo present
|
||||
else
|
||||
echo gone
|
||||
fi
|
||||
)"
|
||||
case "${UNLOAD_OUT}" in
|
||||
*gone*) : ;;
|
||||
*) die "nvm unload did not remove nvm_print_color_legend (${UNLOAD_OUT})" ;;
|
||||
esac
|
||||
|
||||
if [ -n "${NVM_HAS_COLORS_WAS}" ]; then
|
||||
NVM_HAS_COLORS="${NVM_HAS_COLORS_WAS}"
|
||||
export NVM_HAS_COLORS
|
||||
fi
|
||||
|
||||
cleanup
|
||||
echo "nvm_print_color_legend: passed"
|
||||
@@ -35,4 +35,18 @@ case "${RESULT}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Test 6: every character of RFC 7235 §2.1 `token68` is preserved.
|
||||
# token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
|
||||
# This is a superset of both base64 and base64url; note the '~', which no
|
||||
# base64 variant emits but which an opaque token may legitimately contain.
|
||||
TOKEN68="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~+/="
|
||||
RESULT=$(nvm_sanitize_auth_header "${TOKEN68}")
|
||||
[ "${RESULT}" = "${TOKEN68}" ] || die "FAIL: token68 chars were stripped. Got: '${RESULT}'"
|
||||
|
||||
# Test 7: the RFC 6750 §2.1 example Bearer token, extended with the remaining
|
||||
# valid `b64token` characters, survives intact.
|
||||
B64TOKEN="Bearer mF_9.B5f-4.1JqM~+/="
|
||||
RESULT=$(nvm_sanitize_auth_header "${B64TOKEN}")
|
||||
[ "${RESULT}" = "${B64TOKEN}" ] || die "FAIL: b64token chars were stripped. Got: '${RESULT}'"
|
||||
|
||||
echo "All nvm_sanitize_auth_header tests passed"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
cleanup () {
|
||||
rm -rf "${TEST_DIR-}"
|
||||
unset TEST_DIR NVM_DIR
|
||||
}
|
||||
|
||||
: nvm.sh
|
||||
\. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
# `local_options` is zsh-only, so no other shell can regress this
|
||||
[ -n "${ZSH_VERSION-}" ] || exit 0
|
||||
|
||||
# an isolated NVM_DIR with a single known version, so that ambient versions
|
||||
# and aliases can not affect any assertions. `alias/lts` is deliberately absent:
|
||||
# globbing it is why `nvm_list_aliases` has to suppress `nomatch` at all.
|
||||
TEST_DIR="${PWD}/nvm_zsh_options_tmp"
|
||||
mkdir -p "${TEST_DIR}/alias" "${TEST_DIR}/versions/node/v24.13.0/bin" || die 'failed to create test dirs'
|
||||
make_echo "${TEST_DIR}/versions/node/v24.13.0/bin/node" 'v24.13.0' || die 'failed to create test node binary'
|
||||
echo '24' > "${TEST_DIR}/alias/default" || die 'failed to create default alias'
|
||||
NVM_DIR="${TEST_DIR}"
|
||||
|
||||
setopt nomatch
|
||||
unsetopt markdirs
|
||||
unsetopt shwordsplit
|
||||
|
||||
nvm_list_aliases >/dev/null 2>&1
|
||||
[[ -o nomatch ]] || die 'nvm_list_aliases left nomatch unset'
|
||||
|
||||
nvm alias >/dev/null 2>&1
|
||||
[[ -o nomatch ]] || die '"nvm alias" left nomatch unset'
|
||||
|
||||
nvm ls >/dev/null 2>&1
|
||||
[[ -o nomatch ]] || die '"nvm ls" left nomatch unset'
|
||||
|
||||
# called directly rather than in a command substitution, so that anything
|
||||
# `nvm_ls` fails to restore is visible here
|
||||
nvm_ls 24 >/dev/null 2>&1
|
||||
[[ -o markdirs ]] && die 'nvm_ls left markdirs set'
|
||||
[[ -o shwordsplit ]] && die 'nvm_ls left shwordsplit set'
|
||||
|
||||
# and the inverse: a caller that wants these on has to get them back
|
||||
setopt markdirs
|
||||
setopt shwordsplit
|
||||
|
||||
nvm_ls 24 >/dev/null 2>&1
|
||||
[[ -o markdirs ]] || die 'nvm_ls left markdirs unset'
|
||||
[[ -o shwordsplit ]] || die 'nvm_ls left shwordsplit unset'
|
||||
|
||||
cleanup
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; exit 1; }
|
||||
|
||||
\. ../common.sh
|
||||
|
||||
# `#` is a pattern operator only under zsh's `extendedglob`
|
||||
[ -n "${ZSH_VERSION-}" ] || exit 0
|
||||
|
||||
# We need to unload nvm again first, as by the time this test is run,
|
||||
# despite being unloaded in setup, the inherited PATH still contains
|
||||
# an nvm-installed node version. `nvm unload` unsets NVM_DIR, so cache it.
|
||||
\. ../../nvm.sh || die 'sourcing returned nonzero exit code'
|
||||
NVM_DIR_CACHED="${NVM_DIR}"
|
||||
nvm unload || die 'unloading returned nonzero exit code'
|
||||
NVM_DIR="${NVM_DIR_CACHED}"
|
||||
|
||||
# the comment is the point: stripping it is what needs a `#` pattern
|
||||
echo '0.10.1 # comment' > "${NVM_DIR}/alias/default" || die 'creation of default alias failed'
|
||||
|
||||
setopt extendedglob || die 'enabling extendedglob failed'
|
||||
|
||||
\. ../../nvm.sh || die 'sourcing returned nonzero exit code'
|
||||
|
||||
[[ -o extendedglob ]] || die 'sourcing nvm.sh disabled extendedglob'
|
||||
|
||||
NVM_LS_CURRENT_NOT_GREPPED="$(nvm ls current | strip_colors)"
|
||||
NVM_LS_CURRENT="$(nvm ls current | strip_colors | \grep -o 'v0\.10\.1')"
|
||||
[ "_${NVM_LS_CURRENT}" = '_v0.10.1' ] || die "'nvm ls current' did not return '-> v0.10.1', got '${NVM_LS_CURRENT_NOT_GREPPED}'"
|
||||
|
||||
NVM_ALIAS_DEFAULT="$(nvm alias default | strip_colors)"
|
||||
[ "_${NVM_ALIAS_DEFAULT}" = '_default -> 0.10.1 (-> v0.10.1 *)' ] \
|
||||
|| die "'nvm alias default' did not return 'default -> 0.10.1 (-> v0.10.1 *)', got '${NVM_ALIAS_DEFAULT}'"
|
||||
Reference in New Issue
Block a user