Repository navigation
Fix Cargo source replacement being ignored (#338, #455) - #1420
Open
Mikola Lysenko (mikolalysenko) wants to merge 7 commits into
Open
Mikola Lysenko (mikolalysenko) wants to merge 7 commits into
Mikola Lysenko (mikolalysenko) wants to merge 7 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
This was referenced Oct 12, 2026
Agent-mode apply, scan and vex looked for a `cargo vendor` tree only at `<cwd>/vendor`. A custom vendor directory, a workspace root's vendor directory seen from a member, or a `vendor/` that no config wires all made apply patch a copy cargo ignores while reporting success, and made vex judge the wrong copy. The crawler now follows the `[source.crates-io] replace-with` chain of every cargo config cargo reads (each ancestor's `.cargo/config*`, then `$CARGO_HOME`'s) and crawls the directory source it ends on, resolved the way cargo resolves config paths. Without a directory replacement it crawls the registry cache, and a configured directory that is missing yields nothing rather than a copy cargo doesn't read. Refs #338, #455 Assisted-by: Claude Code:claude-opus-5-5
A project whose .cargo/config replaces crates.io with a directory source (`cargo vendor`) builds every crate from that directory and never reads a registry. `scan --mode hosted` still pinned the crate to a per-patch Socket registry and reported success, so every fresh `cargo build --frozen --offline` failed with "no matching package". The hosted cargo rewriter now follows the project config's `[source.crates-io] replace-with` chain and, when it ends on a directory source, skips every cargo dependency with nothing written and a `redirect_cargo_directory_source` warning that points at agent mode. A registry mirror replacement is still redirected. Refs #455 Assisted-by: Claude Code:claude-opus-5-5
Three fixtures staged a bare `vendor/` with no source replacement and relied on the crawler treating it as cargo's source. They now write the `.cargo/config.toml` that `cargo vendor` asks for, and the resolver strips a BOM through the shared text helper. Refs #338 Assisted-by: Claude Code:claude-opus-5-5
Rollback and prune look for an agent-mode patch left in the shared registry cache when the project crawl searches only a `cargo vendor` directory. That check still looked for `<cwd>/vendor`, so a custom or workspace-root vendor directory skipped it, and an unwired `vendor/` triggered it needlessly. It now asks the crawler for the directory source the project's cargo configs name. The hosted refusal's message now says why a Socket registry pin breaks an offline vendored build, instead of claiming cargo never reads it. Refs #338, #455 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 12, 2026 07:33
Collaborator
Author
|
BugBot review Generated by Claude Code |
The dispatch, all-ecosystem rollback and scan-scope tests staged a bare `vendor/` crate tree and relied on the crawler treating it as cargo's source. They now write the source replacement `cargo vendor` asks for, so they keep exercising the vendored-crate path. Refs #338 Assisted-by: Claude Code:claude-opus-5-5
Collaborator
Author
|
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 9083269. Configure here.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #338
Fixes #455
Summary
socket-patch never read Cargo's source replacement
(
[source.crates-io] replace-with = "…"→[source.<name>] directory = "…"),so it guessed where a
cargo vendorproject builds from, and guessed wrong.cargo vendoruses a custom directory (or apply runs from a workspace member), yet reports success and VEX attests not_affected #338, Hosted cargo scan in acargo vendorproject reports success but breaks every freshcargo build --frozen --offline, and VEX then omits the patch #455 symptom 2). The crawler hard-coded<cwd>/vendor. With a custom vendor directory, with a workspace-rootvendor directory seen from a member, or with an unwired or non-cargo
vendor/,applypatched a copy cargo doesn't build from and reportedsuccess, and
vexjudged the wrong copy. The crawler now follows thereplace-withchain of every config cargo reads (each ancestor's.cargo/config*, then$CARGO_HOME's) and crawls the directory source itends on, resolved the way cargo resolves config paths (against the parent
of
.cargo/). Without a directory replacement it crawls the registrycache. A configured directory that is missing yields nothing, never a copy
cargo ignores.
find_cargo_copiesdecided that a vendordirectory hides the registry cache by checking
<cwd>/vendor. It now asksthe crawler for the configured directory source.
cargo vendorproject reports success but breaks every freshcargo build --frozen --offline, and VEX then omits the patch #455 symptom 1). When the project's.cargo/config*replaces crates.io with a directory source, every cargo dependency is
skipped with nothing written and a new additive
redirect_cargo_directory_sourcewarning that points at agent mode. Aregistry-mirror replacement is still redirected.
The new pure module
formats/cargo/source_replacement.rsholds the resolver(
crates_io_source) and the config file walk (config_layer_paths).CLI_CONTRACT.md and docs/ecosystems.md are updated.
Per-issue checklist
crawler_cargo_e2e::custom_vendor_dir_named_by_source_replacement_is_crawled; real cargo:e2e_safety_cargo_build::apply_patches_a_custom_named_vendor_dircrawler_cargo_e2e::workspace_root_source_replacement_applies_to_a_member; real cargo:e2e_safety_cargo_build::apply_from_a_member_patches_the_workspace_vendor_dirvendor/crawler_cargo_e2e::unwired_vendor_dir_falls_back_to_the_registry_cachecrawler_cargo_e2e::missing_replacement_directory_crawls_nothing$CARGO_HOMEconfigcrawler_cargo_e2e::cargo_home_source_replacement_is_honouredpatch::redirect::tests::cargo_directory_source_replacement_is_refused(both config spellings, CRLF, a multi-hop chain; mirror control still redirects)vex_consumed.rs); the crawler tests aboveformats::cargo::source_replacement::tests(8 unit tests)Red before the fix: all 5 new
crawler_cargo_e2etests failed onorigin/maincode. The hosted test failed with the Socket registry pin written into
Cargo.toml,Cargo.lockand.cargo/config.toml.Fixtures that staged a bare
vendor/and relied on the old guess now write the.cargo/config.tomlthatcargo vendorasks for (6 crawler unit/oracle tests,crawlers_empty_paths_e2e,e2e_cargo×2,e2e_vendor_cargo_build's #336"behind a cargo vendor dir" rollback). None of their assertions were loosened.
Local evidence (on 30aa879; 9083269 adds 3 fixture wirings, CI green)
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --all-features: all pass except 4read-only-permission tests that can't fail when run as root in this sandbox
(
copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_…,pypi_requirements::wire_failure_…).These are unrelated to this diff.
socket-patch-cli:--lib,e2e_cargo,in_process_cargo_apply,mode_migration_cargo,e2e_redirect_cargo_build,e2e_redirect_cargo_shapes,e2e_vendor_cargo_build(incl. both Cargo rollback after an agent→vendored takeover leaves the shared registry cache patched, reports success, and deletes the revert blobs #336 rollback tests with real cargo),vex_terminal_output,in_process_rollback_hosted,in_process_vendor,covgap_commands_scan_mod: passcargo test -p socket-patch-cli --all-features --test e2e_safety_cargo_build -- --ignored:10/10 pass with real cargo 1.93.1, including the two new Agent-mode cargo apply patches the wrong copy when
cargo vendoruses a custom directory (or apply runs from a workspace member), yet reports success and VEX attests not_affected #338 shapescargo test --workspacecouldn't finish locally: the sandbox ranout of disk building every CLI test binary. CI runs it.
npm/,pypi/,gem/) only dispatch to the binary, so noparallel change is needed.
/code-review high: findings not fixed here
.cargo/config*(therewriter is pure over the project's files). A directory replacement set
only in an ancestor or
~/.cargo/config.tomlis not seen by hosted mode.Hosted cargo scan in a
cargo vendorproject reports success but breaks every freshcargo build --frozen --offline, and VEX then omits the patch #455's repro andcargo vendor's printed snippet both put it in theproject config. Plumbing outer configs into the hosted engine (like
yarn's
OuterYarnMirror) is a follow-up.is_vendored(vendor/cargo.rs) still probes<root>/vendorfor itsalready_vendored_in_treerefusal. That is afail-closed refusal with its own contract tests, and neither issue
reports it. Follow-up.
vendor/. Cargo neverbuilt from that copy, so the patch had no effect.
rollbacknow lookswhere cargo builds. The stray edit in the unused
vendor/copy stays.Otherand keep theregistry-cache crawl. Cargo unpacks local-registry crates into
registry/src, which is what the crawler reads...in--cwdand per-key (not per-table) merge ofconflicting
[source.x]definitions: cargo itself rejects the latter("more than one source location").
absolute()is used rather thancanonicalize()so reported paths keep matching the cwd the user gave(macOS
/var→/private/var).vendor::cargo_config::read_config_chainis
[patch]-specific (it drops files with no patch entries). Unifying thewalkers is a refactor for its own PR. The extra reads are at most a handful
of small files per crawl.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TUHnkhA7W5gHh21jSMkY7P
Generated by Claude Code