Skip to content

Commit

Permalink
Sanitize spawn calls which contain .cmd for win32
Browse files Browse the repository at this point in the history
  • Loading branch information
luke.swan committed Oct 16, 2024
1 parent 3c347ac commit 9510bca
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const install = async (
// See: https://github.com/raineorshine/npm-check-updates/issues/1191
...(packageManager === 'pnpm' ? { npm_config_strict_peer_dependencies: false } : null),
},
shell: process.platform === 'win32',
},
)
print(options, stdout)
Expand Down
7 changes: 5 additions & 2 deletions src/package-managers/npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,14 +586,15 @@ async function spawnNpm(
spawnOptions: Index<any> = {},
): Promise<any> {
const cmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'
const sanitizedSpawnOptions = process.platform === 'win32' ? { ...spawnOptions, shell: true } : spawnOptions

const fullArgs = [
...(npmOptions.global ? [`--global`] : []),
...(npmOptions.prefix ? [`--prefix=${npmOptions.prefix}`] : []),
'--json',
...(Array.isArray(args) ? args : [args]),
]
const { stdout } = await spawn(cmd, fullArgs, spawnPleaseOptions, spawnOptions)
const { stdout } = await spawn(cmd, fullArgs, spawnPleaseOptions, sanitizedSpawnOptions)
return stdout
}

Expand All @@ -609,15 +610,17 @@ export async function defaultPrefix(options: Options): Promise<string | undefine
if (options.prefix) {
return Promise.resolve(options.prefix)
}
const spawnOptions = {}

const cmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'
const sanitizedSpawnOptions = process.platform === 'win32' ? { ...spawnOptions, shell: true } : spawnOptions

let prefix: string | undefined

// catch spawn error which can occur on Windows
// https://github.com/raineorshine/npm-check-updates/issues/703
try {
const { stdout } = await spawn(cmd, ['config', 'get', 'prefix'])
const { stdout } = await spawn(cmd, ['config', 'get', 'prefix'], {}, sanitizedSpawnOptions)
prefix = stdout
} catch (e: any) {
const message = (e.message || e || '').toString()
Expand Down
9 changes: 6 additions & 3 deletions src/package-managers/pnpm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ export const list = async (options: Options = {}): Promise<Index<string | undefi
// use npm for local ls for completeness
// this should never happen since list is only called in runGlobal -> getInstalledPackages
if (!options.global) return npm.list(options)
const spawnOptions = {}

const cmd = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
const { stdout } = await spawn(cmd, ['ls', '-g', '--json'])
const sanitzedSpawnOptions = process.platform === 'win32' ? { ...spawnOptions, shell: true } : spawnOptions
const { stdout } = await spawn(cmd, ['ls', '-g', '--json'], {}, sanitzedSpawnOptions)
const result = JSON.parse(stdout) as PnpmList
const list = keyValueBy(result[0].dependencies || {}, (name, { version }) => ({
[name]: version,
Expand Down Expand Up @@ -91,18 +93,19 @@ export const semver = withNpmWorkspaceConfig(npm.semver)
async function spawnPnpm(
args: string | string[],
npmOptions: NpmOptions = {},
spawnOptions?: SpawnOptions,
spawnOptions: SpawnOptions = {},
spawnPleaseOptions?: SpawnPleaseOptions,
): Promise<string> {
const cmd = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
const sanitzedSpawnOptions = process.platform === 'win32' ? { ...spawnOptions, shell: true } : spawnOptions

const fullArgs = [
...(npmOptions.global ? 'global' : []),
...(Array.isArray(args) ? args : [args]),
...(npmOptions.prefix ? `--prefix=${npmOptions.prefix}` : []),
]

const { stdout } = await spawn(cmd, fullArgs, spawnPleaseOptions, spawnOptions)
const { stdout } = await spawn(cmd, fullArgs, spawnPleaseOptions, sanitzedSpawnOptions)

return stdout
}
Expand Down
7 changes: 5 additions & 2 deletions src/package-managers/yarn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ async function spawnYarn(
spawnOptions: SpawnOptions = {},
): Promise<string> {
const cmd = process.platform === 'win32' ? 'yarn.cmd' : 'yarn'
const sanitizedSpawnOptions = process.platform === 'win32' ? { ...spawnOptions, shell: true } : spawnOptions

const fullArgs = [
...(yarnOptions.global ? ['global'] : []),
Expand All @@ -208,7 +209,7 @@ async function spawnYarn(
...(Array.isArray(args) ? args : [args]),
]

const { stdout } = await spawn(cmd, fullArgs, spawnPleaseOptions, spawnOptions)
const { stdout } = await spawn(cmd, fullArgs, spawnPleaseOptions, sanitizedSpawnOptions)

return stdout
}
Expand All @@ -225,10 +226,12 @@ export async function defaultPrefix(options: Options): Promise<string | null> {
if (options.prefix) {
return Promise.resolve(options.prefix)
}
const spawnOptions = {}

const cmd = process.platform === 'win32' ? 'yarn.cmd' : 'yarn'
const sanitizedSpawnOptions = process.platform === 'win32' ? { ...spawnOptions, shell: true } : spawnOptions

const { stdout: prefix } = await spawn(cmd, ['global', 'dir'])
const { stdout: prefix } = await spawn(cmd, ['global', 'dir'], {}, sanitizedSpawnOptions)
// yarn 2.0 does not support yarn global
// catch error to prevent process from crashing
// https://github.com/raineorshine/npm-check-updates/issues/873
Expand Down
1 change: 1 addition & 0 deletions src/types/SpawnOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ import { Index } from './IndexType'
export interface SpawnOptions {
cwd?: string
env?: Index<string>
shell?: boolean
}

0 comments on commit 9510bca

Please sign in to comment.