feat(exec): support shell interpreter (#4328)

close #4320
This commit is contained in:
Black-Hole
2022-02-13 20:28:01 +08:00
committed by GitHub
parent e1b4590084
commit 8d3255515b
3 changed files with 70 additions and 7 deletions

View 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\""
}
}
```

View File

@@ -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

View File

@@ -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([
{