Skip to content

Fix Cargo source replacement being ignored (#338, #455) - #1420

Open
Mikola Lysenko (mikolalysenko) wants to merge 7 commits into
mainfrom
agent/fix-cargo-source-replacement
Open

Mikola Lysenko (mikolalysenko) wants to merge 7 commits into
mainfrom
agent/fix-cargo-source-replacement

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

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 vendor project builds from, and guessed wrong.

The new pure module formats/cargo/source_replacement.rs holds 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

Issue Regression tests (red before the fix → green)
#338 shape 1 (custom dir) crawler_cargo_e2e::custom_vendor_dir_named_by_source_replacement_is_crawled; real cargo: e2e_safety_cargo_build::apply_patches_a_custom_named_vendor_dir
#338 shape 2 (member) crawler_cargo_e2e::workspace_root_source_replacement_applies_to_a_member; real cargo: e2e_safety_cargo_build::apply_from_a_member_patches_the_workspace_vendor_dir
#338 shape 3 + non-cargo vendor/ crawler_cargo_e2e::unwired_vendor_dir_falls_back_to_the_registry_cache
#338 fresh checkout / missing dir crawler_cargo_e2e::missing_replacement_directory_crawls_nothing
#338 $CARGO_HOME config crawler_cargo_e2e::cargo_home_source_replacement_is_honoured
#455 hosted redirect patch::redirect::tests::cargo_directory_source_replacement_is_refused (both config spellings, CRLF, a multi-hop chain; mirror control still redirects)
#455 vex reads the wrong copy covered by the crawler change: vex discovers through the same crawler (vex_consumed.rs); the crawler tests above
resolver formats::cargo::source_replacement::tests (8 unit tests)

Red before the fix: all 5 new crawler_cargo_e2e tests failed on origin/main
code. The hosted test failed with the Socket registry pin written into
Cargo.toml, Cargo.lock and .cargo/config.toml.

Fixtures that staged a bare vendor/ and relied on the old guess now write the
.cargo/config.toml that cargo vendor asks 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)

/code-review high: findings not fixed here

  • Hosted mode reads only the project's own .cargo/config* (the
    rewriter is pure over the project's files). A directory replacement set
    only in an ancestor or ~/.cargo/config.toml is not seen by hosted mode.
    Hosted cargo scan in a cargo vendor project reports success but breaks every fresh cargo build --frozen --offline, and VEX then omits the patch #455's repro and cargo vendor's printed snippet both put it in the
    project config. Plumbing outer configs into the hosted engine (like
    yarn's OuterYarnMirror) is a follow-up.
  • Vendored mode's is_vendored (vendor/cargo.rs) still probes
    <root>/vendor for its already_vendored_in_tree refusal. That is a
    fail-closed refusal with its own contract tests, and neither issue
    reports it. Follow-up.
  • Upgrade from a release that patched an unwired vendor/. Cargo never
    built from that copy, so the patch had no effect. rollback now looks
    where cargo builds. The stray edit in the unused vendor/ copy stays.
  • local-registry / git replacements are Other and keep the
    registry-cache crawl. Cargo unpacks local-registry crates into
    registry/src, which is what the crawler reads.
  • Lexical .. in --cwd and per-key (not per-table) merge of
    conflicting [source.x] definitions
    : cargo itself rejects the latter
    ("more than one source location"). absolute() is used rather than
    canonicalize() so reported paths keep matching the cwd the user gave
    (macOS /var → /private/var).
  • A third config-chain walker / no memo. vendor::cargo_config::read_config_chain
    is [patch]-specific (it drops files with no patch entries). Unifying the
    walkers 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

Assisted-by: Claude Code:claude-opus-5-5
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
Adds real-cargo e2e coverage for a custom-named vendor directory and
for apply run from a workspace member, and documents how agent mode
finds the directory source and the new hosted refusal code.

Refs #338, #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
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 12, 2026 07:33
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

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
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants