refactor(pacquet/config): replace env mutations with DI pattern#11718
Conversation
… DI seam Replaces process-environment mutation in the `default_store_dir` tests with the dependency-injection pattern established in pnpm/pacquet#339 and consolidated for the in-tree pacquet subtree in #11708. Tracks pnpm/pacquet#343 — the original issue still applied after pacquet was merged into this repo because the env-mutating tests came with it. The four affected unit tests (`test_default_store_dir_with_pnpm_home_env` and `test_default_store_dir_with_xdg_env` in `defaults::tests`, plus `should_use_pnpm_home_env_var` and `should_use_xdg_data_home_env_var` in `lib::tests`) now drive each branch with per-test unit structs that satisfy `EnvVar`. No `EnvGuard` snapshot, no `unsafe` block, no process-environment write. The `home_dir` and `current_dir` closures call `unreachable!` for branches the early `PNPM_HOME` / `XDG_DATA_HOME` returns short-circuit before consulting them, documenting the precondition the way the style guide's worked example does. `default_store_dir` is now generic over `Sys: EnvVar` and takes the `home_dir` and `current_dir` lookups as `FnOnce` closures, mirroring the shape of `Config::current`. A thin args-less wrapper `default_store_dir_host` wires the production `Host` provider together with `home::home_dir` and `env::current_dir` so the SmartDefault expression on `Config::store_dir` stays short. The `have_default_values` wiring assertion now compares against `default_store_dir::<Host>(home::home_dir, env::current_dir)` instead of the old args-less helper. `npmrc_auth::tests::ignores_non_auth_keys` no longer needs to hold the EnvGuard global lock against the two `Config::new()` snapshots it compares — nothing in the crate mutates `PNPM_HOME` or `XDG_DATA_HOME` anymore, so the env-derived `store_dir` is observed identically by both calls even under nextest's in-process parallelism. `EnvGuard` itself stays in `pacquet-testing-utils` because the proxy cascade and `NPM_CONFIG_WORKSPACE_DIR` tests in `lib::tests`, as well as out-of-crate users in `git-fetcher` and `executor`, still rely on it. Retiring it entirely is out of scope for this issue. --- Written by an agent (Claude Code, claude-opus-4-7).
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
📝 WalkthroughWalkthroughThis PR replaces direct process-global reads in config defaults with a DI seam: ChangesProcess-global state dependency injection for config defaults
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #11718 +/- ##
==========================================
- Coverage 89.74% 89.73% -0.02%
==========================================
Files 129 129
Lines 14949 14970 +21
==========================================
+ Hits 13416 13433 +17
- Misses 1533 1537 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Micro-Benchmark ResultsLinux |
…ameter
The Windows branch of `default_store_dir` calls
`current_dir().expect("current directory is unavailable")`, which
requires `Error: Debug` on the `Result<PathBuf, Error>` returned by the
`CurrentDir` closure. The original `where` clause didn't declare that
bound, so the function compiled on Linux/macOS (where the Windows
branch is `#[cfg(windows)]`-gated out) but failed on
`Lint and Test (windows-latest)` once the cfg fired.
All current callers pass `env::current_dir` (Error = `io::Error`) or
pin `Error = std::io::Error` via turbofish on test fakes — both
already satisfy `Debug` — so this is a pure type-bound fix with no
behaviour or call-site change.
---
Written by an agent (Claude Code, claude-opus-4-7).
The "Dependency injection for tests" gating list in
`pacquet/CODE_STYLE_GUIDE.md` enumerated four reasons to reach past
real fixtures for the DI seam: filesystem error kinds, deterministic
time, external-service happy paths, and unreachable-by-design
preconditions. It did not cover the case this PR retired from
`default_store_dir`: tests that mutate a single per-process slot
(env vars, cwd, umask, signal handlers, …) and so race with every
other test in the same process.
The pre-existing `EnvGuard` workaround restored correctness only by
holding a binary-wide mutex around `unsafe { env::set_var(...) }`,
which forecloses parallelism inside the affected tests and leaves
`unsafe` in the test source. A capability-trait fake keeps the read
deterministic and the mutation contained to the test that needs it.
Adds that bullet to the style guide between "Deterministic time" and
"External-service happy paths," and updates rule 7 in
`pacquet/AGENTS.md` (and its `CLAUDE.md` / `GEMINI.md` symlink
targets) so the summary mirrors the longer list.
---
Written by an agent (Claude Code, claude-opus-4-7).
The previous commit cited `set_current_dir` and "the umask" as illustrative examples in both the style guide and the AGENTS rule 7 summary. Neither is actually used anywhere in the pacquet codebase today — only `env::set_var` is. Speculative examples in a style guide invite contributors to chase patterns that don't exist, so narrow the wording to the one slot we have a concrete example for while keeping the principle generalisable (the bullet still says "any future analogue"). --- Written by an agent (Claude Code, claude-opus-4-7).
…ullet Reviewer feedback: keep the broader `set_current_dir` / umask / signal-handler / global-allocator examples in the DI gating bullet and rule 7 summary. They're not used in the codebase today, but the analogues are useful as forward-looking illustrations so the next contributor recognises the same shape when it comes up. Restores the wording introduced in 96040d7; reverses the narrowing in d930bed. --- Written by an agent (Claude Code, claude-opus-4-7).
Adds a "Reading process state" section to CODE_STYLE_GUIDE.md, placed right before "Dependency injection for tests" so the reading order captures the two questions in dependency order: first ask whether you should be reaching for `env::var` / `env::current_dir` at all, then ask how to inject it if the answer is yes. The section pins: 1. Library code should rarely call `std::env::var`, `std::env::var_os`, or `std::env::current_dir` directly. The default fix is a parameter (`&Path`, `&str`, an `Option<String>`, or a `FnOnce` closure) so the caller decides which value to read; `Config::current` and `workspace::find_workspace_dir_from_env_with` already follow this. 2. When the read genuinely needs to happen, route through the DI seam (`Sys: EnvVar`, `Sys::var(name)`). 3. The narrow legitimate direct-call case is computing a `Config` default that has no caller — `default_store_dir`, `default_modules_dir`, `default_virtual_store_dir`. This is the "begrudging" use that pnpm/pacquet#343 + #11718 finally threaded through the DI seam. 4. Other accepted boundary reads are program-entry knobs (`RAYON_NUM_THREADS`, `TRACE`) and the lifecycle-script env snapshot in `crates/executor` / `crates/git-fetcher` that forwards the parent env to spawned children verbatim. The section belongs in CODE_STYLE_GUIDE.md (code-level convention), not CONTRIBUTING.md (PR workflow) or AGENTS.md (agent-specific operating rules); rule 7 in AGENTS.md already cross-links the style guide, so no change there. --- Written by an agent (Claude Code, claude-opus-4-7).
Reviewer pointed out that the args-less `default_store_dir_host` wrapper could be inlined into the `#[default(_code = ...)]` expression on `Config::store_dir` — the SmartDefault macro accepts the turbofish form `default_store_dir::<Host, _, _, _>(home::home_dir, env::current_dir)` verbatim, and once the wrapper is gone there's nothing for the indirection to earn. Dropping the wrapper also removes a small motivation for the `Host` import inside `defaults.rs` — adjust the doc comment on `default_store_dir` to cite `crate::Host` by full path instead. The `#[cfg(windows)] Error: std::fmt::Debug` bound that the same reviewer asked about is not feasible: attributes on where-clause predicates are still unstable (rust-lang/rust#115590), so the bound stays unconditional with a comment explaining why. --- Written by an agent (Claude Code, claude-opus-4-7).
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pacquet/crates/config/src/lib.rs`:
- Around line 977-986: Update the stale comment so it no longer references the
removed `default_store_dir_host` wrapper and instead documents the direct call
to `default_store_dir::<Host, _, _, _>(home::home_dir, env::current_dir)` for
`store_dir`; edit the paragraph that currently mentions `default_store_dir_host`
and replace that wording with the direct generic `default_store_dir` invocation
and a brief note that the SmartDefault expression resolves via the production
capability using `Host`, `home::home_dir`, and `env::current_dir`, leaving the
rest of the explanation about wiring and tests (`defaults::tests`) unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c6bdd0be-23ad-4c42-b782-d3cf7f643e30
📒 Files selected for processing (6)
pacquet/AGENTS.mdpacquet/CODE_STYLE_GUIDE.mdpacquet/crates/config/src/defaults.rspacquet/crates/config/src/defaults/tests.rspacquet/crates/config/src/lib.rspacquet/crates/config/src/npmrc_auth/tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Agent
- GitHub Check: ubuntu-latest / Node.js 24 / Test
- GitHub Check: Run benchmark on ubuntu-latest
- GitHub Check: Lint and Test (windows-latest)
🧰 Additional context used
📓 Path-based instructions (3)
pacquet/**/AGENTS.md
📄 CodeRabbit inference engine (pacquet/CLAUDE.md)
Document agent functionality and interactions in AGENTS.md
pacquet/**/AGENTS.md: Document agent responsibilities, capabilities, and interactions in AGENTS.md file
Maintain clear and up-to-date documentation of all agent definitions and their purposes
Include agent capabilities, input/output specifications, and integration guidelines in agent documentation
Files:
pacquet/AGENTS.md
pacquet/**/*.{rs,md,txt}
📄 CodeRabbit inference engine (pacquet/AGENTS.md)
When citing code anywhere (code comments, doc comments, Markdown docs, PR descriptions, or commit messages), link to a specific commit SHA (first 10 hex characters), not a branch name. Branch links are impermanent and may 404 if files change.
Files:
pacquet/AGENTS.mdpacquet/crates/config/src/defaults.rspacquet/crates/config/src/defaults/tests.rspacquet/crates/config/src/npmrc_auth/tests.rspacquet/CODE_STYLE_GUIDE.mdpacquet/crates/config/src/lib.rs
pacquet/**/*.rs
📄 CodeRabbit inference engine (pacquet/AGENTS.md)
Any change in pacquet must match how the same feature is implemented in the TypeScript pnpm CLI. Find the equivalent code in pnpm workspaces, read the implementation including logic and edge cases, and port the behavior faithfully with structural similarity.
Do not invent behavior that pnpm does not have. Do not 'fix' pnpm quirks unless the same fix has landed in pnpm. If pnpm and pacquet disagree, pnpm is the source of truth.
Log emissions are part of 'match pnpm'. When porting a function that fires events through globalLogger/logger.debug/streamParser.write, mirror the call site, payload, and ordering so
@pnpm/cli.default-reporterparses pacquet's NDJSON the same way it parses pnpm's.Prefer real fixtures (tempfile::TempDir, mocked registry, integration tests) over dependency-injection seams for most happy paths and error paths. Use the DI seam (capability trait on Host provider) only for branches real fixtures cannot reach: filesystem error kinds, deterministic time, process-global state mutations, or external-service happy paths.
Declare a newtype wrapper for branded string types. Do not collapse the brand into plain String or &str. Give the type its own struct so misuse is a type error.
If upstream always validates before construction of a branded string type, validate too in the Rust wrapper via TryFrom and/or FromStr. Do not provide an infallible public constructor.
If upstream never validates a branded string type, just brand for type-safety. Expose an infallible From and From<&str> where convenient. The type-safety win is the whole point.
If upstream occasionally constructs a branded string type without validation via bare 'as' assertion, expose from_str_unchecked or similarly named constructor on the Rust side. Keep the validating constructor as well.
Match upstream serde behavior for branded types crossing JSON/YAML/INI boundaries. Use #[serde(try_from = "String")] for deserialization (validates) and #[serde(into = "String")] for s...
Files:
pacquet/crates/config/src/defaults.rspacquet/crates/config/src/defaults/tests.rspacquet/crates/config/src/npmrc_auth/tests.rspacquet/crates/config/src/lib.rs
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: pnpm/pnpm
Timestamp: 2026-05-18T14:22:41.046Z
Learning: Follow the contributing guide in CONTRIBUTING.md, including commit message format, writing style, setup, and automated checks to run before committing.
Learnt from: CR
Repo: pnpm/pnpm
Timestamp: 2026-05-18T14:22:41.046Z
Learning: Follow the code style guide in CODE_STYLE_GUIDE.md for code-level conventions beyond what cargo fmt, taplo, and clippy enforce: imports, modules, naming, ownership and borrowing, trait bounds, pattern matching, pipe-trait, error handling, test layout, and Arc/Rc cloning.
Learnt from: CR
Repo: pnpm/pnpm
Timestamp: 2026-05-18T14:22:41.046Z
Learning: Keep dependencies at the right level. Add a new dependency to the specific crate that needs it, not to the workspace root or a shared crate unless multiple crates actually depend on it.
Learnt from: CR
Repo: pnpm/pnpm
Timestamp: 2026-05-18T14:22:41.046Z
Learning: User-facing errors go through miette via the pacquet-diagnostics crate. Match pnpm's error codes and messages where pnpm defines them — error codes are part of the public contract.
Learnt from: CR
Repo: pnpm/pnpm
Timestamp: 2026-05-18T14:22:41.046Z
Learning: Keep commits focused. A bug fix commit should not also refactor or reformat unrelated code. Reference the upstream pnpm commit/PR you ported from when applicable.
📚 Learning: 2026-05-14T17:38:34.573Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11640
File: pacquet/AGENTS.md:1-6
Timestamp: 2026-05-14T17:38:34.573Z
Learning: In this repository, files named `AGENTS.md` are agent-guide instructions for AI coding tools (e.g., Claude Code/Codex/Cursor) following the agentsmd.net convention, not documentation of software agents or an agentic framework. When reviewing `**/AGENTS.md`, do not apply review rules intended for agentic-framework documentation (e.g., documenting agent capabilities, inputs/outputs, or integration points); instead, treat these files as tooling/assistive guidance for contributors.
Applied to files:
pacquet/AGENTS.md
🔇 Additional comments (6)
pacquet/AGENTS.md (1)
52-54: LGTM!pacquet/CODE_STYLE_GUIDE.md (1)
507-515: LGTM!Also applies to: 524-524
pacquet/crates/config/src/defaults.rs (1)
1-1: LGTM!Also applies to: 56-90, 93-93, 97-97, 103-103, 107-107, 110-112
pacquet/crates/config/src/defaults/tests.rs (1)
5-5: LGTM!Also applies to: 18-26, 28-38, 41-50, 54-60, 63-73, 76-100
pacquet/crates/config/src/lib.rs (1)
18-18: LGTM!Also applies to: 187-189, 959-963, 1007-1053
pacquet/crates/config/src/npmrc_auth/tests.rs (1)
59-69: LGTM!
There was a problem hiding this comment.
Pull request overview
Refactors pacquet-config’s default_store_dir logic and tests to avoid mutating the process environment, by routing env reads through the existing DI seam (Sys: EnvVar) and injecting home_dir / current_dir as closures. This aligns the crate with the pacquet DI conventions introduced in the earlier seam consolidation work.
Changes:
- Made
default_store_dirgeneric overSys: EnvVarand injectedhome_dir/current_dirclosures to keep tests deterministic withoutstd::env::set_var/EnvGuard. - Updated
pacquet-configtests to use per-testEnvVarfakes to coverPNPM_HOMEandXDG_DATA_HOMEprecedence branches. - Updated pacquet documentation to recommend avoiding direct process-state reads in library code and to prefer parameterization/DI.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
pacquet/crates/config/src/npmrc_auth/tests.rs |
Removes EnvGuard usage and updates rationale comments around env-derived defaults. |
pacquet/crates/config/src/lib.rs |
Updates Config::store_dir SmartDefault wiring and rewrites env-dependent tests to use DI fakes instead of env mutation. |
pacquet/crates/config/src/defaults/tests.rs |
Replaces env-mutation tests with EnvVar fake providers and adds deterministic fall-through coverage. |
pacquet/crates/config/src/defaults.rs |
Refactors default_store_dir to accept Sys: EnvVar plus injected home/cwd closures. |
pacquet/CODE_STYLE_GUIDE.md |
Adds guidance on avoiding direct process-state reads and when to use DI. |
pacquet/AGENTS.md |
Updates contributor checklist to include “shared process-global state that tests would otherwise mutate” as a DI-appropriate case. |
Comments suppressed due to low confidence (1)
pacquet/CODE_STYLE_GUIDE.md:524
- The DI guidance references
pnpm/pnpm#11718as the PR that retiredEnvGuardfromdefault_store_dir, but elsewhere in this document/PR the referenced change ispnpm/pnpm#11708(and this PR). Please reconcile the PR number so the historical link is accurate.
- **Shared process-global state that tests would otherwise mutate.** When a branch depends on a single per-process slot — environment variables, the current working directory, the umask, signal handlers, the global allocator — the only way to exercise it without DI is to write to that slot, and the write is observed by every other test in the same process. A serialisation lock (the `EnvGuard` pattern that pnpm/pacquet#343 + pnpm/pnpm#11718 retired from `default_store_dir`) restores correctness only by forcing the affected tests to run single-threaded, and leaves an `unsafe { env::set_var(...) }` block at the call site. A capability-trait fake keeps the read deterministic and the mutation contained to the test that needs it, so nextest's in-process parallelism stays useful and `unsafe` stays out of test code. The reverse follows too: a real-fixture happy path should not be promoted to DI just because it crosses a process-global slot — only the *mutation* side of the slot is the problem; reading whatever the shell already has is fine.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // The SmartDefault expression for `store_dir` resolves to | ||
| // `default_store_dir::<Host>(home::home_dir, env::current_dir)` | ||
| // via the thin `default_store_dir_host` wrapper, so calling | ||
| // the generic helper here with the same `Host` capability and | ||
| // the same OS closures must produce the same value — even on | ||
| // a developer machine with `PNPM_HOME` / `XDG_DATA_HOME` set. | ||
| // This is the wiring assertion that proves the SmartDefault | ||
| // field still goes through the production capability; the | ||
| // per-branch behaviour of `default_store_dir` is exercised | ||
| // with fake-`Sys` structs in `defaults::tests`. |
There was a problem hiding this comment.
Same stale comment as CodeRabbit's; updated to match the current direct call in ef28426.
Written by an agent (Claude Code, claude-opus-4-7).
Generated by Claude Code
| // `Config::new()` reads `PNPM_HOME` / `XDG_DATA_HOME` via | ||
| // `default_store_dir::<Host>` to compute `store_dir`. Both | ||
| // values come from the real process environment, but no other | ||
| // test in this crate mutates them anymore — the per-branch | ||
| // tests in `defaults::tests` and `lib::tests` drive | ||
| // `default_store_dir` through the dependency-injection seam | ||
| // (pnpm/pacquet#339, pnpm/pnpm#11708, pnpm/pacquet#343) with | ||
| // fake `Sys` providers, so the two `Config::new()` snapshots | ||
| // compared below observe the same env-derived `store_dir` even | ||
| // under nextest's in-process parallelism without an `EnvGuard` | ||
| // lock. |
There was a problem hiding this comment.
Right — the comment cited the old single-type-param signature. Updated in ef28426 to spell out the current four-parameter turbofish: default_store_dir::<Host, _, _, _>(home::home_dir, env::current_dir).
Written by an agent (Claude Code, claude-opus-4-7).
Generated by Claude Code
| - **Take the value as a parameter.** A function that needs a path declares `path: &Path`; one that needs an env-var value takes it as a `&str` argument, an `Option<String>`, or a `FnOnce` closure that produces it. `Config::current` threads the cwd through a caller-supplied `FnOnce() -> Result<PathBuf, _>` closure rather than calling `env::current_dir` itself, and `crates/workspace`'s `find_workspace_dir_from_env_with` does the same for an env-var lookup — both let tests drive the read without touching the process environment. | ||
| - **Thread the read through the DI seam.** Declare `Sys: EnvVar` and call `Sys::var(name)`. See [Dependency injection for tests](#dependency-injection-for-tests) for the convention. | ||
|
|
||
| The narrow case where a direct call is acceptable is computing the default of a `Config` field that has no caller to take the value from — `default_store_dir`, `default_modules_dir`, and `default_virtual_store_dir` are the canonical examples; this is the "begrudging" use behind pnpm/pacquet#343. Even there, route the lookup through the DI seam: the generic `default_store_dir<Sys: EnvVar>` form keeps the reads testable, and the args-less wrapper that feeds `SmartDefault` (`default_store_dir_host`) is a single-line composition of the production capabilities (`Host`, `home::home_dir`, `env::current_dir`) that exists only because the `SmartDefault` macro needs an args-less expression. The other accepted boundary reads are program-entry knobs (`RAYON_NUM_THREADS` in `crates/cli`, `TRACE` in `crates/diagnostics`) and the lifecycle-script env snapshot in `crates/executor` and `crates/git-fetcher`, which has to forward the parent environment to spawned children verbatim. If new library code seems to need `env::var` / `env::current_dir` for any other reason, the answer is almost always a `&Path` (or equivalent) parameter, not a process-state read. |
There was a problem hiding this comment.
Fixed in ef28426. The style guide now recommends inlining the production composition at the SmartDefault site directly (#[default(_code = "default_store_dir::<Host, _, _, _>(home::home_dir, env::current_dir)")]) rather than introducing an args-less wrapper.
On the suppressed low-confidence comment in the same review about the PR number (pnpm/pnpm#11718 vs #11708) — #11708 introduced the DI seam consolidation, and this PR (#11718) is the one that actually retires the EnvGuard pattern from default_store_dir. The citation is correct as-is.
Written by an agent (Claude Code, claude-opus-4-7).
Generated by Claude Code
Commit 49c690c inlined the SmartDefault expression for `Config::store_dir` and dropped the `default_store_dir_host` wrapper, but three comments still pointed at the wrapper or at the old single-type-parameter signature of `default_store_dir`. CodeRabbit and Copilot flagged all three on review: - `crates/config/src/lib.rs`, `have_default_values`: the comment said the SmartDefault resolved "via the thin `default_store_dir_host` wrapper". Now reflects the direct `default_store_dir::<Host, _, _, _>(home::home_dir, env::current_dir)` call. - `crates/config/src/npmrc_auth/tests.rs`, `ignores_non_auth_keys`: the comment cited `default_store_dir::<Host>` with no closure parameters. Now spells out the four-parameter turbofish that matches the current signature. - `CODE_STYLE_GUIDE.md`, "Reading process state": the paragraph recommended an args-less `default_store_dir_host` wrapper as the pattern to follow. Now recommends inlining the production composition at the `SmartDefault` site directly. Copilot also queried whether `#11718` was the right number in the DI section's `EnvGuard` retirement citation — confirmed it is. #11708 introduced the DI seam consolidation; this PR is the one that retires the env-mutation pattern from `default_store_dir`. --- Written by an agent (Claude Code, claude-opus-4-7).
Integrated-Benchmark Report (Linux)Scenario: Frozen Lockfile
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 2.44746032906,
"stddev": 0.07750584005097994,
"median": 2.44802273846,
"user": 2.65026798,
"system": 3.7087297199999996,
"min": 2.3426409989600003,
"max": 2.5503736049600003,
"times": [
2.52185342996,
2.36222052296,
2.5358972899600003,
2.5503736049600003,
2.4486619589600003,
2.44738351796,
2.49716208296,
2.3426409989600003,
2.3578353889600003,
2.41057449496
]
},
{
"command": "pacquet@main",
"mean": 2.4035835999600006,
"stddev": 0.05095639506254182,
"median": 2.39778391346,
"user": 2.6613895800000003,
"system": 3.7110050200000004,
"min": 2.35567497796,
"max": 2.5127644419600004,
"times": [
2.39227323796,
2.36901105096,
2.35567497796,
2.5127644419600004,
2.40635619796,
2.4100352169600003,
2.40329458896,
2.36261885096,
2.35729530996,
2.46651212596
]
},
{
"command": "pnpm",
"mean": 4.82267371796,
"stddev": 0.04583083190450137,
"median": 4.82486827796,
"user": 8.28508578,
"system": 4.12960382,
"min": 4.73652744996,
"max": 4.89758743196,
"times": [
4.82416828896,
4.87628666996,
4.84113149196,
4.822546441959999,
4.79256983296,
4.82891030496,
4.89758743196,
4.8255682669599995,
4.73652744996,
4.78144099996
]
}
]
}Scenario: Frozen Lockfile (Hot Cache)
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 0.67458871466,
"stddev": 0.022132698632454404,
"median": 0.66994754156,
"user": 0.37849946,
"system": 1.5504529999999999,
"min": 0.65679761906,
"max": 0.73577442106,
"times": [
0.73577442106,
0.67112866206,
0.66248265306,
0.67137322906,
0.66876642106,
0.66514512506,
0.67515804106,
0.66775263006,
0.65679761906,
0.67150834506
]
},
{
"command": "pacquet@main",
"mean": 0.70678647046,
"stddev": 0.0527348985626677,
"median": 0.69511974006,
"user": 0.36626756000000005,
"system": 1.5739554999999998,
"min": 0.65888172406,
"max": 0.8278255450600001,
"times": [
0.76738284806,
0.70668373306,
0.66534019906,
0.8278255450600001,
0.68646658106,
0.65888172406,
0.70525097506,
0.67451550306,
0.70377289906,
0.67174469706
]
},
{
"command": "pnpm",
"mean": 2.5835932454600004,
"stddev": 0.14161888940838308,
"median": 2.52395747106,
"user": 3.2075173600000007,
"system": 2.2070575000000003,
"min": 2.46516238406,
"max": 2.89700385706,
"times": [
2.89700385706,
2.46516238406,
2.53022899706,
2.69122918406,
2.50368231306,
2.51768594506,
2.46832524806,
2.5440317400600003,
2.7252994250600002,
2.49328336106
]
}
]
} |
Tracks pnpm/pacquet#343. The env-mutating
default_store_dirtests came with the pacquet subtree merge, so the original fix still applies here — this PR threads them through the DI seam consolidated in #11708.Summary
default_store_diris now generic overSys: EnvVarwithhome_dir/current_dirasFnOnceclosures (same shape asConfig::current). A thin args-lessdefault_store_dir_hostwrapper keeps theSmartDefaultexpression onConfig::store_dirshort.test_default_store_dir_with_pnpm_home_env,test_default_store_dir_with_xdg_envindefaults::tests;should_use_pnpm_home_env_var,should_use_xdg_data_home_env_varinlib::tests) now drive each branch with per-test unit-structEnvVarfakes — noEnvGuard, nounsafe, nostd::env::set_var. Closures the early returns don't consume callunreachable!to document the precondition.EnvGuardfromnpmrc_auth::tests::ignores_non_auth_keys: nothing in the crate mutatesPNPM_HOME/XDG_DATA_HOMEanymore.EnvGuarditself stays — proxy-cascade andNPM_CONFIG_WORKSPACE_DIRtests, plusgit-fetcher/executor, still rely on it. Retiring it entirely is out of scope.Test plan
cargo check -p pacquet-config --testscargo fmt --checkcargo test -p pacquet-config(155 passed)just ready(CI)Written by an agent (Claude Code, claude-opus-4-7).
Summary by CodeRabbit
Documentation
Refactor
Tests