Merge pull request #20290 from ShoyuVanilla/tmp-lockfiles

Use `TempDir` for copied lockfiles
This commit is contained in:
Lukas Wirth 2025-07-27 11:36:35 +00:00 committed by GitHub
commit b77072075c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 54 additions and 6 deletions

7
Cargo.lock generated
View File

@ -1679,6 +1679,7 @@ dependencies = [
"serde_json", "serde_json",
"span", "span",
"stdx", "stdx",
"temp-dir",
"toolchain", "toolchain",
"tracing", "tracing",
"triomphe", "triomphe",
@ -2284,6 +2285,12 @@ dependencies = [
"tt", "tt",
] ]
[[package]]
name = "temp-dir"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83176759e9416cf81ee66cb6508dbfe9c96f20b8b56265a39917551c23c70964"
[[package]] [[package]]
name = "tenthash" name = "tenthash"
version = "1.1.0" version = "1.1.0"

View File

@ -156,6 +156,7 @@ smallvec = { version = "1.15.1", features = [
"const_generics", "const_generics",
] } ] }
smol_str = "0.3.2" smol_str = "0.3.2"
temp-dir = "0.1.16"
text-size = "1.1.1" text-size = "1.1.1"
tracing = "0.1.41" tracing = "0.1.41"
tracing-tree = "0.4.0" tracing-tree = "0.4.0"

View File

@ -20,6 +20,7 @@ semver.workspace = true
serde_json.workspace = true serde_json.workspace = true
serde.workspace = true serde.workspace = true
serde_derive.workspace = true serde_derive.workspace = true
temp-dir.workspace = true
tracing.workspace = true tracing.workspace = true
triomphe.workspace = true triomphe.workspace = true
la-arena.workspace = true la-arena.workspace = true

View File

@ -552,6 +552,7 @@ impl CargoWorkspace {
pub(crate) struct FetchMetadata { pub(crate) struct FetchMetadata {
command: cargo_metadata::MetadataCommand, command: cargo_metadata::MetadataCommand,
manifest_path: ManifestPath,
lockfile_path: Option<Utf8PathBuf>, lockfile_path: Option<Utf8PathBuf>,
kind: &'static str, kind: &'static str,
no_deps: bool, no_deps: bool,
@ -655,7 +656,15 @@ impl FetchMetadata {
} }
.with_context(|| format!("Failed to run `{cargo_command:?}`")); .with_context(|| format!("Failed to run `{cargo_command:?}`"));
Self { command, lockfile_path, kind: config.kind, no_deps, no_deps_result, other_options } Self {
manifest_path: cargo_toml.clone(),
command,
lockfile_path,
kind: config.kind,
no_deps,
no_deps_result,
other_options,
}
} }
pub(crate) fn no_deps_metadata(&self) -> Option<&cargo_metadata::Metadata> { pub(crate) fn no_deps_metadata(&self) -> Option<&cargo_metadata::Metadata> {
@ -672,18 +681,47 @@ impl FetchMetadata {
locked: bool, locked: bool,
progress: &dyn Fn(String), progress: &dyn Fn(String),
) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> { ) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
let Self { mut command, lockfile_path, kind, no_deps, no_deps_result, mut other_options } = let Self {
self; mut command,
manifest_path,
lockfile_path,
kind,
no_deps,
no_deps_result,
mut other_options,
} = self;
if no_deps { if no_deps {
return no_deps_result.map(|m| (m, None)); return no_deps_result.map(|m| (m, None));
} }
let mut using_lockfile_copy = false; let mut using_lockfile_copy = false;
let mut _temp_dir_guard = None;
// The manifest is a rust file, so this means its a script manifest // The manifest is a rust file, so this means its a script manifest
if let Some(lockfile) = lockfile_path { if let Some(lockfile) = lockfile_path {
let target_lockfile = _temp_dir_guard = temp_dir::TempDir::with_prefix("rust-analyzer").ok();
target_dir.join("rust-analyzer").join("metadata").join(kind).join("Cargo.lock"); let target_lockfile = _temp_dir_guard
.and_then(|tmp| tmp.path().join("Cargo.lock").try_into().ok())
.unwrap_or_else(|| {
// When multiple workspaces share the same target dir, they might overwrite into a
// single lockfile path.
// See https://github.com/rust-lang/rust-analyzer/issues/20189#issuecomment-3073520255
let manifest_path_hash = std::hash::BuildHasher::hash_one(
&std::hash::BuildHasherDefault::<rustc_hash::FxHasher>::default(),
&manifest_path,
);
let disambiguator = format!(
"{}_{manifest_path_hash}",
manifest_path.components().nth_back(1).map_or("", |c| c.as_str())
);
target_dir
.join("rust-analyzer")
.join("metadata")
.join(kind)
.join(disambiguator)
.join("Cargo.lock")
});
match std::fs::copy(&lockfile, &target_lockfile) { match std::fs::copy(&lockfile, &target_lockfile) {
Ok(_) => { Ok(_) => {
using_lockfile_copy = true; using_lockfile_copy = true;

View File

@ -1905,7 +1905,8 @@ fn cargo_target_dir(
meta.manifest_path(manifest); meta.manifest_path(manifest);
// `--no-deps` doesn't (over)write lockfiles as it doesn't do any package resolve. // `--no-deps` doesn't (over)write lockfiles as it doesn't do any package resolve.
// So we can use it to get `target_directory` before copying lockfiles // So we can use it to get `target_directory` before copying lockfiles
let mut other_options = vec!["--no-deps".to_owned()]; meta.no_deps();
let mut other_options = vec![];
if manifest.is_rust_manifest() { if manifest.is_rust_manifest() {
meta.env("RUSTC_BOOTSTRAP", "1"); meta.env("RUSTC_BOOTSTRAP", "1");
other_options.push("-Zscript".to_owned()); other_options.push("-Zscript".to_owned());