fix(exec): preserve user execution cwd (#10445)

close #5759
close #10403
This commit is contained in:
Zoltan Kochan
2026-01-12 15:41:17 +01:00
committed by GitHub
parent 938ea1f18c
commit e4d08f920e
5 changed files with 39 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-script-runners": patch
"pnpm": patch
---
When running "pnpm exec" from a subdirectory of a project, don't change the current working directory to the root of the project [#5759](https://github.com/pnpm/pnpm/issues/5759).

View File

@@ -146,6 +146,7 @@ export type ExecOpts = Required<Pick<Config, 'selectedProjectsGraph'>> & {
implicitlyFellbackFromRun?: boolean
} & Pick<Config,
| 'bin'
| 'cliOptions'
| 'dir'
| 'extraBinPaths'
| 'extraEnv'
@@ -187,7 +188,7 @@ export async function handler (
chunks = chunks.reverse()
}
} else {
chunks = [[opts.dir as ProjectRootDir]]
chunks = [[(opts.cliOptions.dir ?? process.cwd()) as ProjectRootDir]]
const project = await tryReadProjectManifest(opts.dir)
if (project.manifest != null) {
opts.selectedProjectsGraph = {

View File

@@ -158,6 +158,7 @@ export type RunOpts =
& { recursive?: boolean }
& Pick<Config,
| 'bin'
| 'cliOptions'
| 'verifyDepsBeforeRun'
| 'dir'
| 'enablePrePostScripts'

View File

@@ -157,6 +157,7 @@ test('exec inside a workspace package', async () => {
'--store-dir',
path.resolve(DEFAULT_OPTS.storeDir),
])
process.chdir('project-1')
await exec.handler({
...DEFAULT_OPTS,
dir: path.resolve('project-1'),

29
pnpm/test/exec.ts Normal file
View File

@@ -0,0 +1,29 @@
import fs from 'fs'
import path from 'path'
import { prepare } from '@pnpm/prepare'
import { execPnpm, execPnpmSync } from './utils/index.js'
test("exec should respect the caller's current working directory", async () => {
prepare({
name: 'root',
version: '1.0.0',
})
const projectRoot = process.cwd()
fs.mkdirSync('some-directory', { recursive: true })
const subdirPath = path.join(projectRoot, 'some-directory')
await execPnpm(['install'])
const cmdFilePath = path.join(subdirPath, 'cwd.txt')
execPnpmSync(
['exec', 'node', '-e', `require('fs').writeFileSync(${JSON.stringify(cmdFilePath)}, process.cwd(), 'utf8')`],
{
cwd: subdirPath,
expectSuccess: true,
}
)
expect(fs.readFileSync(cmdFilePath, 'utf8')).toBe(subdirPath)
})