Skip to content

pacquet: support remote (non-registry) https-tarball direct dependencies (prerequisite for #12001 integrity parity) #12053

Description

@zkochan

Summary

Pacquet does not support remote (non-registry) https-tarball direct dependencies end to end. Installing one (e.g. "foo": "https://cdn.example.com/foo-1.0.0.tgz") panics while building the lockfile. This is the prerequisite for matching pnpm's behavior around tarball-dependency integrity — in particular the fix in #12040 for #12001 — which cannot be reached in pacquet until external tarball deps install at all.

Current behavior

A bare specifier whose URL starts with the configured registry is claimed by the npm resolver (it is parsed as a registry name@version at parse_bare_specifier.rs:91, faithfully mirroring pnpm's parseBareSpecifier). That path already carries integrity from registry metadata and works fine.

A URL that does not start with the registry falls through to the TarballResolver, which returns name_ver: None, manifest: None, and integrity: None (lines 89/92/95) — by design, since the name/version/integrity are only known after the tarball is downloaded and its package.json is read. Nothing in the resolve/install pipeline then fetches the tarball to fill those in, so the install panics:

Error:   × Main thread panicked.
  ├─▶ at pacquet/crates/package-manager/src/dependencies_graph_to_lockfile.rs:327:10
  ╰─▶ dep paths produced by the resolver always parse as PkgNameVerPeer: MissingSuffix

The panic is at dependencies_graph_to_lockfile.rs:327: with name_ver unset, the dep path is just the URL, which cannot parse as PkgNameVerPeer. The doc comment a few lines below even notes that tarball/git/file resolvers "learn the name from the fetched manifest" — pacquet just doesn't do that fetch for direct tarball deps yet.

Reproduction

// package.json — tarball URL on a host that is NOT the configured registry
{ "dependencies": { "is-positive": "https://cdn.example.com/is-positive/-/is-positive-1.0.0.tgz" } }
pacquet install   # panics (MissingSuffix) instead of resolving + installing

In tests, the same path is reached by pointing at the loopback registry via 127.0.0.1 while the registry is configured as localhost (so the URL prefix doesn't match) — see the test referenced below.

Work to implement

  1. Fetch the tarball manifest during resolution for TarballResolver results (download the tarball, read package.json), so name_ver and manifest are populated — matching pnpm's tarball resolver + fetcher flow.
  2. Compute and record integrity for the downloaded tarball, so the lockfile entry is complete and the install pass (which already errors on a tarball resolution missing integrity) succeeds.
  3. Carry integrity over on reuse. Once external tarball deps install, port pnpm's fix: preserve tarball dependency integrity in the lockfile #12040 fix: when a tarball dep is reused from the lockfile without being re-fetched (e.g. an unrelated add/install rewrites the lockfile), keep the existing integrity rather than dropping it — otherwise the next --frozen-lockfile install fails with ERR_PNPM_MISSING_TARBALL_INTEGRITY.

Test coverage already in place

A gated regression test lands with the #12040 mirror: pacquet/crates/cli/tests/tarball_url_dependency.rsremote_tarball_integrity_survives_unrelated_install. It encodes the full target scenario (install external tarball dep → add an unrelated package → assert integrity preserved verbatim → --frozen-lockfile succeeds) but is gated with allow_known_failure! because the feature isn't built. When the work above lands, flip the known-failure gate and the test enforces the #12001 invariant directly.

References


Written by an agent (Claude Code, claude-opus-4-8).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions