diff options
author | isaacs <i@izs.me> | 2021-02-26 02:38:28 +0300 |
---|---|---|
committer | Ruy Adorno <ruyadorno@hotmail.com> | 2021-03-05 00:07:14 +0300 |
commit | e69be2ac5c35e985732e2baa00b70d39332e4b9f (patch) | |
tree | 302f7bf48708fafc31ff0ced070609c4e183474c /bin | |
parent | 4a5dd3a5a200b3f4f7b47168497d8e03dca3a2ca (diff) |
Get correct npm prefix on all Windows unix shellsisaacs/fix-windows-shell-bins
1. Set the shebang to /usr/bin/env bash instead of /bin/sh (which might
be dash or some other shell)
2. Use Unix-style line endings, not Windows-style (Cygwin accepts
either, but mingw bash sometimes objects, and WSL bash always does)
3. Test against paths using wslpath if available, but still pass win32
paths to node.exe, since it is a Windows binary that only knows how
to handle Windows paths.
This makes npm as installed by the Node.js Windows MSI installer behave
properly under WSL, Cygwin, MINGW Git Bash, and the internal MINGW Git
Bash when posix CLI utilities are exposed to the cmd.exe shell.
The test is not quite as comprehensive as I'd like. It runs on the
various Windows bash implementations if they are found in their expected
locations, skipping any that are not installed. Short of shipping
mingw, cygwin, and wsl as test fixtures, I'm not sure how we could do
much better, however. At least, we can use this test to assist debug
and catch issues on Windows machines (ours or users who report
problems).
PR-URL: https://github.com/npm/cli/pull/2789
Credit: @isaacs
Close: #2789
Reviewed-by: @nlf
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/npm | 45 | ||||
-rwxr-xr-x | bin/npx | 48 |
2 files changed, 53 insertions, 40 deletions
@@ -1,10 +1,10 @@ -#!/bin/sh +#!/usr/bin/env bash (set -o igncr) 2>/dev/null && set -o igncr; # cygwin encoding fix basedir=`dirname "$0"` case `uname` in - *CYGWIN*) basedir=`cygpath -w "$basedir"`;; + *CYGWIN*) basedir=`cygpath -w "$basedir"`;; esac NODE_EXE="$basedir/node.exe" @@ -15,23 +15,30 @@ if ! [ -x "$NODE_EXE" ]; then NODE_EXE=node fi -NPM_CLI_JS="$basedir/node_modules/npm/bin/npm-cli.js" +# this path is passed to node.exe, so it needs to match whatever +# kind of paths Node.js thinks it's using, typically win32 paths. +CLI_BASEDIR="$("$NODE_EXE" -p 'require("path").dirname(process.execPath)')" +NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js" -case `uname` in - *MINGW*) - NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` - NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" - if [ -f "$NPM_PREFIX_NPM_CLI_JS" ]; then - NPM_CLI_JS="$NPM_PREFIX_NPM_CLI_JS" - fi - ;; - *CYGWIN*) - NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` - NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" - if [ -f "$NPM_PREFIX_NPM_CLI_JS" ]; then - NPM_CLI_JS="$NPM_PREFIX_NPM_CLI_JS" - fi - ;; -esac +NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` +if [ $? -ne 0 ]; then + # if this didn't work, then everything else below will fail + echo "Could not determine Node.js install directory" >&2 + exit 1 +fi +NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" + +# a path that will fail -f test on any posix bash +NPM_WSL_PATH="/.." + +# WSL can run Windows binaries, so we have to give it the win32 path +# however, WSL bash tests against posix paths, so we need to construct that +# to know if npm is installed globally. +if [ `uname` = 'Linux' ] && type wslpath &>/dev/null ; then + NPM_WSL_PATH=`wslpath "$NPM_PREFIX_NPM_CLI_JS"` +fi +if [ -f "$NPM_PREFIX_NPM_CLI_JS" ] || [ -f "$NPM_WSL_PATH" ]; then + NPM_CLI_JS="$NPM_PREFIX_NPM_CLI_JS" +fi "$NODE_EXE" "$NPM_CLI_JS" "$@" @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # This is used by the Node.js installer, which expects the cygwin/mingw # shell script to already be present in the npm dependency folder. @@ -8,7 +8,7 @@ basedir=`dirname "$0"` case `uname` in - *CYGWIN*) basedir=`cygpath -w "$basedir"`;; + *CYGWIN*) basedir=`cygpath -w "$basedir"`;; esac NODE_EXE="$basedir/node.exe" @@ -16,24 +16,30 @@ if ! [ -x "$NODE_EXE" ]; then NODE_EXE=node fi -NPM_CLI_JS="$basedir/node_modules/npm/bin/npm-cli.js" -NPX_CLI_JS="$basedir/node_modules/npm/bin/npx-cli.js" - -case `uname` in - *MINGW*) - NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` - NPM_PREFIX_NPX_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npx-cli.js" - if [ -f "$NPM_PREFIX_NPX_CLI_JS" ]; then - NPX_CLI_JS="$NPM_PREFIX_NPX_CLI_JS" - fi - ;; - *CYGWIN*) - NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` - NPM_PREFIX_NPX_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npx-cli.js" - if [ -f "$NPM_PREFIX_NPX_CLI_JS" ]; then - NPX_CLI_JS="$NPM_PREFIX_NPX_CLI_JS" - fi - ;; -esac +# these paths are passed to node.exe, so they need to match whatever +# kind of paths Node.js thinks it's using, typically win32 paths. +CLI_BASEDIR="$("$NODE_EXE" -p 'require("path").dirname(process.execPath)')" +if [ $? -ne 0 ]; then + # if this didn't work, then everything else below will fail + echo "Could not determine Node.js install directory" >&2 + exit 1 +fi +NPM_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npm-cli.js" +NPX_CLI_JS="$CLI_BASEDIR/node_modules/npm/bin/npx-cli.js" +NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` +NPM_PREFIX_NPX_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npx-cli.js" + +# a path that will fail -f test on any posix bash +NPX_WSL_PATH="/.." + +# WSL can run Windows binaries, so we have to give it the win32 path +# however, WSL bash tests against posix paths, so we need to construct that +# to know if npm is installed globally. +if [ `uname` = 'Linux' ] && type wslpath &>/dev/null ; then + NPX_WSL_PATH=`wslpath "$NPM_PREFIX_NPX_CLI_JS"` +fi +if [ -f "$NPM_PREFIX_NPX_CLI_JS" ] || [ -f "$NPX_WSL_PATH" ]; then + NPX_CLI_JS="$NPM_PREFIX_NPX_CLI_JS" +fi "$NODE_EXE" "$NPX_CLI_JS" "$@" |