Files
pnpm/pacquet
Khải 4ec0049f55 fix(pacquet/git-fetcher): bundle transitive deps of bundled dependencies (#12620)
* fix(git-fetcher): bundle transitive deps of bundled dependencies

The packlist `bundleDependencies` pass only spliced in each
directly-bundled package's own files; it never followed that package's
own dependencies, so a bundled dep's transitive (and hoisted)
dependencies were dropped from the published file set.

Replace the per-dependency recursion with npm-bundled's reachability
walk: seed from the root manifest's `bundleDependencies`, then
transitively pull in every reachable package's `dependencies` and
`optionalDependencies`, resolving each via the node module-resolution
walk-up (nested `node_modules/` first, then ancestor `node_modules/`).
The walk-up is what lets a hoisted transitive dep at the root
`node_modules/` be found and spliced in under its real path. A
visited-set keyed on the canonicalised resolved directory keeps a
diamond from being processed twice and stops dependency cycles.

Ports the upstream pnpm test "bundles transitive dependencies of
bundled dependencies (hoisted)" from
releasing/commands/test/publish/pack.ts, plus nested-wins-over-hoisted
and optionalDependencies/devDependencies coverage.

Resolves https://github.com/pnpm/pnpm/issues/12602

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga

* docs(git-fetcher): fix stale bundling comment and pin test citation

Address review nits on the transitive-bundling change:

- The comment in `collect_own_files` referred to a `bundleDependencies`
  pass "below", but bundling now lives in the separate
  `collect_bundled_files`; describe the current structure instead.
- Pin the ported-test citation to a commit permalink, per
  pacquet/AGENTS.md's rule that code citations link to a specific SHA.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga

* fix(git-fetcher): refuse bundled deps whose real path escapes the package

A `node_modules/<name>` entry can be a symlink pointing outside the
package (a sibling directory or an absolute host path). The name still
passes `is_safe_bundle_name` because it is a single safe segment, so the
walk-up resolves it and `collect_own_files` walks the symlink target —
splicing host files into the published set. The git/directory fetchers
import untrusted packages, making this an information-disclosure path.

Check each resolved dependency's canonical (symlink-resolved) path
against the canonical package root and refuse anything that escapes,
falling back to a lexical comparison when canonicalization is
unavailable. Reuses the canonicalize call already used for cycle dedup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga

* fix(git-fetcher): fail closed when a bundled dep's real path is unverifiable

The symlink-escape guard fell back to a lexical path check whenever
`fs::canonicalize` returned `None` for the dependency. A symlink under
`node_modules/` is lexically inside the package even when its target
escapes, so that fallback was fail-open. When the root canonicalizes but
the dependency does not, refuse the dependency instead: a genuine
dependency always canonicalizes here, since `resolve_bundled_dependency`
already stat'd its `package.json` through the same path. The lexical
fallback now applies only when the root itself cannot be canonicalized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga

* fix(git-fetcher): correct the upstream test citation to a real commit

The previous citation pinned SHA cab1c11c69, which does not exist — it
was taken from the issue body without verification. Point instead at the
in-repo copy of the test at pnpm11/releasing/commands/test/publish/pack.ts,
pinned to a commit that actually contains it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-24 11:38:38 +00:00
..
2026-04-30 16:35:57 +02:00

pacquet

Warning

pacquet is under active development and not yet ready for production use.

The official pnpm rewrite in Rust.

pacquet is a port of the pnpm CLI from TypeScript to Rust. It is not a new package manager and not a reimagining of pnpm. Its behavior, flags, defaults, error codes, file formats, and directory layout will match pnpm exactly.

Roadmap

pacquet will become the installation engine of pnpm. The transition will happen in two phases.

Phase 1: fetching and linking

pacquet replaces fetching and linking only. pnpm continues to create the lockfile, and pacquet does the rest. We expect this alone to make pnpm at least twice as fast in most scenarios. Shipping this phase is the current focus.

Phase 2: resolution

pacquet also takes over dependency resolution.

See CONTRIBUTING.md for development setup, debugging, testing, and benchmarking.

Benchmark