feat(pacquet): port resolving/tarball-resolver#11773
Conversation
|
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 ignored due to path filters (1)
📒 Files selected for processing (1)
📜 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). (7)
🧰 Additional context used📓 Path-based instructions (1)pacquet/**/*.rs📄 CodeRabbit inference engine (pacquet/AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-05-20T19:40:55.051ZApplied to files:
🔇 Additional comments (1)
📝 WalkthroughWalkthroughThis PR introduces a new ChangesTarball Resolution Support
Sequence DiagramsequenceDiagram
participant Client
participant TarballResolver
participant ThrottledClient
participant ResolveResult
Client->>TarballResolver: resolve(WantedDependency)
TarballResolver->>TarballResolver: validate bare_specifier and HTTP(S)
TarballResolver->>TarballResolver: normalize URL via url::Url
TarballResolver->>ThrottledClient: HEAD request
ThrottledClient-->>TarballResolver: response with Cache-Control
TarballResolver->>TarballResolver: select immutable post-redirect or request URL
TarballResolver->>ResolveResult: construct Tarball resolution
ResolveResult-->>Client: return claim with resolved tarball URL
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
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 |
Micro-Benchmark ResultsLinux |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #11773 +/- ##
==========================================
+ Coverage 89.66% 89.70% +0.03%
==========================================
Files 170 171 +1
Lines 20318 20392 +74
==========================================
+ Hits 18218 18292 +74
Misses 2100 2100 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Integrated-Benchmark Report (Linux)Scenario: Frozen Lockfile
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 2.57263951852,
"stddev": 0.11982532150411719,
"median": 2.53351660082,
"user": 2.7983286799999996,
"system": 3.8273040799999998,
"min": 2.41951009332,
"max": 2.77014530232,
"times": [
2.53547155032,
2.53156165132,
2.77014530232,
2.76433000132,
2.41951009332,
2.47769901532,
2.6424793803199997,
2.59753264932,
2.49069087932,
2.49697466232
]
},
{
"command": "pacquet@main",
"mean": 2.49053240452,
"stddev": 0.057384167495415084,
"median": 2.49318167532,
"user": 2.76756908,
"system": 3.82022608,
"min": 2.40489517332,
"max": 2.59835963632,
"times": [
2.40489517332,
2.52583561532,
2.51645085032,
2.48981142232,
2.5393671483199998,
2.59835963632,
2.49655192832,
2.44206403232,
2.44914585032,
2.44284238832
]
},
{
"command": "pnpm",
"mean": 4.942611014020001,
"stddev": 0.056675404293762284,
"median": 4.9498312783200005,
"user": 8.35457258,
"system": 4.266083879999999,
"min": 4.85344168532,
"max": 5.018762268320001,
"times": [
5.018762268320001,
4.97307549932,
4.982182868320001,
4.85344168532,
4.9013517253200005,
4.87484351632,
4.911298594320001,
4.9333888343200005,
5.01149142632,
4.96627372232
]
}
]
}Scenario: Frozen Lockfile (Hot Cache)
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 0.69129429678,
"stddev": 0.007632192448618294,
"median": 0.69092345048,
"user": 0.40964648,
"system": 1.5711779600000002,
"min": 0.67743203548,
"max": 0.70282783148,
"times": [
0.69666908448,
0.68568283548,
0.68951244448,
0.69900668748,
0.70282783148,
0.69657927348,
0.68625927448,
0.67743203548,
0.68663904448,
0.69233445648
]
},
{
"command": "pacquet@main",
"mean": 0.7405651207799998,
"stddev": 0.07140788286630792,
"median": 0.70340644548,
"user": 0.4132271799999999,
"system": 1.6006218599999997,
"min": 0.69096950248,
"max": 0.89659043848,
"times": [
0.78614099548,
0.69779084048,
0.82687461848,
0.70666159648,
0.69543355348,
0.69096950248,
0.89659043848,
0.70193687848,
0.70487601248,
0.69837677148
]
},
{
"command": "pnpm",
"mean": 2.59874654148,
"stddev": 0.10921526889640769,
"median": 2.5540626909800004,
"user": 3.3043050800000002,
"system": 2.1799953600000004,
"min": 2.4739432954800002,
"max": 2.78249256948,
"times": [
2.74161571448,
2.5629021184800003,
2.5428791744800003,
2.78249256948,
2.54522326348,
2.49059866948,
2.51769268248,
2.4739432954800002,
2.62461993848,
2.7054979884800003
]
}
]
} |
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/package-manager/src/install_package_from_registry.rs`:
- Around line 111-114: The code currently unwraps parse of resolution.id into
PkgNameVer using expect in install_package_from_registry (the block that assigns
name_ver, real_name, version), which may panic on malformed ids; change this to
handle parse failure gracefully by matching the parse result (or using .ok_or /
map_err) and returning the appropriate error variant (UnsupportedResolution)
instead of panicking; ensure you reference resolution.id.as_ref().parse() and
PkgNameVer so the function returns Err(UnsupportedResolution) when parsing fails
and only proceeds to set real_name and version on success.
In `@pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs`:
- Around line 115-117: The is_http_url function currently claims inputs starting
with "http:" or "https:" too loosely (e.g., "http:foo"); tighten the check to
only accept proper schemes by matching "http://" and "https://" instead. Update
the is_http_url(bare: &str) logic to use starts_with("http://") ||
starts_with("https://") so non-standard specs aren't misrouted; verify related
call sites in TarballResolver and any unit tests that rely on is_http_url.
🪄 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: 97538b78-b147-41cd-84c5-09424d9c99e7
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (17)
Cargo.tomlpacquet/crates/package-manager/src/install_package_from_registry.rspacquet/crates/package-manager/src/install_package_from_registry/tests.rspacquet/crates/package-manager/src/install_without_lockfile.rspacquet/crates/resolving-default-resolver/src/tests.rspacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rspacquet/crates/resolving-deps-resolver/src/tests.rspacquet/crates/resolving-npm-resolver/src/npm_resolver.rspacquet/crates/resolving-npm-resolver/src/npm_resolver/tests.rspacquet/crates/resolving-resolver-base/Cargo.tomlpacquet/crates/resolving-resolver-base/src/lib.rspacquet/crates/resolving-resolver-base/src/resolve.rspacquet/crates/resolving-resolver-base/src/tests.rspacquet/crates/resolving-tarball-resolver/Cargo.tomlpacquet/crates/resolving-tarball-resolver/src/lib.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver/tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs
📄 CodeRabbit inference engine (pacquet/AGENTS.md)
pacquet/**/*.rs: When porting a function that firespnpm:<channel>events throughglobalLogger,logger.debug(), orstreamParser.write(), mirror the call site, payload, and ordering so the reporter parses pacquet's NDJSON the same way it parses pnpm's.
Declare a newtype wrapper for branded string types. Do not collapse the brand into a plainStringor&str.
If upstream always validates before construction, validate in pacquet's wrapper too. The wrapper must construct only viaTryFrom<String>and/orFromStr. Do not provide an infallible public constructor.
If upstream never validates, just brand for type-safety. Expose an infallibleFrom<String>(andFrom<&str>when convenient).
If upstream occasionally constructs without validation, exposefrom_str_uncheckedas an escape hatch alongside the validating constructor.
Match upstream serde behavior for branded types that cross JSON, YAML, or INI boundaries. Use#[serde(try_from = "String")]for deserialization and#[serde(into = "String")]for serialization.
Use#[derive(derive_more::From)]and#[derive(derive_more::Into)]for mechanical conversion impls. Fall back to manualimplonly when conversion needs custom logic.
String-literal unions should becomeenums, not newtype wrappers. Model closed sets of valid string values as enums.
Template literal types should be treated as branded strings with validation discipline from rules 2-5.
Choose owned vs. borrowed parameters to minimize copies. Widen to the most encompassing type (&Pathover&PathBuf,&strover&String) when it doesn't force extra copies.
PreferArc::clone(&x)/Rc::clone(&x)overx.clone()for reference-counted types, so the cost is visible at the call site.
Follow Rust API Guidelines for naming conventions.
Do not use star imports inside module bodies. Writeuse super::{Foo, bar}instead ofuse super::*;. Two forms stay allowed: external-crate preludes likeuse rayon::prelude::*;and root-of-module re-...
Files:
pacquet/crates/resolving-resolver-base/src/tests.rspacquet/crates/resolving-tarball-resolver/src/lib.rspacquet/crates/resolving-default-resolver/src/tests.rspacquet/crates/resolving-npm-resolver/src/npm_resolver/tests.rspacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rspacquet/crates/resolving-resolver-base/src/lib.rspacquet/crates/resolving-resolver-base/src/resolve.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver/tests.rspacquet/crates/resolving-deps-resolver/src/tests.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rspacquet/crates/resolving-npm-resolver/src/npm_resolver.rspacquet/crates/package-manager/src/install_package_from_registry/tests.rspacquet/crates/package-manager/src/install_package_from_registry.rspacquet/crates/package-manager/src/install_without_lockfile.rs
🧠 Learnings (1)
📚 Learning: 2026-05-20T19:40:55.051Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11774
File: pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs:0-0
Timestamp: 2026-05-20T19:40:55.051Z
Learning: In the pacquet Rust code, ensure the semver implementation uses the `node-semver` crate (not `nodejs-semver`). `node-semver`’s public API does not include a `satisfies_with_prerelease`-style method; prerelease-tolerant matching should be implemented inline by first calling `Range::satisfies`, and when it rejects a prerelease version, retry matching against a stripped `MAJOR.MINOR.PATCH` base of the prerelease version.
Applied to files:
pacquet/crates/resolving-resolver-base/src/tests.rspacquet/crates/resolving-tarball-resolver/src/lib.rspacquet/crates/resolving-default-resolver/src/tests.rspacquet/crates/resolving-npm-resolver/src/npm_resolver/tests.rspacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rspacquet/crates/resolving-resolver-base/src/lib.rspacquet/crates/resolving-resolver-base/src/resolve.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver/tests.rspacquet/crates/resolving-deps-resolver/src/tests.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rspacquet/crates/resolving-npm-resolver/src/npm_resolver.rspacquet/crates/package-manager/src/install_package_from_registry/tests.rspacquet/crates/package-manager/src/install_package_from_registry.rspacquet/crates/package-manager/src/install_without_lockfile.rs
🔇 Additional comments (15)
pacquet/crates/resolving-resolver-base/Cargo.toml (1)
17-20: LGTM!pacquet/crates/resolving-resolver-base/src/resolve.rs (1)
15-15: LGTM!Also applies to: 20-49, 223-229
pacquet/crates/resolving-resolver-base/src/lib.rs (1)
30-33: LGTM!pacquet/crates/resolving-resolver-base/src/tests.rs (1)
1-1: LGTM!Also applies to: 6-7, 137-137
Cargo.toml (1)
46-46: LGTM!pacquet/crates/resolving-npm-resolver/src/npm_resolver.rs (1)
34-37: LGTM!Also applies to: 347-349
pacquet/crates/resolving-npm-resolver/src/npm_resolver/tests.rs (1)
118-118: LGTM!Also applies to: 152-152, 250-250, 278-278
pacquet/crates/resolving-default-resolver/src/tests.rs (1)
1-1: LGTM!Also applies to: 3-4, 18-20
pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs (1)
145-145: LGTM!pacquet/crates/resolving-deps-resolver/src/tests.rs (1)
1-1: LGTM!Also applies to: 5-7, 46-47
pacquet/crates/resolving-tarball-resolver/Cargo.toml (1)
1-27: LGTM!pacquet/crates/resolving-tarball-resolver/src/lib.rs (1)
1-27: LGTM!pacquet/crates/resolving-tarball-resolver/src/tarball_resolver/tests.rs (1)
1-154: LGTM!pacquet/crates/package-manager/src/install_package_from_registry/tests.rs (1)
155-159: LGTM!pacquet/crates/package-manager/src/install_without_lockfile.rs (1)
380-389: 🏗️ Heavy liftNo action needed—the comment correctly documents the actual invariant.
The code's assumption is accurate and already explicit: install_without_lockfile uses only
NpmResolver, which producesname@versionIDs, so the.expect()is safe. The comment at lines 380-383 documents this npm-only path clearly and correctly. TarballResolver exists in the codebase but is not wired into the without-lockfile resolver chain—DefaultResolver's chain remains empty pending future per-protocol wiring in subsequent PRs. There is no forward-compatibility risk with the current code.
Adds pacquet-resolving-tarball-resolver, the Rust port of resolving/tarball-resolver/src/index.ts. The new crate claims any WantedDependency whose bare specifier starts with `http://` or `https://`, normalizes the URL through `reqwest::Url::parse`, runs a HEAD pre-flight that follows redirects, and stores the post-redirect URL in the resolution when the response carries `cache-control: immutable`. Mutable responses keep the normalized request URL. Integrity stays None at resolve time, matching upstream (integrity is stamped later in package-requester). To make the seam fit, ResolveResult.id is now an opaque `PkgResolutionId(String)` newtype in resolver-base mirroring upstream's branded string at core/types/misc.ts:59. PkgNameVer was a poor fit because tarball ids are URLs and git ids are `repo#commit` — not name@version. NpmResolver round-trips the existing PkgNameVer through PkgResolutionId::from(string); the npm-only install paths in package-manager parse the id back to PkgNameVer at their boundary (safe because the npm resolver stamps that shape). The deps-resolver alias fallback drops its `.id.name` access since the id is opaque now. Test coverage in the new crate (7 tests, mockito): http(s) claim vs decline, mutable vs immutable response, immutable-after-redirect follow, resolve_latest for http(s) vs non-http(s).
… params Dylint's perfectionist::single-letter-closure-param rejects |v|; rename to |header| in the cache-control header check.
…chain Insert TarballResolver after the GitResolver in install_without_lockfile's DefaultResolver chain so http(s):// bare specifiers actually route through the new resolver. Order mirrors upstream's chain (npm → git → tarball → local/...).
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
pacquet/crates/resolving-resolver-base/src/resolve.rs (1)
14-15: ⚡ Quick winUse serde conversion attrs for this branded string.
PkgResolutionIdis a public brand, so#[serde(transparent)]skips the explicit string conversion boundary the repo expects here. Please serialize viaStringand deserialize throughTryFrom<String>/Into<String>instead.♻️ Suggested change
-use derive_more::{Display, From}; +use derive_more::{Display, From, Into}; @@ -#[derive(Debug, Display, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, From)] -#[serde(transparent)] +#[derive(Debug, Display, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, From, Into)] +#[serde(try_from = "String", into = "String")] pub struct PkgResolutionId(String);As per coding guidelines, "Match upstream serde behavior for branded types that cross JSON, YAML, or INI boundaries. Use
#[serde(try_from = "String")]for deserialization and#[serde(into = "String")]for serialization."Also applies to: 33-35
🤖 Prompt for 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. In `@pacquet/crates/resolving-resolver-base/src/resolve.rs` around lines 14 - 15, Replace #[serde(transparent)] on the branded string type PkgResolutionId with explicit serde conversion attributes so serialization goes through String and deserialization uses TryFrom<String>: annotate PkgResolutionId with #[serde(try_from = "String", into = "String")] and ensure the type implements TryFrom<String> for deserialization and Into<String>/From<&str> for serialization; make the same change for the other branded types referenced around lines 33-35 so all public branded string types serialize via String and deserialize via TryFrom<String>.
🤖 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/resolving-tarball-resolver/src/tarball_resolver.rs`:
- Around line 99-101: The claimed result sets alias: None which drops the
requested install name for tarball deps; update the code that constructs the
claimed result (the block with resolved_via and normalized_bare_specifier) to
forward the requested alias from wanted_dependency by using
wanted_dependency.alias.clone() (or equivalent) instead of None so the original
spec alias (e.g., "foo" for "https://.../bar.tgz") is preserved downstream.
---
Nitpick comments:
In `@pacquet/crates/resolving-resolver-base/src/resolve.rs`:
- Around line 14-15: Replace #[serde(transparent)] on the branded string type
PkgResolutionId with explicit serde conversion attributes so serialization goes
through String and deserialization uses TryFrom<String>: annotate
PkgResolutionId with #[serde(try_from = "String", into = "String")] and ensure
the type implements TryFrom<String> for deserialization and
Into<String>/From<&str> for serialization; make the same change for the other
branded types referenced around lines 33-35 so all public branded string types
serialize via String and deserialize via TryFrom<String>.
🪄 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: aee58a3a-d3b3-4323-ad55-e218d6ccd4f4
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
Cargo.tomlpacquet/crates/resolving-resolver-base/src/resolve.rspacquet/crates/resolving-tarball-resolver/Cargo.tomlpacquet/crates/resolving-tarball-resolver/src/lib.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver/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). (8)
- GitHub Check: Lint and Test (ubuntu-latest)
- GitHub Check: Lint and Test (windows-latest)
- GitHub Check: Lint and Test (macos-latest)
- GitHub Check: Dylint
- GitHub Check: Code Coverage
- GitHub Check: Run benchmark on ubuntu-latest
- GitHub Check: Run benchmark on ubuntu-latest
- GitHub Check: Compile & Lint
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs
📄 CodeRabbit inference engine (pacquet/AGENTS.md)
pacquet/**/*.rs: When porting a function that firespnpm:<channel>events throughglobalLogger,logger.debug(), orstreamParser.write(), mirror the call site, payload, and ordering so the reporter parses pacquet's NDJSON the same way it parses pnpm's.
Declare a newtype wrapper for branded string types. Do not collapse the brand into a plainStringor&str.
If upstream always validates before construction, validate in pacquet's wrapper too. The wrapper must construct only viaTryFrom<String>and/orFromStr. Do not provide an infallible public constructor.
If upstream never validates, just brand for type-safety. Expose an infallibleFrom<String>(andFrom<&str>when convenient).
If upstream occasionally constructs without validation, exposefrom_str_uncheckedas an escape hatch alongside the validating constructor.
Match upstream serde behavior for branded types that cross JSON, YAML, or INI boundaries. Use#[serde(try_from = "String")]for deserialization and#[serde(into = "String")]for serialization.
Use#[derive(derive_more::From)]and#[derive(derive_more::Into)]for mechanical conversion impls. Fall back to manualimplonly when conversion needs custom logic.
String-literal unions should becomeenums, not newtype wrappers. Model closed sets of valid string values as enums.
Template literal types should be treated as branded strings with validation discipline from rules 2-5.
Choose owned vs. borrowed parameters to minimize copies. Widen to the most encompassing type (&Pathover&PathBuf,&strover&String) when it doesn't force extra copies.
PreferArc::clone(&x)/Rc::clone(&x)overx.clone()for reference-counted types, so the cost is visible at the call site.
Follow Rust API Guidelines for naming conventions.
Do not use star imports inside module bodies. Writeuse super::{Foo, bar}instead ofuse super::*;. Two forms stay allowed: external-crate preludes likeuse rayon::prelude::*;and root-of-module re-...
Files:
pacquet/crates/resolving-tarball-resolver/src/lib.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver/tests.rspacquet/crates/resolving-resolver-base/src/resolve.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs
🧠 Learnings (1)
📚 Learning: 2026-05-20T19:40:55.051Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11774
File: pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs:0-0
Timestamp: 2026-05-20T19:40:55.051Z
Learning: In the pacquet Rust code, ensure the semver implementation uses the `node-semver` crate (not `nodejs-semver`). `node-semver`’s public API does not include a `satisfies_with_prerelease`-style method; prerelease-tolerant matching should be implemented inline by first calling `Range::satisfies`, and when it rejects a prerelease version, retry matching against a stripped `MAJOR.MINOR.PATCH` base of the prerelease version.
Applied to files:
pacquet/crates/resolving-tarball-resolver/src/lib.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver/tests.rspacquet/crates/resolving-resolver-base/src/resolve.rspacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs
🔇 Additional comments (5)
pacquet/crates/resolving-resolver-base/src/resolve.rs (1)
238-248: LGTM!Cargo.toml (1)
34-48: LGTM!pacquet/crates/resolving-tarball-resolver/Cargo.toml (1)
1-26: LGTM!pacquet/crates/resolving-tarball-resolver/src/lib.rs (1)
1-26: LGTM!pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs (1)
24-81: LGTM!Also applies to: 107-122
…ync lockfile - Echo `wanted_dependency.alias` on the `ResolveResult` so a spec like `"foo": "https://.../bar.tgz"` preserves `foo` as the install name downstream. Matches the npm and git resolvers' convention even though upstream TS doesn't surface alias on `ResolveResult` (downstream consumers fall back to `wantedDependency.alias` over there). - Drop a stray blank line in resolve.rs that cargo fmt rejected. - Record the new `package-manager -> resolving-tarball-resolver` edge in Cargo.lock so `cargo build --locked` succeeds on CI.
Summary
pacquet-resolving-tarball-resolver, the Rust port ofresolving/tarball-resolver/src/index.ts. Claims anyWantedDependencywhose bare specifier starts withhttp://orhttps://, normalizes the URL throughreqwest::Url::parse, runs a HEAD pre-flight that follows redirects, and stores the post-redirect URL in the resolution when the response carriescache-control: immutable. Mutable responses keep the normalized request URL.name_ver: Noneon theResolveResultandintegrity: Noneon theTarballResolution. Tarball URLs carry noname@versionat resolve time — the canonical name/version come from the manifest after the tarball is fetched. Integrity is computed later bypackage-requester. Matches upstream.TarballResolverinto theinstall_without_lockfileresolver chain after the npm and git resolvers. Order mirrors upstream'screateResolverchain:npm → git → tarball → local/runtimes/...(those slot in as their crates land).This PR previously also introduced
PkgResolutionIdinresolving-resolver-base, but that landed first via the git-resolver port in #11779.Test plan
just check— workspace passesjust test— 434 tests pass across the affected crates (7 new inpacquet-resolving-tarball-resolver: http(s) claim vs decline, mutable vs immutable response, immutable-after-redirect follow,resolve_latestfor http(s) vs non-http(s))just lint— no clippy warningsjust fmt— cleanWritten by an agent (Claude Code, claude-opus-4-7).
Summary by CodeRabbit