mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-19 20:22:21 -04:00
cb6f9e58c3efdfd2215e9554c6fece30d34ba3f2
select_platform_variant + PlatformSelector (#437 slice B) (#466)
* feat(lockfile): select_platform_variant + PlatformSelector (#437 slice B) Add the variant-picking logic for `VariationsResolution` ahead of Slice D's install-pipeline dispatch: - `PlatformSelector { os, cpu, libc: Option<String> }` mirrors upstream's [`PlatformSelector`](https://github.com/pnpm/pnpm/blob/94240bc046/resolving/resolver-base/src/index.ts#L78-L83). The `libc` tri-state encodes pnpm's `string | null | undefined` shape: `None` (host doesn't care about libc — macOS/Windows/BSD) and `Some("glibc")` collapse to the same matching arm (variant must have no `libc:` annotation); `Some("musl")` requires an exact `libc: "musl"` annotation so the glibc default doesn't silently win on a musl host. - `select_platform_variant(variants, selector)` ports [`selectPlatformVariant`](https://github.com/pnpm/pnpm/blob/94240bc046/resolving/resolver-base/src/index.ts#L92-L98). Iterates `variants` in declaration order and returns the first variant whose `targets[]` contains an `(os, cpu, libc)` triple matching the selector. Targets-array scan is linear because real archives ship 1–3 target entries per variant; quadratic cost is immaterial. - `libc_matches(variant_libc, requested_libc)` is the asymmetric helper from [`libcMatches`](https://github.com/pnpm/pnpm/blob/94240bc046/resolving/resolver-base/src/index.ts#L100-L107). Crate-private so the matching policy isn't part of the public API. Lives in `pacquet-lockfile` next to the variant types (mirrors upstream's `resolver-base` package boundary). The host-platform side (constructing the `PlatformSelector` from `pacquet-graph-hasher`'s existing `host_platform/arch/libc` helpers) lands at the install dispatcher in Slice D — keeps `pacquet-lockfile` free of the `graph-hasher` dep and lets tests drive the picker with synthetic hosts. Tests: first-match wins, multi-target variant matches any host triple, no-match returns `None`, musl-host rejects glibc-default variant, musl-host matches musl-annotated variant, and a six-row `libc_matches` truth table (None / "glibc" / "musl" / unknown-future-libc on both sides) pinning the asymmetric contract from upstream. Part of #437. --- Written by an agent (Claude Code, claude-opus-4-7). * docs: refresh stale references + add declaration-order tie-breaker test Two follow-ups from Copilot review on PR #466: - `resolution.rs:152-154` claimed "the variant picker checks at runtime that the resolved inner is atomic", but `select_platform_variant` does not. Reword to describe the actual contract: pacquet's `PlatformAssetResolution.resolution` is typed as the full `LockfileResolution` for serde uniformity, and the lockfile is trusted to honor upstream's atomic-inner invariant. No infinite-recursion risk because the install dispatcher doesn't call back into `select_platform_variant` for non-`Variations` inputs. - `resolution.rs:169` referenced `pick_variant` in `pacquet-package-manager`, but the picker actually lives in this module as `select_platform_variant`. Updated the pointer. - `pick_returns_first_when_multiple_variants_match` test: two variants both list the same `(darwin, arm64)` target; the test asserts the first one wins, pinning the `Array.prototype.find` semantics. Pnpm-written lockfiles can rely on declaration order (e.g., listing a preferred build before a fallback) — without this test, a future refactor that switched the iteration to a triple-keyed `BTreeMap` would silently break that. No behavior change; doc-comment text + test addition. --- Written by an agent (Claude Code, claude-opus-4-7).
Description
Languages
Rust
61.2%
TypeScript
38.3%
JavaScript
0.4%