feat: Show what cargo metadata is doing in status

This commit is contained in:
Lukas Wirth 2025-06-16 18:05:44 +02:00
parent e2c3647c6a
commit 9dfbd56bb8
6 changed files with 56 additions and 25 deletions

View file

@ -42,7 +42,7 @@ pub fn load_workspace_at(
root: &Path,
cargo_config: &CargoConfig,
load_config: &LoadCargoConfig,
progress: &dyn Fn(String),
progress: &(dyn Fn(String) + Sync),
) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> {
let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root));
let root = ProjectManifest::discover_single(&root)?;

View file

@ -12,6 +12,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use serde_derive::Deserialize;
use serde_json::from_value;
use span::Edition;
use stdx::process::spawn_with_streaming_output;
use toolchain::Tool;
use crate::{CfgOverrides, InvocationStrategy};
@ -399,11 +400,21 @@ impl CargoWorkspace {
// FIXME: Fetching metadata is a slow process, as it might require
// calling crates.io. We should be reporting progress here, but it's
// unclear whether cargo itself supports it.
progress("metadata".to_owned());
progress("cargo metadata: started".to_owned());
(|| -> anyhow::Result<(_, _)> {
let output = meta.cargo_command().output()?;
let res = (|| -> anyhow::Result<(_, _)> {
let mut errored = false;
let output =
spawn_with_streaming_output(meta.cargo_command(), &mut |_| (), &mut |line| {
errored = errored || line.starts_with("error") || line.starts_with("warning");
if errored {
progress("cargo metadata: ?".to_owned());
return;
}
progress(format!("cargo metadata: {line}"));
})?;
if !output.status.success() {
progress(format!("cargo metadata: failed {}", output.status));
let error = cargo_metadata::Error::CargoMetadata {
stderr: String::from_utf8(output.stderr)?,
}
@ -431,7 +442,9 @@ impl CargoWorkspace {
.ok_or(cargo_metadata::Error::NoJson)?;
Ok((cargo_metadata::MetadataCommand::parse(stdout)?, None))
})()
.with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))
.with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()));
progress("cargo metadata: finished".to_owned());
res
}
pub fn new(

View file

@ -195,6 +195,7 @@ impl Sysroot {
pub fn load_workspace(
&self,
sysroot_source_config: &RustSourceWorkspaceConfig,
progress: &dyn Fn(String),
) -> Option<RustLibSrcWorkspace> {
assert!(matches!(self.workspace, RustLibSrcWorkspace::Empty), "workspace already loaded");
let Self { root: _, rust_lib_src_root: Some(src_root), workspace: _, error: _ } = self
@ -205,7 +206,7 @@ impl Sysroot {
let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap();
if fs::metadata(&library_manifest).is_ok() {
if let Some(loaded) =
self.load_library_via_cargo(library_manifest, src_root, cargo_config)
self.load_library_via_cargo(library_manifest, src_root, cargo_config, progress)
{
return Some(loaded);
}
@ -296,6 +297,7 @@ impl Sysroot {
library_manifest: ManifestPath,
rust_lib_src_dir: &AbsPathBuf,
cargo_config: &CargoMetadataConfig,
progress: &dyn Fn(String),
) -> Option<RustLibSrcWorkspace> {
tracing::debug!("Loading library metadata: {library_manifest}");
let mut cargo_config = cargo_config.clone();
@ -313,7 +315,7 @@ impl Sysroot {
false,
// Make sure we never attempt to write to the sysroot
true,
&|_| (),
progress,
) {
Ok(it) => it,
Err(e) => {

View file

@ -235,7 +235,8 @@ fn smoke_test_real_sysroot_cargo() {
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
&Default::default(),
);
let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo());
let loaded_sysroot =
sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), &|_| ());
if let Some(loaded_sysroot) = loaded_sysroot {
sysroot.set_workspace(loaded_sysroot);
}

View file

@ -170,7 +170,7 @@ impl ProjectWorkspace {
pub fn load(
manifest: ProjectManifest,
config: &CargoConfig,
progress: &dyn Fn(String),
progress: &(dyn Fn(String) + Sync),
) -> anyhow::Result<ProjectWorkspace> {
ProjectWorkspace::load_inner(&manifest, config, progress)
.with_context(|| format!("Failed to load the project at {manifest}"))
@ -179,7 +179,7 @@ impl ProjectWorkspace {
fn load_inner(
manifest: &ProjectManifest,
config: &CargoConfig,
progress: &dyn Fn(String),
progress: &(dyn Fn(String) + Sync),
) -> anyhow::Result<ProjectWorkspace> {
let res = match manifest {
ProjectManifest::ProjectJson(project_json) => {
@ -206,7 +206,7 @@ impl ProjectWorkspace {
fn load_cargo(
cargo_toml: &ManifestPath,
config: &CargoConfig,
progress: &dyn Fn(String),
progress: &(dyn Fn(String) + Sync),
) -> Result<ProjectWorkspace, anyhow::Error> {
progress("Discovering sysroot".to_owned());
let CargoConfig {
@ -304,7 +304,7 @@ impl ProjectWorkspace {
&sysroot,
*no_deps,
false,
&|_| (),
progress,
) {
Ok((meta, _error)) => {
let workspace = CargoWorkspace::new(
@ -347,13 +347,16 @@ impl ProjectWorkspace {
&sysroot,
*no_deps,
false,
&|_| (),
progress,
)
});
let loaded_sysroot = s.spawn(|| {
sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata(
sysroot_metadata_config(extra_env, &targets),
))
sysroot.load_workspace(
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
extra_env, &targets,
)),
progress,
)
});
let cargo_config_extra_env =
s.spawn(|| cargo_config_env(cargo_toml, extra_env, &sysroot));
@ -411,7 +414,7 @@ impl ProjectWorkspace {
pub fn load_inline(
mut project_json: ProjectJson,
config: &CargoConfig,
progress: &dyn Fn(String),
progress: &(dyn Fn(String) + Sync),
) -> ProjectWorkspace {
progress("Discovering sysroot".to_owned());
let mut sysroot =
@ -443,11 +446,18 @@ impl ProjectWorkspace {
});
let loaded_sysroot = s.spawn(|| {
if let Some(sysroot_project) = sysroot_project {
sysroot.load_workspace(&RustSourceWorkspaceConfig::Json(*sysroot_project))
sysroot.load_workspace(
&RustSourceWorkspaceConfig::Json(*sysroot_project),
progress,
)
} else {
sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata(
sysroot_metadata_config(&config.extra_env, &targets),
))
sysroot.load_workspace(
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
&config.extra_env,
&targets,
)),
progress,
)
}
});
@ -497,9 +507,13 @@ impl ProjectWorkspace {
.unwrap_or_default();
let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata(
sysroot_metadata_config(&config.extra_env, &targets),
));
let loaded_sysroot = sysroot.load_workspace(
&RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
&config.extra_env,
&targets,
)),
&|_| (),
);
if let Some(loaded_sysroot) = loaded_sysroot {
sysroot.set_workspace(loaded_sysroot);
}

View file

@ -76,7 +76,8 @@ impl Tester {
};
let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo());
let loaded_sysroot =
sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), &|_| ());
if let Some(loaded_sysroot) = loaded_sysroot {
sysroot.set_workspace(loaded_sysroot);
}