Skip to content

Commit

Permalink
Make it work on Windows with WSL, MSYS, Cygwin
Browse files Browse the repository at this point in the history
  • Loading branch information
nmarghetti committed Dec 28, 2020
1 parent 10399ed commit 7f15005
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 36 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/windows-npm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: 'Tests on Windows: `nvm install`'

on: [pull_request, push]

jobs:
node:
name: 'MSYS fail prefix nvm install'
runs-on: windows-latest
steps:
- name: Retrieve nvm
shell: bash
run: |
mkdir vp "$HOME/.nvm"
curl -sSLo "$HOME/.nvm/nvm.sh" "https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/${GITHUB_SHA}/nvm.sh"
source "$HOME/.nvm/nvm.sh"
! nvm install --lts
nodes:
name: 'MSYS nvm install'
runs-on: windows-latest
strategy:
matrix:
npm-node-version:
- '--lts'
- '--default 12'
- '--no-progress 10'

steps:
- name: Retrieve nvm
shell: bash
run: |
mkdir vp "$HOME/.nvm"
curl -sSLo "$HOME/.nvm/nvm.sh" "https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/${GITHUB_SHA}/nvm.sh"
source "$HOME/.nvm/nvm.sh"
unset npm_config_prefix
nvm install ${{ matrix.npm-node-version }}
wsl_nodes:
name: 'WSL nvm install'
runs-on: windows-latest
strategy:
matrix:
wsl-distrib:
- Debian
- Alpine
- Ubuntu-18.04
npm-node-version:
- '--lts'
- '11'
steps:
- uses: Vampire/setup-wsl@v1
with:
distribution: ${{ matrix.wsl-distrib }}
additional-packages: bash curl ca-certificates
- name: Retrieve nvm on WSL
shell: wsl-bash {0}
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SHA: github.sha
run: |
mkdir -p "$HOME/.nvm"
curl -sSLo "$HOME/.nvm/nvm.sh" "https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/nvm.sh"
source "$HOME/.nvm/nvm.sh"
nvm install ${{ matrix.npm-node-version }}
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,17 @@ which should output `nvm` if the installation was successful. Please note that `

If you're running a system without prepackaged binary available, which means you're going to install nodejs or io.js from its source code, you need to make sure your system has a C++ compiler. For OS X, Xcode will work, for Debian/Ubuntu based GNU/Linux, the `build-essential` and `libssl-dev` packages work.

**Note:** `nvm` does not support Windows (see [#284](https://github.com/nvm-sh/nvm/issues/284)), but may work in WSL (Windows Subsystem for Linux) depending on the version of WSL. For Windows, two alternatives exist, which are neither supported nor developed by us:
**Note:** `nvm` does not support Windows (see [#284](https://github.com/nvm-sh/nvm/issues/284)), but may work in WSL (Windows Subsystem for Linux) depending on the version of WSL. It may work also with GitBash or Cygwin. For Windows, two alternatives exist, which are neither supported nor developed by us:

- [nvm-windows](https://github.com/coreybutler/nvm-windows)
- [nodist](https://github.com/marcelklehr/nodist)

**Note:** `nvm` may work with [GitBash](https://gitforwindows.org/) if installed with script method (the git repository contains filenames with characters not supported on Windows):

```sh
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | METHOD=script bash
```

**Note:** `nvm` does not support [Fish] either (see [#303](https://github.com/nvm-sh/nvm/issues/303)). Alternatives exist, which are neither supported nor developed by us:

- [bass](https://github.com/edc/bass) allows you to use utilities written for Bash in fish shell
Expand Down
151 changes: 118 additions & 33 deletions nvm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,12 @@ nvm_has_system_iojs() {
}

nvm_is_version_installed() {
[ -n "${1-}" ] && [ -x "$(nvm_version_path "$1" 2>/dev/null)"/bin/node ]
local NVM_OS
NVM_OS="$(nvm_get_os)"
local NODE
NODE='node'
[ "_${NVM_OS}" = "_win" ] && NODE='node.exe'
[ -n "${1-}" ] && [ -x "$(nvm_version_path "$1" 2>/dev/null)"/bin/"${NODE}" ]
}

nvm_print_npm_version() {
Expand Down Expand Up @@ -326,10 +331,14 @@ nvm_tree_contains_path() {
return 2
fi

local previous_pathdir
previous_pathdir="${node_path}"
local pathdir
pathdir=$(dirname "${node_path}")
while [ "${pathdir}" != "" ] && [ "${pathdir}" != "." ] && [ "${pathdir}" != "/" ] && [ "${pathdir}" != "${tree}" ]; do
pathdir=$(dirname "${pathdir}")
pathdir=$(dirname "${previous_pathdir}")
while [ "${pathdir}" != "" ] && [ "${pathdir}" != "." ] && [ "${pathdir}" != "/" ] &&
[ "${pathdir}" != "${tree}" ] && [ "${pathdir}" != "${previous_pathdir}" ]; do
previous_pathdir="${pathdir}"
pathdir=$(dirname "${previous_pathdir}")
done
[ "${pathdir}" = "${tree}" ]
}
Expand Down Expand Up @@ -1559,7 +1568,7 @@ nvm_get_checksum() {
SHASUMS_URL="${MIRROR}/${3}/SHASUMS.txt"
fi

nvm_download -L -s "${SHASUMS_URL}" -o - | command awk "{ if (\"${4}.tar.${5}\" == \$2) print \$1}"
nvm_download -L -s "${SHASUMS_URL}" -o - | command awk "{ if (\"${4}.${5}\" == \$2) print \$1}"
}

nvm_print_versions() {
Expand Down Expand Up @@ -1761,6 +1770,7 @@ nvm_get_os() {
SunOS\ *) NVM_OS=sunos ;;
FreeBSD\ *) NVM_OS=freebsd ;;
AIX\ *) NVM_OS=aix ;;
CYGWIN* | MSYS* | MINGW*) NVM_OS=win ;;
esac
nvm_echo "${NVM_OS-}"
}
Expand Down Expand Up @@ -1882,14 +1892,11 @@ nvm_install_binary() {
local VERSION
VERSION="$(nvm_strip_iojs_prefix "${PREFIXED_VERSION}")"

if [ -z "$(nvm_get_os)" ]; then
return 2
fi
local NVM_OS
NVM_OS="$(nvm_get_os)"

local tar_compression_flag
tar_compression_flag='z'
if nvm_supports_xz "${VERSION}"; then
tar_compression_flag='J'
if [ -z "${NVM_OS}" ]; then
return 2
fi

local TARBALL
Expand All @@ -1914,21 +1921,52 @@ nvm_install_binary() {
if [ -f "${TARBALL}" ]; then
TMPDIR="$(dirname "${TARBALL}")/files"
fi
local tar
tar='tar'
if [ "${NVM_OS}" = 'aix' ]; then
tar='gtar'

local EXTRACT_SUCCESS
EXTRACT_SUCCESS=0

# For Windows system (GitBash with MSYS, Cygwin)
if [ "${NVM_OS}" = 'win' ]; then
if (
[ -n "${TMPDIR-}" ] && \
command mkdir -p "${TMPDIR}" && \
command unzip -q "${TARBALL}" -d "${TMPDIR}" && \
VERSION_PATH="$(nvm_version_path "${PREFIXED_VERSION}")/bin" && \
command mkdir -p "${VERSION_PATH}" && \
command mv "${TMPDIR}/"*/* "${VERSION_PATH}" && \
command rm -rf "${TMPDIR}"
); then
EXTRACT_SUCCESS=1
fi
# For non Windows system (including WSL running on Windows)
else
local tar_compression_flag
tar_compression_flag='z'
if nvm_supports_xz "${VERSION}"; then
tar_compression_flag='J'
fi

local tar
if [ "${NVM_OS}" = 'aix' ]; then
tar='gtar'
else
tar='tar'
fi

if (
[ -n "${TMPDIR-}" ] && \
command mkdir -p "${TMPDIR}" && \
command "${tar}" -x${tar_compression_flag}f "${TARBALL}" -C "${TMPDIR}" --strip-components 1 && \
VERSION_PATH="$(nvm_version_path "${PREFIXED_VERSION}")" && \
command mkdir -p "${VERSION_PATH}" && \
command mv "${TMPDIR}/"* "${VERSION_PATH}" && \
command rm -rf "${TMPDIR}"
); then
EXTRACT_SUCCESS=1
fi
fi
if (
[ -n "${TMPDIR-}" ] && \
command mkdir -p "${TMPDIR}" && \
command "${tar}" -x${tar_compression_flag}f "${TARBALL}" -C "${TMPDIR}" --strip-components 1 && \
VERSION_PATH="$(nvm_version_path "${PREFIXED_VERSION}")" && \
command mkdir -p "${VERSION_PATH}" && \
command mv "${TMPDIR}/"* "${VERSION_PATH}" && \
command rm -rf "${TMPDIR}"
); then

if [ "$EXTRACT_SUCCESS" -eq 1 ]; then
if [ -n "${ALIAS-}" ]; then
nvm alias "${ALIAS}" "${provided_version}"
fi
Expand Down Expand Up @@ -2028,10 +2066,15 @@ nvm_download_artifact() {
local SLUG
SLUG="$(nvm_get_download_slug "${FLAVOR}" "${KIND}" "${VERSION}")"

local NVM_OS
NVM_OS="$(nvm_get_os)"

local COMPRESSION
COMPRESSION='gz'
if nvm_supports_xz "${VERSION}"; then
COMPRESSION='xz'
COMPRESSION='tar.gz'
if [ "${NVM_OS}" = "win" ]; then
COMPRESSION='zip'
elif nvm_supports_xz "${VERSION}"; then
COMPRESSION='tar.xz'
fi

local CHECKSUM
Expand All @@ -2049,13 +2092,13 @@ nvm_download_artifact() {
)

local TARBALL
TARBALL="${tmpdir}/${SLUG}.tar.${COMPRESSION}"
TARBALL="${tmpdir}/${SLUG}.${COMPRESSION}"
local TARBALL_URL
if nvm_version_greater_than_or_equal_to "${VERSION}" 0.1.14; then
TARBALL_URL="${MIRROR}/${VERSION}/${SLUG}.tar.${COMPRESSION}"
TARBALL_URL="${MIRROR}/${VERSION}/${SLUG}.${COMPRESSION}"
else
# node <= 0.1.13 does not have a directory
TARBALL_URL="${MIRROR}/${SLUG}.tar.${COMPRESSION}"
TARBALL_URL="${MIRROR}/${SLUG}.${COMPRESSION}"
fi

if [ -r "${TARBALL}" ]; then
Expand Down Expand Up @@ -2317,6 +2360,36 @@ nvm_npmrc_bad_news_bears() {
return 1
}

# args: path to check and transform if needed
nvm_ensure_posix_path() {
[ -z "$1" ] && nvm_err "Need the location as first parameter" && return 1
local location
location="$1"

# If already posix path, just return it
[ "$(printf '%s' "$location" | command cut -b 1)" = "/" ] && nvm_echo "$location" && return 0

local letter
letter=$(printf '%s' "$location" | command cut -b 1 | command tr '[:upper:]' '[:lower:]')
local letter_upper
letter_upper=$(printf '%s' "$letter" | command tr '[:lower:]' '[:upper:]')
local letter_prefix
[ -d '/mnt/' ] && letter_prefix='/mnt'
# prefix like /mnt/c or /c
if [ -d "$letter_prefix/$letter" ]; then
letter_prefix="$letter_prefix/$letter"
# prefix like /mnt/C or /C
elif [ -d "$letter_prefix/$letter_upper" ]; then
letter_prefix="$letter_prefix/$letter_upper"
else
nvm_err "Unable to convert the path to posix"
return 1
fi
# Remove Windows prefix (eg. C:) and replace \ by /
location=$(printf '%s' "$location" | command cut -b 3- | command sed 's#\\#/#g')
nvm_echo "${letter_prefix}${location}"
}

nvm_die_on_prefix() {
local NVM_DELETE_PREFIX
NVM_DELETE_PREFIX="${1-}"
Expand Down Expand Up @@ -2346,6 +2419,9 @@ nvm_die_on_prefix() {
return 3
fi

local NVM_OS
NVM_OS="$(nvm_get_os)"

# npm normalizes NPM_CONFIG_-prefixed env vars
# https://github.com/npm/npmconf/blob/22827e4038d6eebaafeb5c13ed2b92cf97b8fb82/npmconf.js#L331-L348
# https://github.com/npm/npm/blob/5e426a78ca02d0044f8dd26e0c5f881217081cbd/lib/config/core.js#L343-L359
Expand All @@ -2357,6 +2433,9 @@ nvm_die_on_prefix() {
if [ -n "${NVM_NPM_CONFIG_PREFIX_ENV-}" ]; then
local NVM_CONFIG_VALUE
eval "NVM_CONFIG_VALUE=\"\$${NVM_NPM_CONFIG_PREFIX_ENV}\""
if [ -n "$NVM_CONFIG_VALUE" ] && [ "_${NVM_OS}" = "_win" ]; then
NVM_CONFIG_VALUE="$(nvm_ensure_posix_path "$NVM_CONFIG_VALUE")"
fi
if [ -n "${NVM_CONFIG_VALUE-}" ] && ! nvm_tree_contains_path "${NVM_DIR}" "${NVM_CONFIG_VALUE}"; then
nvm deactivate >/dev/null 2>&1
nvm_err "nvm is not compatible with the \"${NVM_NPM_CONFIG_PREFIX_ENV}\" environment variable: currently set to \"${NVM_CONFIG_VALUE}\""
Expand Down Expand Up @@ -3130,8 +3209,13 @@ nvm() {
nvm_get_make_jobs
fi

NVM_NO_PROGRESS="${NVM_NO_PROGRESS:-${noprogress}}" nvm_install_source "${FLAVOR}" std "${VERSION}" "${NVM_MAKE_JOBS}" "${ADDITIONAL_PARAMETERS}"
EXIT_CODE=$?
if [ "_${NVM_OS}" = "_win" ]; then
nvm_err "Unable to install from source for Windows"
EXIT_CODE=1
else
NVM_NO_PROGRESS="${NVM_NO_PROGRESS:-${noprogress}}" nvm_install_source "${FLAVOR}" std "${VERSION}" "${NVM_MAKE_JOBS}" "${ADDITIONAL_PARAMETERS}"
EXIT_CODE=$?
fi
fi

fi
Expand Down Expand Up @@ -3944,6 +4028,7 @@ nvm() {
nvm_npmrc_bad_news_bears \
nvm_get_colors nvm_set_colors nvm_print_color_code nvm_format_help_message_colors \
nvm_echo_with_colors nvm_err_with_colors \
nvm_ensure_posix_path \
>/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 \
Expand Down
4 changes: 2 additions & 2 deletions test/fast/Unit tests/nvm_get_checksum
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ nvm_download() {
nvm_get_checksum_alg() {
echo 'sha-256'
}
OUTPUT="$(nvm_get_checksum node std foo bar baz)"
OUTPUT="$(nvm_get_checksum node std foo bar tar.baz)"
EXPECTED_OUTPUT="mirror-node-std/foo/SHASUMS256.txt"
[ "${OUTPUT}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${OUTPUT}<"

nvm_get_checksum_alg() {
echo 'sha-1'
}
OUTPUT="$(nvm_get_checksum iojs std foo bar baz)"
OUTPUT="$(nvm_get_checksum iojs std foo bar tar.baz)"
EXPECTED_OUTPUT="mirror-iojs-std/foo/SHASUMS.txt"
[ "${OUTPUT}" = "${EXPECTED_OUTPUT}" ] || die "expected >${EXPECTED_OUTPUT}<, got >${OUTPUT}<"

Expand Down

0 comments on commit 7f15005

Please sign in to comment.