Repository navigation
Fix hosted/vendored cargo floor reads (#653, #651) - #1429
Mikola Lysenko (mikolalysenko) wants to merge 7 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Hosted cargo patches are served from a sparse registry, which cargo only loads from 1.68. A project that declared an older cargo in rust-version or rust-toolchain[.toml] got "success" from scan --mode hosted, and every build then failed with "usage of sparse registries requires -Z sparse-registry". Hosted scan now refuses each cargo patch there with redirect_cargo_old_cargo, writes nothing, and points at --mode vendored (#653). The declared floor now has one reader in formats/cargo, shared with the vendored multi-version warning. It also follows rust-version.workspace = true to [workspace.package], so a standard modern workspace no longer gets a false "declares no rust-version" warning when two versions of a crate are vendored (#651). Assisted-by: Claude Code:claude-opus-5-5
Adds an e2e shape where rust-version = "1.67" makes scan --mode hosted refuse the cargo patch and leave the project untouched, and an engine test that the toolchain files reach the planner. Assisted-by: Claude Code:claude-opus-5-5
Review follow-ups for the hosted cargo floor: - the legacy rust-toolchain file wins over rust-toolchain.toml when both exist, as it does for rustup - a dated nightly-/beta-YYYY-MM-DD channel maps to its release train, so a nightly from before sparse registries is refused too - a workspace member's rust-version counts, since one cargo builds the whole lock - the refusal names the rollback that drops pins an earlier run wrote - vendored reads the toolchain files only when Cargo.toml says nothing - the hosted candidate-file list test knows the toolchain files Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
The hosted engine records an unreadable in-memory rust-toolchain as an empty file. Because rustup prefers the legacy file, that blank placeholder hid rust-toolchain.toml's channel, and a project pinned below cargo 1.68 was still redirected. A blank legacy file now names no toolchain, so the TOML file's channel is used. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
Ready for review (burn-down agent)
Generated by Claude Code |
Final review: needs a decision before this can be briefedThe question: when a workspace pins its toolchain, should a member's low Where:
Example: root
Options:
I lean towards 1, since the PR's own reasoning is about the one cargo that builds the lock. It's a product call, though, so I'm leaving the code as is. Non-blocking notes:
Otherwise checked:
Labelled Generated by Claude Code |
…red-floor # Conflicts: # docs/ecosystems.md
Main's #1420 added a restored field to the e2e Shape struct; the declared-cargo-floor test this branch adds predates it and no longer compiled after merging main. Co-Authored-By: Claude <noreply@anthropic.com>
|
Merged
Generated by Claude Code |
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 45b4799. Configure here.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #653
Fixes #651
What it does
scan --mode hostedpoints a Cargo patch at aper-patch
sparse+registry, and cargo only loads those from 1.68.A project that declared an older cargo used to get
success, andevery build then failed with
usage of sparse registries requires -Z sparse-registry. Now each Cargo patch in such a project is refusedwith
redirect_cargo_old_cargo. Nothing is written, and the messagepoints at
--mode vendored(which builds on 1.41+). If an earlier runalready wrote pins, the message names the
socket-patch rollback pkg:cargo/<name>@<version>that removes them. A project that declaresno floor, or a rolling channel, redirects as before.
rust-version.workspace = truenow reads[workspace.package]. A standard modern workspace no longer gets afalse
cargo_multi_version_old_cargo("declares norust-version")warning.
Root cause
The project's declared cargo floor was read by one private helper in
vendor/cargo.rs, and only vendored mode called it. The helper took[package].rust-versionwith.get(), so the{ workspace = true }table blocked the
[workspace.package]fallback (#651). Hosted modenever asked for the floor at all (#653).
The fix is one pure reader,
formats/cargo/floor.rs, that both modescall. It reads the floor the way cargo and rustup do:
rust-version, with.workspace = trueinheritance;pins, because one cargo builds the whole lock;
rust-toolchainfile overrust-toolchain.tomlwhen both exist (rustup's own order);nightly-/beta-YYYY-MM-DDchannel maps to its release train(stable ships every 6 weeks; 1.68 shipped on 2023-03-09).
rust-toolchain.tomlandrust-toolchainare new read-only(
HOSTED | PRESENCE_ONLY) rows informats/registry.rs. The hostedplanner sees them, but no rewriter edits them and they never trigger the
symlinked-read refusal. The contract and
docs/ecosystems.mdnow givethe hosted cargo floor.
Not covered: toolchain files in ancestor directories, which rustup also
walks to. Hosted mode reads only the project root.
Tests
Red first, on the unchanged code (
cargo test -p socket-patch-core --lib -- cargo_declared_floor_below_sparse_support_is_refused a_workspace_inherited_rust_version_is_the_declared_floor): 2 failed.For example, the hosted test got
left: [],right: ["redirect_cargo_old_cargo"]. Both are green after the fix.patch::redirect::tests::cargo_declared_floor_below_sparse_support_is_refused:rust-version1.67 (also CRLF), an inherited 1.60,rust-toolchain.toml1.67.1,rust-toolchain1.56 and a member's 1.64 are each refused with nothing written. The test also checks the rollback hint over existing pins. 1.68 and an undeclared floor still redirect.e2e_redirect_cargo_shapes::cargo_hosted_refuses_a_project_declaring_cargo_below_1_68: the real CLIscan --mode hostedrefuses, leaves the project byte-identical, andcargo fetch --lockedstill works.hosted::engine::tests::the_cargo_toolchain_files_are_read_as_advisory_inputvendor::cargo::tests::a_workspace_inherited_rust_version_is_the_declared_floor: no multi-version warning for an inherited 1.70.formats::cargo::floor::tests::*: spellings, BOM, precedence, dated channels, member inheritance.Local runs on e482907 (plus the blank-toolchain fix in bbd74db, re-tested with the floor and hosted unit tests):
cargo fmt --all -- --check: clean.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test -p socket-patch-core --all-features(lib and everyintegration test): all pass except 4 permission tests (
copy_treesymlinked root,
vlt_healunremovable lock, poetry/requirementswrite-failure). Those fail the same way on
mainbecause this sandboxruns as uid 0, which ignores chmod.
cargo test -p socket-patch-cli --all-features --lib --bins: 913passed.
SOCKET_PATCH_CARGO_E2E_REQUIRED=1:e2e_redirect_cargo_build22,e2e_redirect_cargo_shapes31,e2e_vendor_cargo_build39,mode_migration_cargo29. All pass.cargo test --workspacelocally: its 150+ CLItest binaries need more disk than this session allows. CI runs the rest.
The npm, PyPI and gem wrappers have no cargo logic, so they needed no
change.
/code-review highraised 7 findings. I fixed 6 in a follow-upcommit; the 7th (ancestor toolchain files) is out of scope, as noted above.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Pr4cZSSSuEsv1rzzGoxTpg
Note
Medium Risk
Changes hosted Cargo redirect eligibility and shared floor parsing affect when pins are written; mistakes could block valid projects or still allow broken sparse pins, but behavior is fail-closed with tests and docs.
Overview
Introduces a shared
formats/cargo/floorreader for the cargo version a project declares (rust-version, workspace inheritance, rootrust-toolchain/rust-toolchain.toml), and wires it into both vendored and hosted Cargo paths.Hosted (
scan --mode hosted) now refuses sparse-registry redirects when that floor is below cargo 1.68, emittingredirect_cargo_old_cargowith no lock/manifest writes (sparse registries need 1.68+). Existing pins get asocket-patch rollbackhint in the message. Hosted discovery reads toolchain files as advisory input only.Vendored reuses the same floor logic so
rust-version.workspace = truecorrectly inherits[workspace.package], fixing falsecargo_multi_version_old_cargowarnings on modern workspaces.Contract docs (
CLI_CONTRACT.md,docs/ecosystems.md) and e2e/unit tests cover the new refusal and inheritance behavior.Reviewed by Cursor Bugbot for commit 45b4799. Configure here.
Generated by Claude Code