mirror of
https://github.com/pnpm/pnpm.git
synced 2026-01-06 22:18:17 -05:00
21
.changeset/slow-shrimps-laugh.md
Normal file
21
.changeset/slow-shrimps-laugh.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-script-runners": patch
|
||||
---
|
||||
|
||||
Added --shell-mode option support to pnpm exec [#4328](https://github.com/pnpm/pnpm/pull/4328)
|
||||
|
||||
* `--shell-mode`: shell interpreter. see: https://github.com/sindresorhus/execa/tree/484f28de7c35da5150155e7a523cbb20de161a4f#shell
|
||||
|
||||
Usage example:
|
||||
|
||||
```shell
|
||||
pnpm --recursive --shell-mode exec -- echo \"\$PNPM_PACKAGE_NAME\"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"check": " pnpm --recursive --shell-mode exec -- echo \"\\$PNPM_PACKAGE_NAME\""
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -19,17 +19,21 @@ import {
|
||||
|
||||
export const shorthands = {
|
||||
parallel: runShorthands.parallel,
|
||||
c: '--shell-mode',
|
||||
}
|
||||
|
||||
export const commandNames = ['exec']
|
||||
|
||||
export function rcOptionsTypes () {
|
||||
return pick([
|
||||
'bail',
|
||||
'sort',
|
||||
'unsafe-perm',
|
||||
'workspace-concurrency',
|
||||
], types)
|
||||
return {
|
||||
...pick([
|
||||
'bail',
|
||||
'sort',
|
||||
'unsafe-perm',
|
||||
'workspace-concurrency',
|
||||
], types),
|
||||
'shell-mode': Boolean,
|
||||
}
|
||||
}
|
||||
|
||||
export const cliOptionsTypes = () => ({
|
||||
@@ -54,11 +58,18 @@ For options that may be used with `-r`, see "pnpm help recursive"',
|
||||
name: '--recursive',
|
||||
shortAlias: '-r',
|
||||
},
|
||||
{
|
||||
description: 'If exist, runs file inside of a shell. \
|
||||
Uses /bin/sh on UNIX and \\cmd.exe on Windows. \
|
||||
The shell should understand the -c switch on UNIX or /d /s /c on Windows.',
|
||||
name: '--shell-mode',
|
||||
shortAlias: '-c',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
url: docsUrl('exec'),
|
||||
usages: ['pnpm [-r] exec <command> [args...]'],
|
||||
usages: ['pnpm [-r] [-c] exec <command> [args...]'],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -70,6 +81,7 @@ export async function handler (
|
||||
reverse?: boolean
|
||||
sort?: boolean
|
||||
workspaceConcurrency?: number
|
||||
shellMode?: boolean
|
||||
} & Pick<Config, 'extraBinPaths' | 'lockfileDir' | 'dir' | 'userAgent' | 'recursive' | 'workspaceDir'>,
|
||||
params: string[]
|
||||
) {
|
||||
@@ -134,6 +146,7 @@ export async function handler (
|
||||
cwd: prefix,
|
||||
env,
|
||||
stdio: 'inherit',
|
||||
shell: opts.shellMode ?? false,
|
||||
})
|
||||
result.passes++
|
||||
} catch (err: any) { // eslint-disable-line
|
||||
|
||||
@@ -414,6 +414,35 @@ test('pnpm exec outside of projects', async () => {
|
||||
expect(outputs).toStrictEqual([])
|
||||
})
|
||||
|
||||
test('pnpm exec shell mode', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
const echoArgs = process.platform === 'win32' ? '%PNPM_PACKAGE_NAME% > name.txt' : '$PNPM_PACKAGE_NAME > name.txt'
|
||||
|
||||
await exec.handler({
|
||||
...DEFAULT_OPTS,
|
||||
dir: process.cwd(),
|
||||
recursive: false,
|
||||
selectedProjectsGraph: {
|
||||
[process.cwd()]: {
|
||||
dependencies: [],
|
||||
package: {
|
||||
dir: process.cwd(),
|
||||
writeProjectManifest: async () => {},
|
||||
manifest: {
|
||||
name: 'test_shell_mode',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
shellMode: true,
|
||||
}, ['echo', echoArgs])
|
||||
|
||||
const result = (await fs.readFile(path.resolve('name.txt'), 'utf8')).trim()
|
||||
|
||||
expect(result).toBe('test_shell_mode')
|
||||
})
|
||||
|
||||
test('pnpm recursive exec works with PnP', async () => {
|
||||
preparePackages([
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user