-
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-npmis 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-npmis updated to a version such as0.1.19, the@go-task/clidependency is implicitly updated. Sincepostuninstallis not run at this time,taskbinaries that were incorrectly installed by@go-task/go-npmbefore 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
globalandaddarguments in theoriginalproperty. However, from reading the Yarn v1 source code, it should probably be enough to check that the value of thecookedproperty is not["add"]. But I haven't been able to test it with the old Yarn yet. ↩