fix: don't recursively switch to the same pnpm version (#8468)

This commit is contained in:
Zoltan Kochan
2024-08-27 13:10:25 +02:00
committed by GitHub
parent 735fc909fd
commit 757e6be29d
5 changed files with 46 additions and 3 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/env.path": minor
---
Add a new field to the return object: `updated`. When `false`, the prepended paths were already present in the path.

View File

@@ -0,0 +1,5 @@
---
"pnpm": patch
---
Throw an exception if pnpm switches to the same version of itself.

19
env/path/src/index.ts vendored
View File

@@ -1,12 +1,27 @@
import path from 'path'
import PATH from 'path-name'
export function prependDirsToPath (prependDirs: string[], env = process.env): { name: string, value: string } {
export interface PrependDirsToPathResult {
name: string
value: string
updated: boolean
}
export function prependDirsToPath (prependDirs: string[], env = process.env): PrependDirsToPathResult {
const prepend = prependDirs.join(path.delimiter)
if (env[PATH] != null && (env[PATH] === prepend || env[PATH]!.startsWith(`${prepend}${path.delimiter}`))) {
return {
name: PATH,
value: env[PATH]!,
updated: false,
}
}
return {
name: PATH,
value: [
...prependDirs,
prepend,
...(env[PATH] != null ? [env[PATH]] : []),
].join(path.delimiter),
updated: true,
}
}

View File

@@ -6,9 +6,21 @@ test('prependDirsToPath', () => {
expect(prependDirsToPath(['foo'], {})).toStrictEqual({
name: PATH,
value: 'foo',
updated: true,
})
expect(prependDirsToPath(['foo'], { [PATH]: 'bar' })).toStrictEqual({
name: PATH,
value: `foo${path.delimiter}bar`,
updated: true,
})
expect(prependDirsToPath(['foo', 'qar'], { [PATH]: `foo${path.delimiter}qar${path.delimiter}bar` })).toStrictEqual({
name: PATH,
value: `foo${path.delimiter}qar${path.delimiter}bar`,
updated: false,
})
expect(prependDirsToPath(['foo', 'qar'], { [PATH]: `foo${path.delimiter}qar` })).toStrictEqual({
name: PATH,
value: `foo${path.delimiter}qar`,
updated: false,
})
})

View File

@@ -1,6 +1,7 @@
import fs from 'fs'
import path from 'path'
import { type Config } from '@pnpm/config'
import { PnpmError } from '@pnpm/error'
import { globalWarn } from '@pnpm/logger'
import { getCurrentPackageName, packageManager } from '@pnpm/cli-meta'
import { prependDirsToPath } from '@pnpm/env.path'
@@ -37,7 +38,12 @@ export async function switchCliVersion (config: Config): Promise<void> {
[`${pkgName}@${pm.version}`]
)
}
const pnpmEnv = prependDirsToPath([path.join(dir, 'bin')])
const wantedPnpmBinDir = path.join(dir, 'bin')
const pnpmEnv = prependDirsToPath([wantedPnpmBinDir])
if (!pnpmEnv.updated) {
// We throw this error to prevent an infinite recursive call of the same pnpm version.
throw new PnpmError('VERSION_SWITCH_FAIL', `Failed to switch pnpm to v${pm.version}. Looks like pnpm CLI is missing at "${wantedPnpmBinDir}" or is incorrect`)
}
const { status } = spawn.sync('pnpm', process.argv.slice(2), {
stdio: 'inherit',
env: {