diff --git a/.dockerignore b/.dockerignore index fc578cc..52e5428 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,6 +8,7 @@ test/bak .urchin.log .urchin_stdout test/**/test_output +test/**/.nvmrc node_modules/ npm-debug.log diff --git a/.github/workflows/nvm-install-test.yml b/.github/workflows/nvm-install-test.yml new file mode 100644 index 0000000..fd82d2b --- /dev/null +++ b/.github/workflows/nvm-install-test.yml @@ -0,0 +1,104 @@ +name: 'Tests: nvm install with set -e' + +on: + pull_request: + push: + workflow_dispatch: + inputs: + ref: + description: 'git ref to use' + required: false + default: 'HEAD' + +jobs: + matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - id: matrix + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ -n "${{ github.event.inputs.ref }}" ]; then + echo "matrix=\"[\"${{ github.event.inputs.ref }}\"]\"" >> $GITHUB_OUTPUT + else + TAGS="$((echo "HEAD" && git tag --sort=-v:refname --merged HEAD --format='%(refname:strip=2) %(creatordate:short)' | grep '^v' | while read tag date; do + if [ "$(uname)" == "Darwin" ]; then + timestamp=$(date -j -f "%Y-%m-%d" "$date" +%s) + threshold=$(date -j -v-4y +%s) + else + timestamp=$(date -d "$date" +%s) + threshold=$(date -d "4 years ago" +%s) + fi + if [ $timestamp -ge $threshold ]; then echo "$tag"; fi + done) | xargs)" + echo $TAGS + TAGS_JSON=$(printf "%s\n" $TAGS | jq -R . | jq -sc .) + echo "matrix=${TAGS_JSON}" >> $GITHUB_OUTPUT + fi + + test: + 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: + ref: ${{ fromJson(needs.matrix.outputs.matrix) }} + has-nvmrc: + - 'no nvmrc' + - 'nvmrc' + shell-level: + - 1 shlvl + - 2 shlvls + + steps: + - uses: actions/checkout@v4 + - name: resolve HEAD to sha + run: | + if [ '${{ matrix.ref }}' = 'HEAD' ]; then + REF="$(git rev-parse HEAD)" + else + REF="${{ matrix.ref }}" + fi + echo "resolved ref: ${REF}" + echo "ref="$REF"" >> $GITHUB_ENV + - run: echo $- # which options are set + - run: echo node > .nvmrc + if: ${{ matrix.has-nvmrc == 'nvmrc' }} + - run: curl -I --compressed -v https://nodejs.org/dist/ + - name: 'install nvm' + run: | + set -e + export NVM_INSTALL_VERSION="${ref}" + curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/${ref}/install.sh" | bash + - name: nvm --version + run: | + set +e + . $NVM_DIR/nvm.sh && nvm --version + - name: nvm install in 1 shell level, ${{ matrix.has-nvmrc }} + if: ${{ matrix.shell-level == '1 shlvl' }} + run: | + set -ex + . $NVM_DIR/nvm.sh + echo nvm.sh sourced + nvm --version + if [ '${{ matrix.has-nvmrc }}' == 'nvmrc' ]; then + nvm install + fi + - name: nvm install in 2 shell levels, ${{ matrix.has-nvmrc }} + if: ${{ matrix.shell-level == '2 shlvls' }} + 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 + + finisher: + runs-on: ubuntu-latest + needs: [test] + steps: + - run: true diff --git a/.gitignore b/.gitignore index fcf59f8..ec161d4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ test/bak .urchin.log .urchin_stdout test/**/test_output +test/**/.nvmrc node_modules/ npm-debug.log diff --git a/Makefile b/Makefile index cc2944b..ddd679e 100644 --- a/Makefile +++ b/Makefile @@ -40,10 +40,14 @@ list: # Note that preexisting NVM_* variables are unset to avoid interfering with tests, except when running the Travis tests (where NVM_DIR must be passed in and the env. is assumed to be pristine). .PHONY: $(SHELL_TARGETS) $(SHELL_TARGETS): - @shell='$@'; shell=$${shell##*-}; which "$$shell" >/dev/null || { printf '\033[0;31m%s\033[0m\n' "WARNING: Cannot test with shell '$$shell': not found." >&2; exit 0; } && \ + @shell='$@'; shell=$${shell##*-}; \ + which "$$shell" >/dev/null || { printf '\033[0;31m%s\033[0m\n' "WARNING: Cannot test with shell '$$shell': not found." >&2; exit 0; } && \ printf '\n\033[0;34m%s\033[0m\n' "Running tests in $$shell"; \ [ -z "$$TRAVIS_BUILD_DIR" ] && for v in $$(set | awk -F'=' '$$1 ~ "^NVM_" { print $$1 }'); do unset $$v; done && unset v; \ - for suite in $(TEST_SUITE); do $(URCHIN) -f -s $$shell test/$$suite || exit; done + for suite in $(TEST_SUITE); do \ + echo "Running test suite: $$suite"; \ + $(URCHIN) -f -s $$shell test/$$suite || exit; \ + done # All-tests target: invokes the specified test suites for ALL shells defined in $(SHELLS). .PHONY: test diff --git a/README.md b/README.md index cc021e6..95b6cad 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ -# Node Version Manager [![Build Status](https://app.travis-ci.com/nvm-sh/nvm.svg?branch=master)][3] [![nvm version](https://img.shields.io/badge/version-v0.39.7-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684) +# Node Version Manager [![Build Status](https://app.travis-ci.com/nvm-sh/nvm.svg?branch=master)][3] [![nvm version](https://img.shields.io/badge/version-v0.40.0-yellow.svg)][4] [![CII Best Practices](https://bestpractices.dev/projects/684/badge)](https://bestpractices.dev/projects/684) @@ -39,6 +39,7 @@ - [Restoring PATH](#restoring-path) - [Set default node version](#set-default-node-version) - [Use a mirror of node binaries](#use-a-mirror-of-node-binaries) + - [Pass Authorization header to mirror](#pass-authorization-header-to-mirror) - [.nvmrc](#nvmrc) - [Deeper Shell Integration](#deeper-shell-integration) - [Calling `nvm use` automatically in a directory with a `.nvmrc` file](#calling-nvm-use-automatically-in-a-directory-with-a-nvmrc-file) @@ -60,6 +61,8 @@ - [macOS Troubleshooting](#macos-troubleshooting) - [WSL Troubleshooting](#wsl-troubleshooting) - [Maintainers](#maintainers) +- [Project Support](#project-support) +- [Enterprise Support](#enterprise-support) - [License](#license) - [Copyright notice](#copyright-notice) @@ -99,10 +102,10 @@ nvm is a version manager for [node.js](https://nodejs.org/en/), designed to be i To **install** or **update** nvm, you should run the [install script][2]. To do that, you may either download and run the script manually, or use the following cURL or Wget command: ```sh -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` ```sh -wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` Running either of the above commands downloads a script and runs it. The script clones the nvm repository to `~/.nvm`, and attempts to add the source lines from the snippet below to the correct profile file (`~/.bash_profile`, `~/.zshrc`, `~/.profile`, or `~/.bashrc`). @@ -124,7 +127,7 @@ Eg: `curl ... | NVM_DIR="path/to/nvm"`. Ensure that the `NVM_DIR` does not conta - The installer can use `git`, `curl`, or `wget` to download `nvm`, whichever is available. -- You can instruct the installer to not edit your shell config (for example if you already get completions via a [zsh nvm plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/nvm)) by setting `PROFILE=/dev/null` before running the `install.sh` script. Here's an example one-line command to do that: `PROFILE=/dev/null bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash'` +- You can instruct the installer to not edit your shell config (for example if you already get completions via a [zsh nvm plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/nvm)) by setting `PROFILE=/dev/null` before running the `install.sh` script. Here's an example one-line command to do that: `PROFILE=/dev/null bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash'` #### Troubleshooting on Linux @@ -172,7 +175,7 @@ You can use a task: ```yaml - name: Install nvm ansible.builtin.shell: > - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash args: creates: "{{ ansible_env.HOME }}/.nvm/nvm.sh" ``` @@ -234,7 +237,7 @@ If you have `git` installed (requires git v1.7.10+): 1. clone this repo in the root of your user profile - `cd ~/` from anywhere then `git clone https://github.com/nvm-sh/nvm.git .nvm` -1. `cd ~/.nvm` and check out the latest version with `git checkout v0.39.7` +1. `cd ~/.nvm` and check out the latest version with `git checkout v0.40.0` 1. activate `nvm` by sourcing it from your shell: `. ./nvm.sh` Now add these lines to your `~/.bashrc`, `~/.profile`, or `~/.zshrc` file to have it automatically sourced upon login: @@ -530,6 +533,13 @@ NVM_IOJS_ORG_MIRROR=https://iojs.org/dist nvm install iojs-v1.0.3 `nvm use` will not, by default, create a "current" symlink. Set `$NVM_SYMLINK_CURRENT` to "true" to enable this behavior, which is sometimes useful for IDEs. Note that using `nvm` in multiple shell tabs with this environment variable enabled can cause race conditions. +#### Pass Authorization header to mirror +To pass an Authorization header through to the mirror url, set `$NVM_AUTH_HEADER` + +```sh +NVM_AUTH_HEADER="Bearer secret-token" nvm install node +``` + ### .nvmrc You can create a `.nvmrc` file containing a node version number (or any other string that `nvm` understands; see `nvm --help` for details) in the project root directory (or any parent directory). @@ -833,13 +843,13 @@ If installing nvm on Alpine Linux *is* still what you want or need to do, you sh ### Alpine Linux 3.13+ ```sh apk add -U curl bash ca-certificates openssl ncurses coreutils python3 make gcc g++ libgcc linux-headers grep util-linux binutils findutils -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` ### Alpine Linux 3.5 - 3.12 ```sh apk add -U curl bash ca-certificates openssl ncurses coreutils python2 make gcc g++ libgcc linux-headers grep util-linux binutils findutils -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash ``` _Note: Alpine 3.5 can only install NodeJS versions up to v6.9.5, Alpine 3.6 can only install versions up to v6.10.3, Alpine 3.7 installs versions up to v8.9.3, Alpine 3.8 installs versions up to v8.14.0, Alpine 3.9 installs versions up to v10.19.0, Alpine 3.10 installs versions up to v10.24.1, Alpine 3.11 installs versions up to v12.22.6, Alpine 3.12 installs versions up to v12.22.12, Alpine 3.13 & 3.14 install versions up to v14.20.0, Alpine 3.15 & 3.16 install versions up to v16.16.0 (**These are all versions on the main branch**). Alpine 3.5 - 3.12 required the package `python2` to build NodeJS, as they are older versions to build. Alpine 3.13+ requires `python3` to successfully build newer NodeJS versions, but you can use `python2` with Alpine 3.13+ if you need to build versions of node supported in Alpine 3.5 - 3.15, you just need to specify what version of NodeJS you need to install in the package install script._ @@ -942,9 +952,9 @@ You have to make sure that the user directory name in `$HOME` and the user direc To change the user directory and/or account name follow the instructions [here](https://support.apple.com/en-us/HT201548) [1]: https://github.com/nvm-sh/nvm.git -[2]: https://github.com/nvm-sh/nvm/blob/v0.39.7/install.sh +[2]: https://github.com/nvm-sh/nvm/blob/v0.40.0/install.sh [3]: https://app.travis-ci.com/nvm-sh/nvm -[4]: https://github.com/nvm-sh/nvm/releases/tag/v0.39.7 +[4]: https://github.com/nvm-sh/nvm/releases/tag/v0.40.0 [Urchin]: https://git.sdf.org/tlevine/urchin [Fish]: https://fishshell.com @@ -1002,7 +1012,7 @@ Here's what you will need to do: If one of these broken versions is installed on your system, the above step will likely still succeed even if you didn't include the `--shared-zlib` flag. However, later, when you attempt to `npm install` something using your old version of node.js, you will see `incorrect data check` errors. If you want to avoid the possible hassle of dealing with this, include that flag. - For more details, see [this issue](https://github.com/nodejs/node/issues/39313) and [this comment](https://github.com/nodejs/node/issues/39313#issuecomment-90.39.776) + For more details, see [this issue](https://github.com/nodejs/node/issues/39313) and [this comment](https://github.com/nodejs/node/issues/39313#issuecomment-90.40.076) - Exit back to your native shell. @@ -1029,7 +1039,7 @@ Now you should be able to use node as usual. If you've encountered this error on WSL-2: ```sh - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0curl: (6) Could not resolve host: raw.githubusercontent.com @@ -1062,6 +1072,16 @@ You can check the contents of the file by running: Currently, the sole maintainer is [@ljharb](https://github.com/ljharb) - more maintainers are quite welcome, and we hope to add folks to the team over time. [Governance](./GOVERNANCE.md) will be re-evaluated as the project evolves. +## Project Support + +Only the latest version (v0.40.0 at this time) is supported. + +## Enterprise Support + +If you are unable to update to the latest version of `nvm`, our [partners](https://openjsf.org/ecosystem-sustainability-program) provide commercial security fixes for all unsupported versions: + + - [HeroDevs Never-Ending Support](https://www.herodevs.com/support?utm_source=OpenJS&utm_medium=Link&utm_campaign=nvm_openjs) + ## License See [LICENSE.md](./LICENSE.md). diff --git a/install.sh b/install.sh index 40c1cdf..4203fbf 100755 --- a/install.sh +++ b/install.sh @@ -33,7 +33,7 @@ nvm_install_dir() { } nvm_latest_version() { - nvm_echo "v0.39.7" + nvm_echo "v0.40.0" } nvm_profile_is_bash_or_zsh() { @@ -358,7 +358,7 @@ nvm_check_global_modules() { command printf %s\\n "$NPM_GLOBAL_MODULES" nvm_echo '=> If you wish to uninstall them at a later point (or re-install them under your' # shellcheck disable=SC2016 - nvm_echo '=> `nvm` Nodes), you can remove them from the system Node as follows:' + nvm_echo '=> `nvm` node installs), you can remove them from the system Node as follows:' nvm_echo nvm_echo ' $ nvm use system' nvm_echo ' $ npm uninstall -g a_module' diff --git a/nvm.sh b/nvm.sh old mode 100644 new mode 100755 index 6dc779e..cf96950 --- a/nvm.sh +++ b/nvm.sh @@ -81,9 +81,9 @@ nvm_command_info() { nvm_has_colors() { local NVM_NUM_COLORS if nvm_has tput; then - NVM_NUM_COLORS="$(tput -T "${TERM:-vt100}" colors)" + NVM_NUM_COLORS="$(command tput -T "${TERM:-vt100}" colors)" fi - [ "${NVM_NUM_COLORS:--1}" -ge 8 ] + [ "${NVM_NUM_COLORS:--1}" -ge 8 ] && [ "${NVM_NO_COLORS-}" != '--no-colors' ] } nvm_curl_libz_support() { @@ -116,12 +116,19 @@ nvm_get_latest() { } nvm_download() { - local CURL_COMPRESSED_FLAG if nvm_has "curl"; then + local CURL_COMPRESSED_FLAG="" + local CURL_HEADER_FLAG="" + + if [ -n "${NVM_AUTH_HEADER:-}" ]; then + sanitized_header=$(nvm_sanitize_auth_header "${NVM_AUTH_HEADER}") + CURL_HEADER_FLAG="--header \"Authorization: ${sanitized_header}\"" + fi + if nvm_curl_use_compression; then CURL_COMPRESSED_FLAG="--compressed" fi - curl --fail ${CURL_COMPRESSED_FLAG:-} -q "$@" + eval "curl -q --fail ${CURL_COMPRESSED_FLAG:-} ${CURL_HEADER_FLAG:-} $*" elif nvm_has "wget"; then # Emulate curl with wget ARGS=$(nvm_echo "$@" | command sed -e 's/--progress-bar /--progress=bar /' \ @@ -133,11 +140,20 @@ nvm_download() { -e 's/-sS /-nv /' \ -e 's/-o /-O /' \ -e 's/-C - /-c /') + + if [ -n "${NVM_AUTH_HEADER:-}" ]; then + ARGS="${ARGS} --header \"${NVM_AUTH_HEADER}\"" + fi # shellcheck disable=SC2086 eval wget $ARGS fi } +nvm_sanitize_auth_header() { + # Remove potentially dangerous characters + nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -]//g' +} + nvm_has_system_node() { [ "$(nvm deactivate >/dev/null 2>&1 && command -v node)" != '' ] } @@ -370,8 +386,9 @@ nvm_install_latest_npm() { || { [ $NVM_IS_16_OR_ABOVE -eq 1 ] && [ $NVM_IS_16_LTS_OR_ABOVE -eq 0 ]; } \ || { [ $NVM_IS_17_OR_ABOVE -eq 1 ] && [ $NVM_IS_18_OR_ABOVE -eq 0 ]; } \ ; then - nvm_echo '* `npm` `v8.x` is the last version that works on `node` `v12`, `v14.13` - `v14.16`, or `v16.0` - `v16.12`' - $NVM_NPM_CMD install -g npm@8 + nvm_echo '* `npm` `v8.6` is the last version that works on `node` `v12`, `v14.13` - `v14.16`, or `v16.0` - `v16.12`' + # ^8.7 breaks `npm ls` on file: deps + $NVM_NPM_CMD install -g npm@8.6 elif \ [ $NVM_IS_18_17_OR_ABOVE -eq 0 ] \ || { [ $NVM_IS_19_OR_ABOVE -eq 1 ] && [ $NVM_IS_20_5_OR_ABOVE -eq 0 ]; } \ @@ -480,15 +497,15 @@ additionally, a single bare nvm-recognized version-ish must be present (after st warn_text="non-commented content parsed: ${1}" - nvm_err "$(nvm_wrap_with_color_code r "${error_text}") + nvm_err "$(nvm_wrap_with_color_code 'r' "${error_text}") -$(nvm_wrap_with_color_code y "${warn_text}")" +$(nvm_wrap_with_color_code 'y' "${warn_text}")" } nvm_process_nvmrc() { - local NVMRC_PATH="$1" + local NVMRC_PATH + NVMRC_PATH="$1" local lines - local unpaired_line lines=$(command sed 's/#.*//' "$NVMRC_PATH" | command sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | nvm_grep -v '^$') @@ -498,8 +515,12 @@ nvm_process_nvmrc() { fi # Initialize key-value storage - local keys='' - local values='' + local keys + keys='' + local values + values='' + local unpaired_line + unpaired_line='' while IFS= read -r line; do if [ -z "${line}" ]; then @@ -1077,7 +1098,7 @@ nvm_print_formatted_alias() { fi local ARROW ARROW='->' - if [ -z "${NVM_NO_COLORS}" ] && nvm_has_colors; then + if nvm_has_colors; then ARROW='\033[0;90m->\033[0m' if [ "_${DEFAULT}" = '_true' ]; then NEWLINE=" \033[${DEFAULT_COLOR}(default)\033[0m\n" @@ -1815,7 +1836,7 @@ nvm_print_versions() { DEFAULT_COLOR=$(nvm_get_colors 5) LTS_COLOR=$(nvm_get_colors 6) - if [ -z "${NVM_NO_COLORS-}" ] && nvm_has_colors; then + if nvm_has_colors; then NVM_HAS_COLORS=1 fi @@ -2420,7 +2441,7 @@ nvm_download_artifact() { nvm_err "Downloading ${TARBALL_URL}..." nvm_download -L -C - "${PROGRESS_BAR}" "${TARBALL_URL}" -o "${TARBALL}" || ( command rm -rf "${TARBALL}" "${tmpdir}" - nvm_err "Binary download from ${TARBALL_URL} failed, trying source." + nvm_err "download from ${TARBALL_URL} failed" return 4 ) @@ -2894,6 +2915,23 @@ nvm_is_natural_num() { esac } +nvm_write_nvmrc() { + local VERSION_STRING + VERSION_STRING=$(nvm_version "${1-$VERSION_STRING}") + if [ "$VERSION_STRING" = '∞' ] || [ "$VERSION_STRING" = 'N/A' ]; then + return 1 + fi + echo "$VERSION_STRING" | tee "$PWD"/.nvmrc > /dev/null || { + if [ "${NVM_SILENT:-0}" -ne 1 ]; then + nvm_err "Warning: Unable to write version number ($VERSION_STRING) to .nvmrc" + fi + return 3 + } + if [ "${NVM_SILENT:-0}" -ne 1 ]; then + nvm_echo "Wrote version number ($VERSION_STRING) to .nvmrc" + fi +} + # Check version dir permissions nvm_check_file_permissions() { nvm_is_zsh && setopt local_options nonomatch @@ -2999,6 +3037,7 @@ nvm() { nvm_echo ' --no-progress Disable the progress bar on any downloads' nvm_echo ' --alias= After installing, set the alias specified to the version specified. (same as: nvm alias )' nvm_echo ' --default After installing, set default alias to the version specified. (same as: nvm alias default )' + nvm_echo ' --save After installing, write the specified version to .nvmrc' 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.' @@ -3007,6 +3046,7 @@ nvm() { nvm_echo ' --silent Silences stdout/stderr output' nvm_echo ' --lts Uses automatic LTS (long-term support) alias `lts/*`, if available.' nvm_echo ' --lts= Uses automatic alias for provided LTS line, if available.' + nvm_echo ' --save Writes the specified version to .nvmrc.' nvm_echo ' nvm exec [] [] Run on . Uses .nvmrc if available and version is omitted.' nvm_echo ' The following optional arguments, if provided, must appear directly after `nvm exec`:' nvm_echo ' --silent Silences stdout/stderr output' @@ -3044,16 +3084,16 @@ nvm() { nvm_echo ' nvm cache clear Empty cache directory for nvm' nvm_echo ' nvm set-colors [] 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_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_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_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' @@ -3219,6 +3259,8 @@ nvm() { local ALIAS local NVM_UPGRADE_NPM NVM_UPGRADE_NPM=0 + local NVM_WRITE_TO_NVMRC + NVM_WRITE_TO_NVMRC=0 local PROVIDED_REINSTALL_PACKAGES_FROM local REINSTALL_PACKAGES_FROM @@ -3317,6 +3359,14 @@ nvm() { SKIP_DEFAULT_PACKAGES=true shift ;; + --save | -w) + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_err '--save and -w may only be provided once' + return 6 + fi + NVM_WRITE_TO_NVMRC=1 + shift + ;; *) break # stop parsing args ;; @@ -3465,6 +3515,11 @@ nvm() { nvm_ensure_default_set "${provided_version}" fi + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_write_nvmrc "${VERSION}" + EXIT_CODE=$? + fi + if [ $EXIT_CODE -ne 0 ] && [ -n "${ALIAS-}" ]; then nvm alias "${ALIAS}" "${provided_version}" EXIT_CODE=$? @@ -3516,9 +3571,13 @@ nvm() { EXIT_CODE=$? else EXIT_CODE=-1 + if [ $nosource -eq 1 ]; then + nvm_err "Binary download is not available for ${VERSION}" + EXIT_CODE=3 + fi fi - if [ $EXIT_CODE -ne 0 ]; then + if [ $EXIT_CODE -ne 0 ] && [ $nosource -ne 1 ]; then if [ -z "${NVM_MAKE_JOBS-}" ]; then nvm_get_make_jobs fi @@ -3533,26 +3592,29 @@ nvm() { fi fi - if [ $EXIT_CODE -eq 0 ] && nvm_use_if_needed "${VERSION}" && nvm_install_npm_if_needed "${VERSION}"; then - if [ -n "${LTS-}" ]; then - nvm_ensure_default_set "lts/${LTS}" + if [ $EXIT_CODE -eq 0 ]; then + if nvm_use_if_needed "${VERSION}" && nvm_install_npm_if_needed "${VERSION}"; then + if [ -n "${LTS-}" ]; then + nvm_ensure_default_set "lts/${LTS}" + else + nvm_ensure_default_set "${provided_version}" + fi + if [ "${NVM_UPGRADE_NPM}" = 1 ]; then + nvm install-latest-npm + EXIT_CODE=$? + fi + if [ $EXIT_CODE -eq 0 ] && [ -z "${SKIP_DEFAULT_PACKAGES-}" ]; then + nvm_install_default_packages + fi + if [ $EXIT_CODE -eq 0 ] && [ -n "${REINSTALL_PACKAGES_FROM-}" ] && [ "_${REINSTALL_PACKAGES_FROM}" != "_N/A" ]; then + nvm reinstall-packages "${REINSTALL_PACKAGES_FROM}" + EXIT_CODE=$? + fi else - nvm_ensure_default_set "${provided_version}" - fi - if [ "${NVM_UPGRADE_NPM}" = 1 ]; then - nvm install-latest-npm EXIT_CODE=$? fi - if [ $EXIT_CODE -eq 0 ] && [ -z "${SKIP_DEFAULT_PACKAGES-}" ]; then - nvm_install_default_packages - fi - if [ $EXIT_CODE -eq 0 ] && [ -n "${REINSTALL_PACKAGES_FROM-}" ] && [ "_${REINSTALL_PACKAGES_FROM}" != "_N/A" ]; then - nvm reinstall-packages "${REINSTALL_PACKAGES_FROM}" - EXIT_CODE=$? - fi - else - EXIT_CODE=$? fi + return $EXIT_CODE ;; "uninstall") @@ -3693,6 +3755,8 @@ nvm() { local NVM_LTS local IS_VERSION_FROM_NVMRC IS_VERSION_FROM_NVMRC=0 + local NVM_WRITE_TO_NVMRC + NVM_WRITE_TO_NVMRC=0 while [ $# -ne 0 ]; do case "$1" in @@ -3704,6 +3768,13 @@ nvm() { --) ;; --lts) NVM_LTS='*' ;; --lts=*) NVM_LTS="${1##--lts=}" ;; + --save | -w) + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_err '--save and -w may only be provided once' + return 6 + fi + NVM_WRITE_TO_NVMRC=1 + ;; --*) ;; *) if [ -n "${1-}" ]; then @@ -3737,6 +3808,10 @@ nvm() { return 127 fi + if [ $NVM_WRITE_TO_NVMRC -eq 1 ]; then + nvm_write_nvmrc "${VERSION}" + fi + if [ "_${VERSION}" = '_system' ]; then if nvm_has_system_node && nvm deactivate "${NVM_SILENT_ARG-}" >/dev/null 2>&1; then if [ "${NVM_SILENT:-0}" -ne 1 ]; then @@ -3752,7 +3827,7 @@ nvm() { nvm_err 'System version of node not found.' fi return 127 - elif [ "_${VERSION}" = "_∞" ]; then + elif [ "_${VERSION}" = '_∞' ]; then if [ "${NVM_SILENT:-0}" -ne 1 ]; then nvm_err "The alias \"${PROVIDED_VERSION}\" leads to an infinite loop. Aborting." fi @@ -4316,7 +4391,7 @@ nvm() { NVM_VERSION_ONLY=true NVM_LTS="${NVM_LTS-}" nvm_remote_version "${PATTERN:-node}" ;; "--version" | "-v") - nvm_echo '0.39.7' + nvm_echo '0.40.0' ;; "unload") nvm deactivate >/dev/null 2>&1 @@ -4357,11 +4432,12 @@ nvm() { 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_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_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_write_nvmrc \ >/dev/null 2>&1 unset NVM_RC_VERSION NVM_NODEJS_ORG_MIRROR NVM_IOJS_ORG_MIRROR NVM_DIR \ NVM_CD_FLAGS NVM_BIN NVM_INC NVM_MAKE_JOBS \ @@ -4387,37 +4463,23 @@ nvm() { } nvm_get_default_packages() { - local NVM_DEFAULT_PACKAGE_FILE="${NVM_DIR}/default-packages" + local NVM_DEFAULT_PACKAGE_FILE + NVM_DEFAULT_PACKAGE_FILE="${NVM_DIR}/default-packages" if [ -f "${NVM_DEFAULT_PACKAGE_FILE}" ]; then - local DEFAULT_PACKAGES - DEFAULT_PACKAGES='' - - # Read lines from $NVM_DIR/default-packages - local line - # ensure a trailing newline - WORK=$(mktemp -d) || exit $? - # shellcheck disable=SC2064 - trap "command rm -rf '$WORK'" EXIT - # shellcheck disable=SC1003 - sed -e '$a\' "${NVM_DEFAULT_PACKAGE_FILE}" > "${WORK}/default-packages" - while IFS=' ' read -r line; do - # Skip empty lines. - [ -n "${line-}" ] || continue - - # Skip comment lines that begin with `#`. - [ "$(nvm_echo "${line}" | command cut -c1)" != "#" ] || continue - - # Fail on lines that have multiple space-separated words - case $line in - *\ *) - nvm_err "Only one package per line is allowed in the ${NVM_DIR}/default-packages file. Please remove any lines with multiple space-separated values." - return 1 - ;; - esac - - DEFAULT_PACKAGES="${DEFAULT_PACKAGES}${line} " - done < "${WORK}/default-packages" - echo "${DEFAULT_PACKAGES}" | command xargs + command awk -v filename="${NVM_DEFAULT_PACKAGE_FILE}" ' + /^[[:space:]]*#/ { next } # Skip lines that begin with # + /^[[:space:]]*$/ { next } # Skip empty lines + /[[:space:]]/ && !/^[[:space:]]*#/ { + print "Only one package per line is allowed in `" filename "`. Please remove any lines with multiple space-separated values." > "/dev/stderr" + err = 1 + exit 1 + } + { + if (NR > 1 && !prev_space) printf " " + printf "%s", $0 + prev_space = 0 + } + ' "${NVM_DEFAULT_PACKAGE_FILE}" fi } @@ -4494,31 +4556,41 @@ nvm_supports_xz() { nvm_auto() { local NVM_MODE NVM_MODE="${1-}" - local VERSION - local NVM_CURRENT - if [ "_${NVM_MODE}" = '_install' ]; then - VERSION="$(nvm_alias default 2>/dev/null || nvm_echo)" - if [ -n "${VERSION}" ]; then - nvm install "${VERSION}" >/dev/null - elif nvm_rc_version >/dev/null 2>&1; then - nvm install >/dev/null - fi - elif [ "_$NVM_MODE" = '_use' ]; then - NVM_CURRENT="$(nvm_ls_current)" - if [ "_${NVM_CURRENT}" = '_none' ] || [ "_${NVM_CURRENT}" = '_system' ]; then - VERSION="$(nvm_resolve_local_alias default 2>/dev/null || nvm_echo)" - if [ -n "${VERSION}" ]; then - nvm use --silent "${VERSION}" >/dev/null - elif nvm_rc_version >/dev/null 2>&1; then - nvm use --silent >/dev/null + + case "${NVM_MODE}" in + none) return 0 ;; + use | install) + local VERSION + local NVM_CURRENT + NVM_CURRENT="$(nvm_ls_current)" + if [ "_${NVM_CURRENT}" = '_none' ] || [ "_${NVM_CURRENT}" = '_system' ]; then + VERSION="$(nvm_resolve_local_alias default 2>/dev/null || nvm_echo)" + if [ -n "${VERSION}" ]; then + if [ "_${VERSION}" != '_N/A' ] && nvm_is_valid_version "${VERSION}"; then + if [ "_${NVM_MODE}" = '_install' ]; then + nvm install "${VERSION}" >/dev/null + else + nvm use --silent "${VERSION}" >/dev/null + fi + else + return 0 + fi + elif nvm_rc_version >/dev/null 2>&1; then + if [ "_${NVM_MODE}" = '_install' ]; then + nvm install >/dev/null + else + nvm use --silent >/dev/null + fi + fi + else + nvm use --silent "${NVM_CURRENT}" >/dev/null fi - else - nvm use --silent "${NVM_CURRENT}" >/dev/null - fi - elif [ "_${NVM_MODE}" != '_none' ]; then - nvm_err 'Invalid auto mode supplied.' - return 1 - fi + ;; + *) + nvm_err 'Invalid auto mode supplied.' + return 1 + ;; + esac } nvm_process_parameters() { diff --git a/package.json b/package.json index 0968873..605ba8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nvm", - "version": "0.39.7", + "version": "0.40.0", "description": "Node Version Manager - Simple bash script to manage multiple active node.js versions", "directories": { "test": "test" @@ -45,7 +45,7 @@ "eclint": "^2.8.1", "markdown-link-check": "^3.12.2", "replace": "^1.2.2", - "semver": "^7.6.2", + "semver": "^7.6.3", "urchin": "^0.0.5" } } diff --git a/test/fast/Running 'nvm unload' should unset all function and variables b/test/fast/Running 'nvm unload' should unset all function and variables index e7fb706..abb5ca4 100755 --- a/test/fast/Running 'nvm unload' should unset all function and variables +++ b/test/fast/Running 'nvm unload' should unset all function and variables @@ -9,7 +9,7 @@ cleanup () { rm -f "${BEFORE}" "${AFTER}"; } die () { echo "$@" ; cleanup ; exit 1; } typeset -f | awk '/ \(\) $/ && !/^main / {print $1}' > "${BEFORE}" -env | grep -v PATH= | grep -v IFS= | grep -v NVM_ | sort >> "${BEFORE}" +env | grep -v PATH= | grep -v IFS= | grep -v NVM_ | grep -v TRAVIS_ | sort >> "${BEFORE}" set +e # TODO: fix \. ../../nvm.sh @@ -20,11 +20,11 @@ type nvm > /dev/null 2>&1 || die "nvm not loaded" nvm unload typeset -f | awk '/ \(\) $/ && !/^main / {print $1}' > "${AFTER}" -env | grep -v PATH= | grep -v IFS= | sort >> "${AFTER}" +env | grep -v PATH= | grep -v IFS= | grep -v TRAVIS_ | sort >> "${AFTER}" ! type nvm > /dev/null 2>&1 || die "nvm not unloaded" DIFF="$(diff "${BEFORE}" "${AFTER}" ||:)" -[ -z "${DIFF}" ] || die "function pollution found: ${DIFF}" +[ -z "${DIFF}" ] || die "function pollution found: >${DIFF}<" cleanup diff --git a/test/fast/Unit tests/Running 'nvm install --save' works as expected' b/test/fast/Unit tests/Running 'nvm install --save' works as expected' new file mode 100644 index 0000000..7f6c565 --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm install --save' works as expected' @@ -0,0 +1,43 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +cleanup () { + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* .nvmrc + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +nvm install --save "$TEST_VERSION" || die "\`nvm install --save $TEST_VERSION\` failed" +OUTPUT="$(cat .nvmrc)" + +nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm install --save $TEST_VERSION\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" + +cleanup diff --git a/test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir b/test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir new file mode 100644 index 0000000..ef8a25a --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm use --save' works with a .nvmrc in the parent dir @@ -0,0 +1,57 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi +if [ -f ../.nvmrc ]; then mv ../.nvmrc ../.nvmrc.orig; fi + +del_nvmrc () { + rm -f .nvmrc ../.nvmrc +} + +cleanup () { + del_nvmrc + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + if [ -f ../.nvmrc.orig ]; then mv ../.nvmrc.orig ../.nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +del_nvmrc +make_fake_node "$TEST_VERSION" + +(cd .. +nvm use --save "$TEST_VERSION" || die "\`nvm use --save $TEST_VERSION\` failed in the parent dir") +nvm use --save || die "\`nvm use --save\` failed" + +[ -f ../.nvmrc ] && [ -f .nvmrc ] || die "expected two .nvmrc files to be generated" + +OUTPUT=$(cat .nvmrc) +EXPECTED_OUTPUT="$(cat ../.nvmrc)" + +[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] \ + || die "invalid \`nvm use --save \` output: expected '$EXPECTED_OUTPUT'; got '$OUTPUT'" + +cleanup diff --git a/test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything b/test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything new file mode 100644 index 0000000..0df4251 --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm use --silent --save' doesn't output anything @@ -0,0 +1,43 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +cleanup () { + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* .nvmrc + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +OUTPUT=$(nvm use --save --silent "$TEST_VERSION" || die "\`nvm use --save --silent $TEST_VERSION\` failed") +EXPECTED_OUTPUT="" + +[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] \ + || die "\`nvm use --save --silent $TEST_VERSION\` output was not silenced to '$EXPECTED_OUTPUT'; got '$OUTPUT'" + +cleanup diff --git a/test/fast/Unit tests/Running 'nvm use -w' works as expected' b/test/fast/Unit tests/Running 'nvm use -w' works as expected' new file mode 100644 index 0000000..afa5835 --- /dev/null +++ b/test/fast/Unit tests/Running 'nvm use -w' works as expected' @@ -0,0 +1,62 @@ +#!/bin/sh +\. ../../../nvm.sh + +set -e + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +TEST_VERSION="v0.2.4" + +cleanup () { + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* .nvmrc + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +nvm deactivate 2>/dev/null || die 'unable to deactivate' + +\. ../../common.sh + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +# 1. install + +nvm install -w "$TEST_VERSION" || die "\`nvm install -w $TEST_VERSION\` failed" +OUTPUT="$(cat .nvmrc)" + +nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm install -w $TEST_VERSION\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" + +# + +unset OUTPUT + +# 2. use + +nvm use -w "$TEST_VERSION" || die "\`nvm use -w $TEST_VERSION\` failed" +OUTPUT="$(cat .nvmrc)" + +nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm use -w $TEST_VERSION\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" + +# + +cleanup diff --git a/test/fast/Unit tests/nvm install -b b/test/fast/Unit tests/nvm install -b new file mode 100755 index 0000000..20b4b76 --- /dev/null +++ b/test/fast/Unit tests/nvm install -b @@ -0,0 +1,20 @@ +#!/bin/sh + +die () { echo "$@" ; exit 1; } + +\. ../../../nvm.sh + +nvm_install_source() { + exit 42 +} + +VERSION="0.7.0" + +EXIT_CODE=$(nvm install -b "${VERSION}" ; echo $?) + +[ $EXIT_CODE -eq 3 ] || die "Expected exit code 3, got ${EXIT_CODE}" + +ACTUAL="$(nvm install -b "${VERSION}" 2>&1)" +EXPECTED="Binary download is not available for v${VERSION}" + +[ "${ACTUAL}" = "${EXPECTED}" ] || die "Expected >${EXPECTED}<, got >${ACTUAL}<" diff --git a/test/fast/Unit tests/nvm ls-remote b/test/fast/Unit tests/nvm ls-remote index 683fe92..bb1ac94 100755 --- a/test/fast/Unit tests/nvm ls-remote +++ b/test/fast/Unit tests/nvm ls-remote @@ -6,14 +6,14 @@ die () { echo "$@" ; cleanup ; exit 1; } cleanup() { unset -f nvm_download nvm_ls_remote nvm_ls_remote_iojs - if [ -n TEMP_NVM_COLORS ]; then + if [ -n "${TEMP_NVM_COLORS-}" ]; then export NVM_COLORS=TEMP_NVM_COLORS fi unset TEMP_NVM_COLORS } \. ../../../nvm.sh -if [ -n ${NVM_COLORS} ]; then +if [ -n "${NVM_COLORS-}" ]; then export TEMP_NVM_COLORS=NVM_COLORS unset NVM_COLORS fi diff --git a/test/fast/Unit tests/nvm_download b/test/fast/Unit tests/nvm_download index 3afd76c..19e2dd9 100644 --- a/test/fast/Unit tests/nvm_download +++ b/test/fast/Unit tests/nvm_download @@ -1,7 +1,8 @@ #!/bin/sh cleanup () { - unset -f die cleanup + unset -f die cleanup NVM_AUTH_HEADER + docker stop httpbin && docker rm httpbin } die () { echo "$@" ; cleanup ; exit 1; } @@ -15,4 +16,13 @@ nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh" >/de # nvm_download should fail to download wrong_install.sh ! nvm_download "https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/wrong_install.sh" >/dev/null || die "nvm_download should fail to download no existing file" +# nvm_download should pass when calling with auth header +docker pull kennethreitz/httpbin && docker run --shell=bash -d --name httpbin -p 80:80 kennethreitz/httpbin +sleep 1 # wait for httpbin to start +NVM_AUTH_HEADER="Bearer test-token" nvm_download "http://127.0.0.1/bearer" > /dev/null || die 'nvm_download with auth header should send correctly' + +# nvm_download should fail when calling without auth header +nvm_download "http://127.0.0.1/bearer" > /dev/null && die 'nvm_download with no auth header should not send the header and should fail' +docker stop httpbin && docker rm httpbin + cleanup diff --git a/test/fast/Unit tests/nvm_get_default_packages b/test/fast/Unit tests/nvm_get_default_packages index 0529137..c57ace9 100755 --- a/test/fast/Unit tests/nvm_get_default_packages +++ b/test/fast/Unit tests/nvm_get_default_packages @@ -74,7 +74,7 @@ rimraf EOF DEFAULT_PKGS="$(nvm_get_default_packages 2>&1 >/dev/null)" -EXPECTED_PKGS="Only one package per line is allowed in the $FILE file. Please remove any lines with multiple space-separated values." +EXPECTED_PKGS="Only one package per line is allowed in \`${FILE}\`. Please remove any lines with multiple space-separated values." [ "${DEFAULT_PKGS}" = "${EXPECTED_PKGS}" ] || die "4: expected default packages >${EXPECTED_PKGS}<; got >${DEFAULT_PKGS}<" cleanup diff --git a/test/fast/Unit tests/nvm_write_nvmrc b/test/fast/Unit tests/nvm_write_nvmrc new file mode 100644 index 0000000..9e0d734 --- /dev/null +++ b/test/fast/Unit tests/nvm_write_nvmrc @@ -0,0 +1,86 @@ +#!/bin/sh +\. ../../../nvm.sh +\. ../../common.sh + +set -e + +TEST_VERSION="v0.2.4" + +if [ -f .nvmrc ]; then mv .nvmrc .nvmrc.orig; fi + +del_nvmrc () { + rm -f .nvmrc +} + +del_alias () { + nvm unalias test >/dev/null 2>&1 +} + +cleanup () { + del_nvmrc + del_alias + nvm cache clear + nvm deactivate + nvm unalias default + rm -rf ${NVM_DIR}/v* + if [ -f .nvmrc.orig ]; then mv .nvmrc.orig .nvmrc; fi + unset -f nvm_ls_remote nvm_ls_remote_iojs +} + +die () { + echo "$@" + cleanup + exit 1 +} + +REMOTE="$PWD/mocks/nvm_ls_remote.txt" +nvm_ls_remote() { + cat "$REMOTE" +} +REMOTE_IOJS="$PWD/mocks/nvm_ls_remote_iojs.txt" +nvm_ls_remote_iojs() { + cat "$REMOTE_IOJS" +} + +make_fake_node "$TEST_VERSION" + +test_version () { + del_nvmrc + VERSION_STRING=${1-} + make_fake_node "$VERSION_STRING" + + nvm_write_nvmrc $VERSION_STRING || die "\`nvm_write_nvmrc ${VERSION_STRING}\` failed" + OUTPUT="$(cat .nvmrc)" + + nvm_is_valid_version "$(cat .nvmrc)" \ + || die "\`nvm install --save ${VERSION_STRING}\`+ \`cat .nvmrc\` outputted invalid version: got '${OUTPUT}'" +} + +# 1. + +test_version "$TEST_VERSION" || die + +# 2. with an alias +del_alias +nvm alias test "$TEST_VERSION" +test_version test || die + +# 3. fails with invalid permissions +del_nvmrc +touch .nvmrc +chmod 0 .nvmrc +nvm_write_nvmrc $TEST_VERSION 2>/dev/null && die "\`nvm_write_nvmrc $TEST_VERSION\` did not fail with invalid permissions" +del_nvmrc + +# 4. respects NVM_SILENT=1 +export NVM_SILENT=1 +[ "$(nvm_write_nvmrc $TEST_VERSION)" = "" ] || die "\`nvm_write_nvmrc $TEST_VERSION\` was not silenced by NVM_SILENT=1" +unset NVM_SILENT + +# 5. fails with an invalid version number +TEST_VERSION="not_a_node_version" +nvm_write_nvmrc $TEST_VERSION 2>/dev/null && die "\`nvm_write_nvmrc $TEST_VERSION\` did not fail" + +# + +cleanup