-
Notifications
You must be signed in to change notification settings - Fork 4
Description
As reported in go-task/task#1081, local installation with npm v9 or later always installs binaries in the global directory.
This is because @go-task/go-npm
always uses the environment variable npm_config_prefix
to get the installation directory instead when the npm bin
command fails.
In npm v9 and later, the npm bin
command has been removed.
Lines 25 to 49 in b3015da
// `npm bin` will output the path where binary files should be installed | |
exec('npm bin', (err, stdout, stderr) => { | |
let dir = null; | |
if (err || stderr || !stdout || stdout.length === 0) { | |
// We couldn't infer path from `npm bin`. Let's try to get it from | |
// Environment variables set by NPM when it runs. | |
// npm_config_prefix points to NPM's installation directory where `bin` folder is available | |
// Ex: /Users/foo/.nvm/versions/node/v4.3.0 | |
const env = process.env; | |
// Get the package manager who is running the script | |
// This is needed since PNPM works in a different way than NPM or YARN. | |
const packageManager = usedPM(); | |
if (env && env.npm_config_prefix) { | |
if (process.platform === 'win32') { | |
// On Windows, use the installation directory itself instead of the `bin` folder. | |
// See: https://docs.npmjs.com/cli/v6/configuring-npm/folders#executables | |
dir = env.npm_config_prefix; | |
} else { | |
dir = join(env.npm_config_prefix, 'bin'); | |
} | |
} else if (env && env.npm_config_local_prefix) { |
@go-task/go-npm
should only use the npm_config_prefix
environment variable when in global mode.
In the case of npm and pnpm, global mode can be detected by reading the npm_config_global
environment variable.
process.env.npm_config_global === 'true'
However, in the case of Yarn V1, the npm_config_global
environment variable does not exist, so the npm_config_argv
environment variable should be parsed to determine this instead. I am still investigating the correct logic, but it is still buggy 1.
Note
This needs to be released as a breaking change.
When@go-task/go-npm
is upgraded, the user's environment will no longer remove binaries that were previously installed by mistake.For example, the following version range is specified in
@go-task/cli
:"@go-task/go-npm": "^0.1.17"--- https://github.com/go-task/task/blob/e0d3e33c32cfa0c99afd95b74086852983603a51/package.json#L32
In this case, when
@go-task/go-npm
is updated to a version such as0.1.19
, the@go-task/cli
dependency is implicitly updated. Sincepostuninstall
is not run at this time,task
binaries that were incorrectly installed by@go-task/go-npm
before this bug was fixed will not be removed.Therefore, it is necessary to upgrade to a version out of this range (e.g.
0.3.0
,1.0.0
).
Footnotes
-
Currently it compares the order of the
global
andadd
arguments in theoriginal
property. However, from reading the Yarn v1 source code, it should probably be enough to check that the value of thecooked
property is not["add"]
. But I haven't been able to test it with the old Yarn yet. β©