Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/project-model/src/sysroot.rs')
-rw-r--r--crates/project-model/src/sysroot.rs69
1 files changed, 55 insertions, 14 deletions
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index c0a5009afb..f244c9736c 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -8,8 +8,9 @@ use core::fmt;
use std::{env, fs, ops::Not, path::Path, process::Command};
use anyhow::{Result, format_err};
+use base_db::Env;
use itertools::Itertools;
-use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
use rustc_hash::FxHashMap;
use stdx::format_to;
use toolchain::{Tool, probe_for_binary};
@@ -30,7 +31,7 @@ pub struct Sysroot {
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RustLibSrcWorkspace {
- Workspace(CargoWorkspace),
+ Workspace { ws: CargoWorkspace, metadata_err: Option<String> },
Json(ProjectJson),
Stitched(stitched::Stitched),
Empty,
@@ -39,7 +40,9 @@ pub enum RustLibSrcWorkspace {
impl fmt::Display for RustLibSrcWorkspace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- RustLibSrcWorkspace::Workspace(ws) => write!(f, "workspace {}", ws.workspace_root()),
+ RustLibSrcWorkspace::Workspace { ws, .. } => {
+ write!(f, "workspace {}", ws.workspace_root())
+ }
RustLibSrcWorkspace::Json(json) => write!(f, "json {}", json.manifest_or_root()),
RustLibSrcWorkspace::Stitched(stitched) => {
write!(f, "stitched with {} crates", stitched.crates.len())
@@ -74,7 +77,7 @@ impl Sysroot {
pub fn is_rust_lib_src_empty(&self) -> bool {
match &self.workspace {
- RustLibSrcWorkspace::Workspace(ws) => ws.packages().next().is_none(),
+ RustLibSrcWorkspace::Workspace { ws, .. } => ws.packages().next().is_none(),
RustLibSrcWorkspace::Json(project_json) => project_json.n_crates() == 0,
RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.is_empty(),
RustLibSrcWorkspace::Empty => true,
@@ -85,9 +88,16 @@ impl Sysroot {
self.error.as_deref()
}
+ pub fn metadata_error(&self) -> Option<&str> {
+ match &self.workspace {
+ RustLibSrcWorkspace::Workspace { metadata_err, .. } => metadata_err.as_deref(),
+ _ => None,
+ }
+ }
+
pub fn num_packages(&self) -> usize {
match &self.workspace {
- RustLibSrcWorkspace::Workspace(ws) => ws.packages().count(),
+ RustLibSrcWorkspace::Workspace { ws, .. } => ws.packages().count(),
RustLibSrcWorkspace::Json(project_json) => project_json.n_crates(),
RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.len(),
RustLibSrcWorkspace::Empty => 0,
@@ -163,6 +173,36 @@ impl Sysroot {
}
}
+ pub fn tool_path(&self, tool: Tool, current_dir: impl AsRef<Path>, envs: &Env) -> Utf8PathBuf {
+ match self.root() {
+ Some(root) => {
+ let mut cmd = toolchain::command(
+ Tool::Rustup.path(),
+ current_dir,
+ &envs
+ .into_iter()
+ .map(|(k, v)| (k.clone(), Some(v.clone())))
+ .collect::<FxHashMap<_, _>>(),
+ );
+ if !envs.contains_key("RUSTUP_TOOLCHAIN")
+ && std::env::var_os("RUSTUP_TOOLCHAIN").is_none()
+ {
+ cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
+ }
+
+ cmd.arg("which");
+ cmd.arg(tool.name());
+ (|| {
+ Some(Utf8PathBuf::from(
+ String::from_utf8(cmd.output().ok()?.stdout).ok()?.trim_end(),
+ ))
+ })()
+ .unwrap_or_else(|| Utf8PathBuf::from(tool.name()))
+ }
+ _ => tool.path(),
+ }
+ }
+
pub fn discover_proc_macro_srv(&self) -> Option<anyhow::Result<AbsPathBuf>> {
let root = self.root()?;
Some(
@@ -210,8 +250,6 @@ impl Sysroot {
&self,
sysroot_source_config: &RustSourceWorkspaceConfig,
no_deps: bool,
- current_dir: &AbsPath,
- target_dir: &Utf8Path,
progress: &dyn Fn(String),
) -> Option<RustLibSrcWorkspace> {
assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded");
@@ -224,8 +262,7 @@ impl Sysroot {
if fs::metadata(&library_manifest).is_ok() {
match self.load_library_via_cargo(
&library_manifest,
- current_dir,
- target_dir,
+ src_root,
cargo_config,
no_deps,
progress,
@@ -294,7 +331,9 @@ impl Sysroot {
&& let Some(src_root) = &self.rust_lib_src_root
{
let has_core = match &self.workspace {
- RustLibSrcWorkspace::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
+ RustLibSrcWorkspace::Workspace { ws: workspace, .. } => {
+ workspace.packages().any(|p| workspace[p].name == "core")
+ }
RustLibSrcWorkspace::Json(project_json) => project_json
.crates()
.filter_map(|(_, krate)| krate.display_name.clone())
@@ -318,7 +357,6 @@ impl Sysroot {
&self,
library_manifest: &ManifestPath,
current_dir: &AbsPath,
- target_dir: &Utf8Path,
cargo_config: &CargoMetadataConfig,
no_deps: bool,
progress: &dyn Fn(String),
@@ -333,9 +371,9 @@ impl Sysroot {
// Make sure we never attempt to write to the sysroot
let locked = true;
- let (mut res, _) =
+ let (mut res, err) =
FetchMetadata::new(library_manifest, current_dir, &cargo_config, self, no_deps)
- .exec(target_dir, locked, progress)?;
+ .exec(locked, progress)?;
// Patch out `rustc-std-workspace-*` crates to point to the real crates.
// This is done prior to `CrateGraph` construction to prevent de-duplication logic from failing.
@@ -388,7 +426,10 @@ impl Sysroot {
let cargo_workspace =
CargoWorkspace::new(res, library_manifest.clone(), Default::default(), true);
- Ok(RustLibSrcWorkspace::Workspace(cargo_workspace))
+ Ok(RustLibSrcWorkspace::Workspace {
+ ws: cargo_workspace,
+ metadata_err: err.map(|e| format!("{e:#}")),
+ })
}
}