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

View File

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

View File

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

View File

@ -552,6 +552,7 @@ impl CargoWorkspace {
pub(crate) struct FetchMetadata {
command: cargo_metadata::MetadataCommand,
manifest_path: ManifestPath,
lockfile_path: Option<Utf8PathBuf>,
kind: &'static str,
no_deps: bool,
@ -655,7 +656,15 @@ impl FetchMetadata {
}
.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> {
@ -672,18 +681,47 @@ impl FetchMetadata {
locked: bool,
progress: &dyn Fn(String),
) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
let Self { mut command, lockfile_path, kind, no_deps, no_deps_result, mut other_options } =
self;
let Self {
mut command,
manifest_path,
lockfile_path,
kind,
no_deps,
no_deps_result,
mut other_options,
} = self;
if no_deps {
return no_deps_result.map(|m| (m, None));
}
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
if let Some(lockfile) = lockfile_path {
let target_lockfile =
target_dir.join("rust-analyzer").join("metadata").join(kind).join("Cargo.lock");
_temp_dir_guard = temp_dir::TempDir::with_prefix("rust-analyzer").ok();
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) {
Ok(_) => {
using_lockfile_copy = true;

View File

@ -1905,7 +1905,8 @@ fn cargo_target_dir(
meta.manifest_path(manifest);
// `--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
let mut other_options = vec!["--no-deps".to_owned()];
meta.no_deps();
let mut other_options = vec![];
if manifest.is_rust_manifest() {
meta.env("RUSTC_BOOTSTRAP", "1");
other_options.push("-Zscript".to_owned());