[BUG] npx with option -c doesn't work as expected in gitbash on windows
mofterdinger opened this issue · comments
What / Why
Hi,
I try to use npx
with option -c
in a gitbash on windows to execute a command provided by an npm module, but npx
tells me that the command wasn't found. The same command line works fine on Mac/Linux.
This is the command I try to execute: npx -c 'cds version'
.
The npm module is: @sap/cds-dk
I'm using the following versions:
- npx: 6.14.8
- node: v12.16.3
- gitbash: 1.9.5
When
Each time I execute the command line: npx -c 'cds version'
Where
- n/a
How
Current Behavior
The command npx
without option -c
works fine, but we want to have a npm run-script-like shell environment.
Steps to Reproduce
Inside a gitbash on windows follow these steps to reproduce:
- create an empty directory and cd into it
- call
npm init
- call
npm install @sap/cds-dk
- call
npx -c 'cds version'
--> you get error:
'cds' is not recognized as an internal or external command, operable program or batch file.
Expected Behavior
See this console output with version information:
@sap/cds: 4.1.7
@sap/cds-compiler: 1.35.0
@sap/cds-dk: 2.0.8
@sap/cds-foss: 2.0.0
@sap/cds-reflect: 2.12.2
@sap/cds-runtime: 2.1.7
Node.js: v12.16.3
home: c:\Users\d032842\workspaces\playground\testnpx\node_modules\@sap\cds-dk\node_modules\@sap\cds
testnpx: 1.0.0
Who
- n/a
References
- n/a
Hi,
is someone able to reproduce this issue and can tell me, if this is an issue in npx or do I use it the wrong way?
Thanks,
Markus
I was able to find the root cause of this issue, but I am unsure how this can be fixed in npx/npm.
The reason any npx -c
command doesn't work in git-bash or any other cygwin bash is, that npx
is getting a Unix-like environment from npm run env
, even though it will execute the command by default within a standard windows cmd
shell.
In case of the option -c
npx creates a node run-script like environment using npm run env
(code). The environment returned from this process is later set in the npx process environment (code).
Using that environment a new process is spawned later on using child_process.spawn, on Windows this always runs inside a new shell (code), which by default is given by process.env.COMSPEC
, which usually is set to cmd.exe
.
However the environment returned by npm run env
is not a valid environment for a cmd.exe
windows process, as when it is executed inside a git-bash it returns a Unix-style PATH
environment variable, which leads to the command not found error mentioned in the issue.
The npm run env
returns such a PATH environment variable, because of the special handling for cygwin and git-bash shells on Windows, which can be seen here and ultimately here.
The npx command therefore executes successfully, when removing the environment variables MSYSTEM
and TERM
.
Therefore MSYSTEM= TERM= npx -c 'cds version'
runs successfully, while npx -c 'cds version'
fails.
Another possibility to fix this issue, is to prevent npx
to let child_process.spawn
pick the cmd.exe
as shell, but explicitly pass option -s "C:\Program Files\Git\bin\bash.exe"
to ensure that the git bash is also used as shell by npx
, which then again fits the Unix-style PATH environment variable. Unfortunately setting the npm config option script-shell
(reference) does not seem to be considered by npx
. This could however help to override the default in such an environment.
I guess therefore there are two main issues at play here. The first is that npx
and child_process.spawn
assume a Windows-like environment if only process.platform === 'win32'
, while npm run env
seems to consider the environment variables MSYSTEM
and TERM
as well. The other issue is that npx
does not consider NPMs configuration option script-shell
.