From cbdd41eee2b84a155eb639cb825686529546f439 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 11 Jun 2017 14:15:04 -0700 Subject: [PATCH] [New] `nvm install`: add `--latest-npm` option to automatically try to upgrade to the latest working version of `npm`. - also add `nvm install-latest-npm` top-level command --- nvm.sh | 93 ++++++++++++++++++- test/fast/Unit tests/nvm_install_latest_npm | 58 ++++++++++++ test/installation_node/install latest npm | 34 +++++++ .../install with --latest-npm | 12 +++ 4 files changed, 196 insertions(+), 1 deletion(-) create mode 100755 test/fast/Unit tests/nvm_install_latest_npm create mode 100755 test/installation_node/install latest npm create mode 100755 test/installation_node/install with --latest-npm diff --git a/nvm.sh b/nvm.sh index 9d91e1a..f4aa8da 100644 --- a/nvm.sh +++ b/nvm.sh @@ -143,6 +143,74 @@ nvm_print_npm_version() { 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)")" + 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 + local NPM_VERSION + NPM_VERSION="$(npm --version 2>/dev/null)" + 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='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.0.0 "${NODE_VERSION}"; then + nvm_echo '* `npm` v4.5.x is the last version that works on `node` versions below v1.0.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 + 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 + 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 @@ -2211,6 +2279,7 @@ nvm() { nvm_echo ' --lts When installing, only select from LTS (long-term support) versions' nvm_echo ' --lts= When installing, only select from versions for a specific LTS line' 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 ' nvm uninstall Uninstall a version' nvm_echo ' nvm uninstall --lts Uninstall using automatic LTS (long-term support) alias `lts/*`, if available.' nvm_echo ' nvm uninstall --lts= Uninstall using automatic alias for provided LTS line, if available.' @@ -2239,6 +2308,7 @@ nvm() { nvm_echo ' nvm alias [] Show all aliases beginning with ' nvm_echo ' nvm alias Set an alias named pointing to ' nvm_echo ' nvm unalias Deletes the alias named ' + nvm_echo ' nvm install-latest-npm Attempt to upgrade to the latest working `npm` on the current node version' nvm_echo ' nvm reinstall-packages Reinstall global `npm` packages contained in to current version' nvm_echo ' nvm unload Unload `nvm` from shell' nvm_echo ' nvm which [] Display path to installed node version. Uses .nvmrc if available' @@ -2344,6 +2414,8 @@ nvm() { local nobinary nobinary=0 local LTS + local NVM_UPGRADE_NPM + NVM_UPGRADE_NPM=0 while [ $# -ne 0 ] do case "$1" in @@ -2364,6 +2436,10 @@ nvm() { LTS="${1##--lts=}" shift ;; + --latest-npm) + NVM_UPGRADE_NPM=1 + shift + ;; *) break # stop parsing args ;; @@ -2496,6 +2572,9 @@ nvm() { if nvm_is_version_installed "$VERSION"; then nvm_err "$VERSION is already installed." if nvm use "$VERSION"; then + if [ "${NVM_UPGRADE_NPM}" = 1 ]; then + nvm install-latest-npm + fi if [ -z "${SKIP_DEFAULT_PACKAGES-}" ] && [ -n "${DEFAULT_PACKAGES-}" ]; then nvm_install_default_packages "$DEFAULT_PACKAGES" fi @@ -2568,6 +2647,10 @@ nvm() { else nvm_ensure_default_set "$provided_version" fi + if [ "${NVM_UPGRADE_NPM}" = 1 ]; then + nvm install-latest-npm + EXIT_CODE=$? + fi if [ -z "${SKIP_DEFAULT_PACKAGES-}" ] && [ -n "${DEFAULT_PACKAGES-}" ]; then nvm_install_default_packages "$DEFAULT_PACKAGES" fi @@ -3174,6 +3257,14 @@ nvm() { command rm -f "$NVM_ALIAS_DIR/${1}" nvm_echo "Deleted alias ${1} - restore it with \`nvm alias \"${1}\" \"$NVM_ALIAS_ORIGINAL\"\`" ;; + "install-latest-npm") + if [ $# -ne 0 ]; then + >&2 nvm --help + return 127 + fi + + nvm_install_latest_npm + ;; "reinstall-packages" | "copy-packages" ) if [ $# -ne 1 ]; then >&2 nvm --help @@ -3290,7 +3381,7 @@ nvm() { nvm_version_path nvm_alias_path nvm_version_dir \ nvm_find_nvmrc nvm_find_up nvm_tree_contains_path \ nvm_version_greater nvm_version_greater_than_or_equal_to \ - nvm_print_npm_version nvm_npm_global_modules \ + 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_curl_use_compression nvm_curl_version \ nvm_supports_source_options nvm_auto nvm_supports_xz \ diff --git a/test/fast/Unit tests/nvm_install_latest_npm b/test/fast/Unit tests/nvm_install_latest_npm new file mode 100755 index 0000000..ecf9c74 --- /dev/null +++ b/test/fast/Unit tests/nvm_install_latest_npm @@ -0,0 +1,58 @@ +#!/bin/sh + +\. ../../common.sh + +die () { echo "$@" ; exit 1; } + +\. ../../../nvm.sh + +nvm deactivate >/dev/null 2>&1 + +CURRENT="$(nvm current)" +[ "$CURRENT" = 'none' ] || [ "$CURRENT" = 'system' ] || die "nvm should be using none or system; got $CURRENT" + +nvm_ls_current() { + echo 'none' +} +node() { + return 1 +} +npm() { + echo '1.2.3' +} + +OUTPUT="$(nvm_install_latest_npm 2>&1 >/dev/null)" +EXIT_CODE="$(nvm_install_latest_npm >/dev/null 2>&1 ; echo $?)" + +EXPECTED="Unable to obtain node version." +[ "${OUTPUT}" = "${EXPECTED}" ] || die "When node is unavailable, expected >${EXPECTED}<; got >${OUTPUT}" + +node() { + echo 'v4.5.6' +} +nvm_ls_current() { + node --version +} +npm() { + return 1 +} +OUTPUT="$(nvm_install_latest_npm 2>&1 >/dev/null)" +EXIT_CODE="$(nvm_install_latest_npm >/dev/null 2>&1 ; echo $?)" + +EXPECTED="Unable to obtain npm version." +[ "${OUTPUT}" = "${EXPECTED}" ] || die "When node is available and npm is unavailable, expected >${EXPECTED}<; got >${OUTPUT}" + +node() { + echo 'v4.5.6' +} +nvm_ls_current() { + echo 'system' +} +npm() { + return 1 +} +OUTPUT="$(nvm_install_latest_npm 2>&1 >/dev/null)" +EXIT_CODE="$(nvm_install_latest_npm >/dev/null 2>&1 ; echo $?)" + +EXPECTED="Unable to obtain npm version." +[ "${OUTPUT}" = "${EXPECTED}" ] || die "When node is system and npm is unavailable, expected >${EXPECTED}<; got >${OUTPUT}" diff --git a/test/installation_node/install latest npm b/test/installation_node/install latest npm new file mode 100755 index 0000000..6527eca --- /dev/null +++ b/test/installation_node/install latest npm @@ -0,0 +1,34 @@ +#!/bin/sh + +set -ex + +die () { echo "$@" ; exit 1; } + +set +e # todo: fix +\. ../../nvm.sh +set -e + +nvm deactivate >/dev/null 2>&1 || die 'unable to deactivate: 1' +nvm install 4 >/dev/null 2>&1 || die 'install v4 failed' +nvm install-latest-npm || die 'nvm install-latest-npm failed: 1' +NPM_VERSION="$(npm --version)" +nvm_version_greater_than_or_equal_to "${NPM_VERSION}" 5.0.0 || die "node v4.x updates to ${NPM_VERSION}; expected >= v5" + +nvm deactivate >/dev/null 2>&1 || die 'unable to deactivate: 2' +nvm install 1 >/dev/null 2>&1 || die 'install v1 failed' +nvm install-latest-npm || die 'nvm install-latest-npm failed: 2' +NPM_VERSION="$(npm --version)" +[ "${NPM_VERSION}" = '4.6.1' ] || die "io.js v1.x updates to ${NPM_VERSION}; expected v4.6.1" + +nvm deactivate >/dev/null 2>&1 || die 'unable to deactivate: 3' +nvm install 0.8.27 >/dev/null 2>&1 || die 'install v0.8 failed' +nvm install-latest-npm || die 'nvm install-latest-npm failed: 3' +NPM_VERSION="$(npm --version)" +[ "${NPM_VERSION}" = '4.5.0' ] || die "node 0.8.27 updates to ${NPM_VERSION}; expected v4.5.0" + +nvm deactivate >/dev/null 2>&1 || die 'unable to deactivate: 4' +nvm install 0.6.21 >/dev/null 2>&1 || die 'install v0.6 failed' +export NPM_CONFIG_STRICT_SSL=false # npm 1 on travis can't handle SSL to npm +nvm install-latest-npm || die 'nvm install-latest-npm failed: 4' +NPM_VERSION="$(npm --version)" +[ "${NPM_VERSION}" = '1.3.26' ] || die "node 0.6.21 updates to ${NPM_VERSION}; expected v1.3.26" diff --git a/test/installation_node/install with --latest-npm b/test/installation_node/install with --latest-npm new file mode 100755 index 0000000..55ac74b --- /dev/null +++ b/test/installation_node/install with --latest-npm @@ -0,0 +1,12 @@ +#!/bin/sh + +set -ex + +die () { echo "$@" ; exit 1; } + +set +e # todo: fix +\. ../../nvm.sh +set -e + +NVM_DEBUG=1 nvm install --latest-npm 4.2.2 \ + | grep 'Attempting to upgrade to the latest working version of npm...' || die 'did not call through to nvm_install_latest_npm'