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.rs | 69 |
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:#}")), + }) } } |