Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/project-model/src/build_dependencies.rs34
-rw-r--r--crates/project-model/src/cargo_config_file.rs62
-rw-r--r--crates/project-model/src/cargo_workspace.rs49
3 files changed, 95 insertions, 50 deletions
diff --git a/crates/project-model/src/build_dependencies.rs b/crates/project-model/src/build_dependencies.rs
index fedc6944f5..aff5391697 100644
--- a/crates/project-model/src/build_dependencies.rs
+++ b/crates/project-model/src/build_dependencies.rs
@@ -22,8 +22,9 @@ use triomphe::Arc;
use crate::{
CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, ManifestPath, Package, Sysroot,
- TargetKind, cargo_config_file::make_lockfile_copy,
- cargo_workspace::MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH, utf8_stdout,
+ TargetKind,
+ cargo_config_file::{LockfileCopy, LockfileUsage, make_lockfile_copy},
+ utf8_stdout,
};
/// Output of the build script and proc-macro building steps for a workspace.
@@ -436,7 +437,7 @@ impl WorkspaceBuildScripts {
current_dir: &AbsPath,
sysroot: &Sysroot,
toolchain: Option<&semver::Version>,
- ) -> io::Result<(Option<temp_dir::TempDir>, Command)> {
+ ) -> io::Result<(Option<LockfileCopy>, Command)> {
match config.run_build_script_command.as_deref() {
Some([program, args @ ..]) => {
let mut cmd = toolchain::command(program, current_dir, &config.extra_env);
@@ -461,17 +462,26 @@ impl WorkspaceBuildScripts {
if let Some(target) = &config.target {
cmd.args(["--target", target]);
}
- let mut temp_dir_guard = None;
- if toolchain
- .is_some_and(|v| *v >= MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH)
- {
+ let mut lockfile_copy = None;
+ if let Some(toolchain) = toolchain {
let lockfile_path =
<_ as AsRef<Utf8Path>>::as_ref(manifest_path).with_extension("lock");
- if let Some((temp_dir, target_lockfile)) = make_lockfile_copy(&lockfile_path) {
+ lockfile_copy = make_lockfile_copy(toolchain, &lockfile_path);
+ if let Some(lockfile_copy) = &lockfile_copy {
requires_unstable_options = true;
- temp_dir_guard = Some(temp_dir);
- cmd.arg("--lockfile-path");
- cmd.arg(target_lockfile.as_str());
+ match lockfile_copy.usage {
+ LockfileUsage::WithFlag => {
+ cmd.arg("--lockfile-path");
+ cmd.arg(lockfile_copy.path.as_str());
+ }
+ LockfileUsage::WithEnvVar => {
+ cmd.arg("-Zlockfile-path");
+ cmd.env(
+ "CARGO_RESOLVER_LOCKFILE_PATH",
+ lockfile_copy.path.as_os_str(),
+ );
+ }
+ }
}
}
match &config.features {
@@ -542,7 +552,7 @@ impl WorkspaceBuildScripts {
cmd.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly");
cmd.arg("-Zunstable-options");
}
- Ok((temp_dir_guard, cmd))
+ Ok((lockfile_copy, cmd))
}
}
}
diff --git a/crates/project-model/src/cargo_config_file.rs b/crates/project-model/src/cargo_config_file.rs
index 5d6e5fd648..ae36deb71f 100644
--- a/crates/project-model/src/cargo_config_file.rs
+++ b/crates/project-model/src/cargo_config_file.rs
@@ -132,25 +132,65 @@ impl<'a> CargoConfigFileReader<'a> {
}
}
+pub(crate) struct LockfileCopy {
+ pub(crate) path: Utf8PathBuf,
+ pub(crate) usage: LockfileUsage,
+ _temp_dir: temp_dir::TempDir,
+}
+
+pub(crate) enum LockfileUsage {
+ /// Rust [1.82.0, 1.95.0). `cargo <subcmd> --lockfile-path <lockfile path>`
+ WithFlag,
+ /// Rust >= 1.95.0. `CARGO_RESOLVER_LOCKFILE_PATH=<lockfile path> cargo <subcmd>`
+ WithEnvVar,
+}
+
pub(crate) fn make_lockfile_copy(
+ toolchain_version: &semver::Version,
lockfile_path: &Utf8Path,
-) -> Option<(temp_dir::TempDir, Utf8PathBuf)> {
+) -> Option<LockfileCopy> {
+ const MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_FLAG: semver::Version =
+ semver::Version {
+ major: 1,
+ minor: 82,
+ patch: 0,
+ pre: semver::Prerelease::EMPTY,
+ build: semver::BuildMetadata::EMPTY,
+ };
+
+ const MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_ENV: semver::Version =
+ semver::Version {
+ major: 1,
+ minor: 95,
+ patch: 0,
+ pre: semver::Prerelease::EMPTY,
+ build: semver::BuildMetadata::EMPTY,
+ };
+
+ let usage = if *toolchain_version >= MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_ENV {
+ LockfileUsage::WithEnvVar
+ } else if *toolchain_version >= MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH_FLAG {
+ LockfileUsage::WithFlag
+ } else {
+ return None;
+ };
+
let temp_dir = temp_dir::TempDir::with_prefix("rust-analyzer").ok()?;
- let target_lockfile = temp_dir.path().join("Cargo.lock").try_into().ok()?;
- match std::fs::copy(lockfile_path, &target_lockfile) {
+ let path: Utf8PathBuf = temp_dir.path().join("Cargo.lock").try_into().ok()?;
+ let path = match std::fs::copy(lockfile_path, &path) {
Ok(_) => {
- tracing::debug!("Copied lock file from `{}` to `{}`", lockfile_path, target_lockfile);
- Some((temp_dir, target_lockfile))
+ tracing::debug!("Copied lock file from `{}` to `{}`", lockfile_path, path);
+ path
}
// lockfile does not yet exist, so we can just create a new one in the temp dir
- Err(e) if e.kind() == std::io::ErrorKind::NotFound => Some((temp_dir, target_lockfile)),
+ Err(e) if e.kind() == std::io::ErrorKind::NotFound => path,
Err(e) => {
- tracing::warn!(
- "Failed to copy lock file from `{lockfile_path}` to `{target_lockfile}`: {e}",
- );
- None
+ tracing::warn!("Failed to copy lock file from `{lockfile_path}` to `{path}`: {e}",);
+ return None;
}
- }
+ };
+
+ Some(LockfileCopy { path, usage, _temp_dir: temp_dir })
}
#[test]
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 483ab28450..792206b74f 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -16,18 +16,10 @@ use toolchain::{NO_RUSTUP_AUTO_INSTALL_ENV, Tool};
use triomphe::Arc;
use crate::{
- CfgOverrides, InvocationStrategy, ManifestPath, Sysroot, cargo_config_file::make_lockfile_copy,
+ CfgOverrides, InvocationStrategy, ManifestPath, Sysroot,
+ cargo_config_file::{LockfileCopy, LockfileUsage, make_lockfile_copy},
};
-pub(crate) const MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH: semver::Version =
- semver::Version {
- major: 1,
- minor: 82,
- patch: 0,
- pre: semver::Prerelease::EMPTY,
- build: semver::BuildMetadata::EMPTY,
- };
-
/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
/// workspace. It pretty closely mirrors `cargo metadata` output.
///
@@ -628,7 +620,7 @@ pub(crate) struct FetchMetadata {
command: cargo_metadata::MetadataCommand,
#[expect(dead_code)]
manifest_path: ManifestPath,
- lockfile_path: Option<Utf8PathBuf>,
+ lockfile_copy: Option<LockfileCopy>,
#[expect(dead_code)]
kind: &'static str,
no_deps: bool,
@@ -688,15 +680,14 @@ impl FetchMetadata {
}
}
- let mut lockfile_path = None;
+ let mut lockfile_copy = None;
if cargo_toml.is_rust_manifest() {
other_options.push("-Zscript".to_owned());
- } else if config
- .toolchain_version
- .as_ref()
- .is_some_and(|v| *v >= MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH)
- {
- lockfile_path = Some(<_ as AsRef<Utf8Path>>::as_ref(cargo_toml).with_extension("lock"));
+ } else if let Some(v) = config.toolchain_version.as_ref() {
+ lockfile_copy = make_lockfile_copy(
+ v,
+ &<_ as AsRef<Utf8Path>>::as_ref(cargo_toml).with_extension("lock"),
+ );
}
if !config.targets.is_empty() {
@@ -729,7 +720,7 @@ impl FetchMetadata {
Self {
manifest_path: cargo_toml.clone(),
command,
- lockfile_path,
+ lockfile_copy,
kind: config.kind,
no_deps,
no_deps_result,
@@ -749,7 +740,7 @@ impl FetchMetadata {
let Self {
mut command,
manifest_path: _,
- lockfile_path,
+ lockfile_copy,
kind: _,
no_deps,
no_deps_result,
@@ -761,13 +752,17 @@ impl FetchMetadata {
}
let mut using_lockfile_copy = false;
- let mut _temp_dir_guard;
- if let Some(lockfile) = lockfile_path
- && let Some((temp_dir, target_lockfile)) = make_lockfile_copy(&lockfile)
- {
- _temp_dir_guard = temp_dir;
- other_options.push("--lockfile-path".to_owned());
- other_options.push(target_lockfile.to_string());
+ if let Some(lockfile_copy) = &lockfile_copy {
+ match lockfile_copy.usage {
+ LockfileUsage::WithFlag => {
+ other_options.push("--lockfile-path".to_owned());
+ other_options.push(lockfile_copy.path.to_string());
+ }
+ LockfileUsage::WithEnvVar => {
+ other_options.push("-Zlockfile-path".to_owned());
+ command.env("CARGO_RESOLVER_LOCKFILE_PATH", lockfile_copy.path.as_os_str());
+ }
+ }
using_lockfile_copy = true;
}
if using_lockfile_copy || other_options.iter().any(|it| it.starts_with("-Z")) {