bazelbuild / bazelbuild/rules_rust
Bug: crates_vendor with cargo patch fails due to incorrect path resolution in local_crate_mirror.bzl
- Dominant language
- Starlark
- Stars
- 843
- Forks
- 651
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 15
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
1. Clone the repository: `git clone https://github.com/ashi009/rules_rust_local_mirror_bug.git`
2. Run: `bazel run //third_party/rust:update-repo` (succeeds)
3. Run: `bazel build //third_party/rust/crates:base64` (fails with error above)
### Key Configuration Files
**Cargo.toml** with local patch:
```toml
[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:
```bzl
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:
```bzl
# 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 root
```
When `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:
```bzl
# 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_vendor` with `mode = "remote"`
- `Cargo.toml` with `[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.
Contributor guide
Assessment
This issue has not been assessed yet.