diff --git a/src/index.ts b/src/index.ts index 7886f87..92e2a59 100644 --- a/src/index.ts +++ b/src/index.ts @@ -446,18 +446,9 @@ function generateShShim (src: string, to: string, opts: InternalOptions): string shTarget = shTarget.split('\\').join('/') const quotedPathToTarget = path.isAbsolute(shTarget) ? `"${shTarget}"` : `"$basedir/${shTarget}"` const quotedPathToTarget_win = path.isAbsolute(shTarget) ? `"${shTarget}"` : `"$basedir_win/${shTarget}"` - let shTarget_win - // For `.cmd`/`.bat` targets the runtime is `cmd` and args is `/C`. When - // Git Bash / MSYS launches a native Win32 process, arguments that look - // like POSIX paths are translated — a bare `/C` becomes `C:\`, which - // drops the switch and leaves cmd.exe running interactively. Prefixing - // with `//` is the MSYS escape: it survives the translation and reaches - // cmd.exe as `/C`. Scoped to the cmd runtime so shebang-derived `/C` - // args on other shims are passed through unchanged. + let shTarget_win = '' let args = opts.args || '' - if (opts.prog === 'cmd' || opts.prog === 'cmd.exe') { - args = escapeMsysCmdSwitches(args) - } + const isCmdRuntime = opts.prog === 'cmd' || opts.prog === 'cmd.exe' const shNodePath = normalizePathEnvVar(opts.nodePath).posix if (!shProg) { shProg = quotedPathToTarget @@ -481,14 +472,15 @@ function generateShShim (src: string, to: string, opts: InternalOptions): string // basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") // basedir_win="$basedir" // exe="" + // msys="" // // case `uname -a` in // *CYGWIN*|*MINGW*|*MSYS*) // if command -v cygpath > /dev/null 2>&1; then - // basedir=`cygpath -w "$basedir"` - // basedir_win="$basedir" + // basedir_win=`cygpath -w "$basedir"` // fi // exe=".exe" + // msys="true" // ;; // *WSL2*) // if command -v wslpath > /dev/null 2>&1; then @@ -521,14 +513,15 @@ function generateShShim (src: string, to: string, opts: InternalOptions): string basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -558,35 +551,50 @@ fi ` } - if (shLongProg) { - if (shProgHasExe) { - sh += `\ + const generateExecBlock = (execArgs: string) => { + if (shLongProg) { + if (shProgHasExe) { + return `\ if [ -x ${shLongProgExe} ]; then - exec ${shLongProgExe} ${args} ${shTarget_win} ${progArgs}"$@" + exec ${shLongProgExe} ${execArgs} ${shTarget_win} ${progArgs}"$@" else - exec ${shProgExe} ${args} ${shTarget_win} ${progArgs}"$@" + exec ${shProgExe} ${execArgs} ${shTarget_win} ${progArgs}"$@" fi ` - } else { - sh += `\ + } else { + return `\ if [ -n "$exe" ] && [ -x ${shLongProgExe} ]; then - exec ${shLongProgExe} ${args} ${shTarget_win} ${progArgs}"$@" + exec ${shLongProgExe} ${execArgs} ${shTarget_win} ${progArgs}"$@" elif [ -x ${shLongProg} ]; then - exec ${shLongProg} ${args} ${shTarget} ${progArgs}"$@" + exec ${shLongProg} ${execArgs} ${shTarget} ${progArgs}"$@" elif command -v ${shProg} >/dev/null 2>&1; then - exec ${shProg} ${args} ${shTarget} ${progArgs}"$@" + exec ${shProg} ${execArgs} ${shTarget} ${progArgs}"$@" elif [ -n "$exe" ] && command -v ${shProgExe} >/dev/null 2>&1; then - exec ${shProgExe} ${args} ${shTarget_win} ${progArgs}"$@" + exec ${shProgExe} ${execArgs} ${shTarget_win} ${progArgs}"$@" else - exec ${shProg} ${args} ${shTarget} ${progArgs}"$@" + exec ${shProg} ${execArgs} ${shTarget} ${progArgs}"$@" fi +` + } + } else { + return `\ +exec ${shProg} ${execArgs} ${shTarget} ${progArgs}"$@" +exit $? ` } - } else { + } + + const msysArgs = isCmdRuntime ? escapeMsysCmdSwitches(args) : args + if (msysArgs !== args) { sh += `\ -exec ${shProg} ${args} ${shTarget} ${progArgs}"$@" -exit $? +if [ -n "$msys" ]; then +${indentShellBlock(generateExecBlock(msysArgs))} +else +${indentShellBlock(generateExecBlock(args))} +fi ` + } else { + sh += generateExecBlock(args) } // Marker used by consumers to detect whether the shim is up-to-date @@ -596,6 +604,10 @@ exit $? return sh } +function indentShellBlock (script: string): string { + return script.split('\n').map(line => line ? ` ${line}` : line).join('\n') +} + /** * Generate the content of a shim for PowerShell. * diff --git a/test/e2e.test.js.snapshot b/test/e2e.test.js.snapshot index 5c74d67..6490475 100644 --- a/test/e2e.test.js.snapshot +++ b/test/e2e.test.js.snapshot @@ -4,14 +4,15 @@ exports[`create a command shim for a .exe file > shim files 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then diff --git a/test/test.js.snapshot b/test/test.js.snapshot index f6994af..0dfcfff 100644 --- a/test/test.js.snapshot +++ b/test/test.js.snapshot @@ -4,14 +4,15 @@ exports[`batch script > shim files > bat.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -25,16 +26,32 @@ case \`uname -a\` in ;; esac -if [ -n "$exe" ] && [ -x "$basedir/cmd.exe" ]; then - exec "$basedir/cmd.exe" //C "$basedir_win/src.bat" "$@" -elif [ -x "$basedir/cmd" ]; then - exec "$basedir/cmd" //C "$basedir/src.bat" "$@" -elif command -v cmd >/dev/null 2>&1; then - exec cmd //C "$basedir/src.bat" "$@" -elif [ -n "$exe" ] && command -v cmd.exe >/dev/null 2>&1; then - exec cmd.exe //C "$basedir_win/src.bat" "$@" +if [ -n "$msys" ]; then + if [ -n "$exe" ] && [ -x "$basedir/cmd.exe" ]; then + exec "$basedir/cmd.exe" //C "$basedir_win/src.bat" "$@" + elif [ -x "$basedir/cmd" ]; then + exec "$basedir/cmd" //C "$basedir/src.bat" "$@" + elif command -v cmd >/dev/null 2>&1; then + exec cmd //C "$basedir/src.bat" "$@" + elif [ -n "$exe" ] && command -v cmd.exe >/dev/null 2>&1; then + exec cmd.exe //C "$basedir_win/src.bat" "$@" + else + exec cmd //C "$basedir/src.bat" "$@" + fi + else - exec cmd //C "$basedir/src.bat" "$@" + if [ -n "$exe" ] && [ -x "$basedir/cmd.exe" ]; then + exec "$basedir/cmd.exe" /C "$basedir_win/src.bat" "$@" + elif [ -x "$basedir/cmd" ]; then + exec "$basedir/cmd" /C "$basedir/src.bat" "$@" + elif command -v cmd >/dev/null 2>&1; then + exec cmd /C "$basedir/src.bat" "$@" + elif [ -n "$exe" ] && command -v cmd.exe >/dev/null 2>&1; then + exec cmd.exe /C "$basedir_win/src.bat" "$@" + else + exec cmd /C "$basedir/src.bat" "$@" + fi + fi `; @@ -90,14 +107,15 @@ exports[`custom node executable > shim files > env.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -150,14 +168,15 @@ exports[`env shebang > shim files > env.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -236,14 +255,15 @@ exports[`env shebang with NODE_PATH > shim files > env.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -345,14 +365,15 @@ exports[`env shebang with PATH extending > shim files > env.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -443,14 +464,15 @@ exports[`env shebang with args > shim files > env.args.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -529,14 +551,15 @@ exports[`env shebang with default args > shim files > env.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -615,14 +638,15 @@ exports[`env shebang with no NODE_PATH > shim files > env.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -701,14 +725,15 @@ exports[`explicit shebang > shim files > sh.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -787,14 +812,15 @@ exports[`explicit shebang with args > shim files > sh.args.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -873,14 +899,15 @@ exports[`explicit shebang with args, linking to another drive on Windows > shim basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -959,14 +986,15 @@ exports[`explicit shebang with prog args > shim files > sh.args.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -1045,14 +1073,15 @@ exports[`no cmd file > shim files > exe.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -1098,14 +1127,15 @@ exports[`no shebang > shim files > exe.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then @@ -1158,14 +1188,15 @@ exports[`shebang with -S > shim files > from.env.s.shim 1`] = ` basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')") basedir_win="$basedir" exe="" +msys="" case \`uname -a\` in *CYGWIN*|*MINGW*|*MSYS*) if command -v cygpath > /dev/null 2>&1; then - basedir=\`cygpath -w "$basedir"\` - basedir_win="$basedir" + basedir_win=\`cygpath -w "$basedir"\` fi exe=".exe" + msys="true" ;; *WSL2*) if command -v wslpath > /dev/null 2>&1; then