Skip to content

Commit 13815ad

Browse files
felipecrszkochan
andauthored
fix: warnings in store|config should be printed to stderr (#12434)
* fix: warnings in `store|config` should be printed to `stderr` * refactor: extract stderr-reporter command list into a named set --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
1 parent 9e0c375 commit 13815ad

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

.changeset/store-use-stderr.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"pnpm": patch
3+
---
4+
5+
Reporter output (warnings, progress) for `pnpm store` and `pnpm config` subcommands now goes to stderr instead of stdout. This fixes scripts that capture their stdout (e.g. `PNPM_STORE=$(pnpm store path)`, `pnpm config list --json | jq`) from getting warnings mixed into the result.

pnpm/src/main.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ import { syncEnvLockfile } from './syncEnvLockfile.js'
3636

3737
export const REPORTER_INITIALIZED = Symbol('reporterInitialized')
3838

39+
// Commands whose reporter output (warnings, progress) must go to stderr so that
40+
// their stdout stays a clean, machine-readable value. For example, `pnpm store
41+
// path` is meant to be captured with `STORE=$(pnpm store path)` and `pnpm config
42+
// list --json` to be piped into `jq`; a warning mixed into stdout would corrupt
43+
// both.
44+
const COMMANDS_WITH_STDERR_REPORTER = new Set(['dlx', 'create', 'config', 'set', 'get', 'sbom', 'with', 'store'])
45+
3946
loudRejection()
4047

4148
function isRootOnlyPatterns (patterns: string[]): boolean {
@@ -95,6 +102,7 @@ export async function main (inputArgv: string[]): Promise<void> {
95102
// we don't need the write permission to it. Related issue: #2700
96103
const globalDirShouldAllowWrite = cmd !== 'root'
97104
const isDlxOrCreateCommand = cmd === 'dlx' || cmd === 'create'
105+
const isConfigCommand = cmd === 'config' || cmd === 'set' || cmd === 'get'
98106
if (cmd === 'link' && cliParams.length === 0) {
99107
cliOptions.global = true
100108
}
@@ -138,9 +146,9 @@ export async function main (inputArgv: string[]): Promise<void> {
138146
// `cmd === 'config'` at this layer, so list them explicitly — users can
139147
// hit the #10684 crash via any of these three entry points.
140148
;({ config, context } = await installConfigDepsAndLoadHooks(config, context, {
141-
tolerateConfigDependenciesErrors: cmd === 'config' || cmd === 'set' || cmd === 'get',
149+
tolerateConfigDependenciesErrors: isConfigCommand,
142150
}) as { config: typeof config, context: ConfigContext })
143-
if (isDlxOrCreateCommand || cmd === 'sbom' || cmd === 'with') {
151+
if (cmd != null && COMMANDS_WITH_STDERR_REPORTER.has(cmd)) {
144152
config.useStderr = true
145153
}
146154
config.argv = argv

0 commit comments

Comments
 (0)