cargo: 'cargo metadata' fails on read-only file system
Problem
I first reported this with rust-analyzer at https://github.com/rust-analyzer/rust-analyzer/issues/10792: when running cargo metadata on a read-only file system, it fails saying
rust-analyzer failed to load workspace: Failed to read Cargo metadata for Rust sources: Failed to run `cargo metadata --manifest-path /home/r/.rustup/toolchains/miri/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml`: `cargo metadata` exited with an error: Updating crates.io index
error: failed to write /home/r/.rustup/toolchains/miri/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.lock
Caused by:
failed to open: /home/r/.rustup/toolchains/miri/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.lock
Caused by:
Read-only file system (os error 30)
rust-analyzer failed to load workspace: Failed to read Cargo metadata for Rust sources: Failed to run `cargo metadata --manifest-path /home/r/.rustup/toolchains/miri/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml`: `cargo metadata` exited with an error: Updating crates.io index
error: failed to write /home/r/.rustup/toolchains/miri/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.lock
Caused by:
failed to open: /home/r/.rustup/toolchains/miri/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.lock
Caused by:
Read-only file system (os error 30)
However, the action RA is trying to perform is fundamentally a read-only operation (querying for information about the rustc compiler crates).
I don’t think the currently available flags provide any way to make this work on a read-only file system either (I tried --frozen but as expected it refuses to download required crates from the network). Even if my toolchain was on a read-write file system I would not want RA’s cargo metadata to change toolchain files, after all.
Proposed Solution
cargo metadata should either handle read-only file systems by falling back to not creating/updating the lock file – or (IMO the right fix) it should not even attempt to mutate the workspace when what it is doing is a read-only operation like just determining the metadata.
Notes
No response
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 11
- Comments: 19 (13 by maintainers)
I see no good reason why it has to be like that. It certainly does not match my mental model at all.
cargo buildhas good reasons to fail when called on a crate stored on a read-only FS.cargo metadataIMO does not.Populating a cache is (conceptually) not a side-effect (formally speaking: a memoized function is observably pure). So I don’t mind it changing
~/.cargo. That is categorically different from mutating the crate it is working on.I would say even more important than being idempotent is it being a read-only operation. It is merely querying some information and state from a crate. If that information depends on things like the crate registry, I am not surprised by multiple queries returning different results. (I would not expect
curlto be idempotent, either.) However, I am severely surprised by such a command changing the on-disk state of my project, and even more surprised when there is no fallback for when performing that unexpected mutation fails.I don’t think a read-only fs ahould be considered ephemeral. It can be compiled (or get metadata retrieved) twice in whoch case the same dependency versions should be used. I see rust-analyzer only reloading cargo metadata when
Cargo.*changes as an optimization.cargo metadatashould be an idempotent operation. That is running it twice will result in the same result. If there is noCargo.lockthat will not be true. The real fix would be to ship a correctCargo.lockfile as part of the rustc-src component.The rustc-src rustup component doesn’t have the root
Cargo.tomlso the rootCargo.lockisn’t used. Rust-analyzer runscargo metadatafor the compiler/rustc crate which normally doesn’t need it’s ownCargo.lockas it uses the workspace’s version, but because the rootCargo.tomlis missing, this isn’t possible.