Skip to content

fix: apply patches during pnpm fetch behind skipped file deps#11063

Open
teee32 wants to merge 3 commits into
pnpm:mainfrom
teee32:fix/fetch-patches-skipped-file-deps
Open

fix: apply patches during pnpm fetch behind skipped file deps#11063
teee32 wants to merge 3 commits into
pnpm:mainfrom
teee32:fix/fetch-patches-skipped-file-deps

Conversation

@teee32

@teee32 teee32 commented Mar 22, 2026

Copy link
Copy Markdown

Problem

pnpm fetch can import a registry package into the virtual store without applying its patch when that package is only reachable through a local file: dependency.

Reproduction / Observation

A minimal repro looks like this:

  1. The root project depends on file:./local-pkg.
  2. local-pkg depends on is-positive@1.0.0.
  3. patchedDependencies contains a patch for is-positive@1.0.0.
  4. Run pnpm install --lockfile-only, remove the root manifest, then run pnpm fetch.

Before this change, fetch created the patched virtual-store directory (is-positive@1.0.0_patch_hash=...) but the imported index.js still contained the unpatched source.

Root cause

headlessInstall() runs patch application via buildModules(), but its root set is built from directDependenciesByImporterId.

When fetch skips local file: dependencies, packages that are only reachable through those skipped nodes are no longer part of that root set. They still get imported into the virtual store from the lockfile, but the later patch/build traversal never visits them.

Change

  • Add patched package nodes to the buildModules() root set in installing/deps-restorer.
  • Add a command-level regression test that covers a patched registry dependency behind a skipped local file: dependency.
  • Add a patch changeset for the user-facing pnpm fetch behavior fix.

Why this fix

This keeps the fix narrow:

  • resolution/import behavior is unchanged
  • only packages already marked with patch != null are added as extra build roots
  • regular installs already reach these packages through direct importer roots, so the behavior change is specific to the fetch + skipped-local-dependency path

Risk

Low. The change does not alter dependency selection or lockfile handling; it only ensures the existing patch step can reach already-imported patched packages.

Validation

  • pnpm --dir _work/pnpm --filter @pnpm/installing.commands run test test/fetch.ts
  • pnpm --dir _work/pnpm --filter @pnpm/installing.deps-installer run test test/install/patch.ts -t 'patch package with exact version'

Fixes #11034.

@teee32 teee32 requested a review from zkochan as a code owner March 22, 2026 15:02
Copilot AI review requested due to automatic review settings March 22, 2026 15:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an edge case where pnpm fetch imports patched packages into the virtual store but fails to actually apply the patch when the package is only reachable through skipped local file: dependencies.

Changes:

  • Extend the buildModules() root set in headlessInstall() to include all dependency graph nodes that have patch info.
  • Add a regression test covering a patched registry dependency that is only reachable via a skipped file: dependency during fetch.
  • Add a changeset documenting the user-facing pnpm fetch fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
installing/deps-restorer/src/index.ts Ensures patched packages are always reachable by the patch/build traversal even when direct importer roots are incomplete (e.g. fetch skipping file: deps).
installing/commands/test/fetch.ts Adds a regression test to assert patched content is present after pnpm fetch in the skipped-file: scenario.
.changeset/fair-mails-wave.md Publishes the behavior change as a patch release for the affected packages/CLI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread installing/commands/test/fetch.ts Outdated
zkochan added 2 commits March 24, 2026 14:48
Ensure fetch still traverses patched packages when the package tree is only reachable
through local file dependencies that are skipped during fetch.
Locate the patched package directory by probing for the actual file
instead of matching on the directory name prefix, which can fail on
Windows due to virtualStoreDirMaxLength truncation.
@zkochan zkochan force-pushed the fix/fetch-patches-skipped-file-deps branch from 6af1951 to 504c192 Compare March 24, 2026 14:00
Move the fix from deps-restorer (adding patched nodes to directNodes)
to deps/graph-builder where the problem originates. When local file:
deps are skipped during fetch, their transitive registry children become
orphaned in the build traversal. Now lockfileToDepGraph promotes those
children into directDependenciesByImporterId so they're naturally
reachable.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread deps/graph-builder/src/lockfileToDepGraph.ts
Comment thread deps/graph-builder/src/lockfileToDepGraph.ts
Comment thread deps/graph-builder/src/lockfileToDepGraph.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v10.32.1] pnpm fetch does not apply patches

3 participants