- 
                Notifications
    
You must be signed in to change notification settings  - Fork 518
 
Description
Bug: crates_vendor with cargo patch fails due to incorrect path resolution in local_crate_mirror.bzl
Summary
When using crates_vendor with mode = "remote" and Cargo.toml with [patch.crates-io] sections that reference local vendor directories, the build fails with a path resolution error in local_crate_mirror.bzl. The issue is on line 9 where repository_ctx.path(path) resolves relative to the external repository instead of the workspace root.
Environment
- rules_rust version: 0.55.0 (latest)
 - Bazel version: 7.4.1 (via Bazelisk)
 - Operating system: macOS
 - Rust toolchain: 1.82.0
 
Error Message
Error in readdir: can't readdir(), not a directory: /private/var/tmp/_bazel_xiaoyishi/d2c3080cf0842704a4fcd706f6251fe8/external/crate_index__base64-0.22.1/third_party/rust/vendor/base64-0.22.1
Minimal Reproduction
Repository: https://github.com/ashi009/rules_rust_local_mirror_bug
Steps to Reproduce
- Clone the repository: 
git clone https://github.com/ashi009/rules_rust_local_mirror_bug.git - Run: 
bazel run //third_party/rust:update-repo(succeeds) - Run: 
bazel build //third_party/rust/crates:base64(fails with error above) 
Key Configuration Files
Cargo.toml with local patch:
[package]
name = "rules_rust_local_mirror_bug"
version = "0.1.0"
edition = "2021"
[dependencies]
base64 = "0.22.1"
[patch.crates-io]
base64 = { path = "third_party/rust/vendor/base64-0.22.1" }third_party/rust/BUILD.bazel with crates_vendor:
crates_vendor(
    name = "crates",
    annotations = {},
    cargo_lockfile = "//:Cargo.lock",
    manifests = ["//:Cargo.toml"],
    mode = "remote",
    repository_name = "third_party_rust",
    tags = ["manual"],
    vendor_path = "third_party/rust/vendor",
)Root Cause Analysis
The bug is in crate_universe/private/local_crate_mirror.bzl line 9:
# Current (broken) code:
path = repository_ctx.path(repository_ctx.attr.path)
# The issue: repository_ctx.path(path) resolves relative to external repository
# but the path "third_party/rust/vendor/base64-0.22.1" should resolve relative to workspace rootWhen crates_vendor processes the cargo patch with path = "third_party/rust/vendor/base64-0.22.1", it tries to resolve this path within the external repository context instead of the workspace root, leading to the incorrect path resolution.
Proposed Fix
Replace the relative path resolution with workspace root resolution:
# Fixed code:
path = repository_ctx.workspace_root.get_child(repository_ctx.attr.path)This ensures that cargo patch paths are resolved relative to the workspace root where the Cargo.toml file is located, matching cargo's expected behavior.
Impact
This bug affects any project using:
crates_vendorwithmode = "remote"Cargo.tomlwith[patch.crates-io]sections pointing to local paths- Local vendor directories for dependency patching
 
This is a common pattern for organizations that need to patch dependencies locally while using crates_vendor for remote BUILD file generation.
Workaround
Currently, there is no known workaround. The issue prevents using local cargo patches with crates_vendor in remote mode.