Skip to content

Commit 91d8140

Browse files
authored
Print globs when workspace members can't be found (#15093)
Cargo expands globs when loading workspace members. If the glob happens to match some non-crate directory, it causes an error that may be tricky to understand, because it makes Cargo complain that it failed to read a `Cargo.toml` from a specific directory, but that directory name won't be listed explicitly anywhere in `Cargo.toml`, so it may seem that Cargo is trying to read some made-up phantom manifest. I've made the error messages mention which glob has been used to select the missing workspace member.
2 parents 53a2fdf + 9b31464 commit 91d8140

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

src/cargo/core/workspace.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,8 @@ impl<'gctx> Workspace<'gctx> {
742742
// self.root_manifest must be Some to have retrieved workspace_config
743743
let root_manifest_path = self.root_manifest.clone().unwrap();
744744

745-
let members_paths =
746-
workspace_config.members_paths(workspace_config.members.as_ref().unwrap_or(&vec![]))?;
745+
let members_paths = workspace_config
746+
.members_paths(workspace_config.members.as_deref().unwrap_or_default())?;
747747
let default_members_paths = if root_manifest_path == self.current_manifest {
748748
if let Some(ref default) = workspace_config.default_members {
749749
Some(workspace_config.members_paths(default)?)
@@ -754,22 +754,23 @@ impl<'gctx> Workspace<'gctx> {
754754
None
755755
};
756756

757-
for path in &members_paths {
757+
for (path, glob) in &members_paths {
758758
self.find_path_deps(&path.join("Cargo.toml"), &root_manifest_path, false)
759759
.with_context(|| {
760760
format!(
761761
"failed to load manifest for workspace member `{}`\n\
762-
referenced by workspace at `{}`",
762+
referenced{} by workspace at `{}`",
763763
path.display(),
764-
root_manifest_path.display()
764+
glob.map(|g| format!(" via `{g}`")).unwrap_or_default(),
765+
root_manifest_path.display(),
765766
)
766767
})?;
767768
}
768769

769770
self.find_path_deps(&root_manifest_path, &root_manifest_path, false)?;
770771

771772
if let Some(default) = default_members_paths {
772-
for path in default {
773+
for (path, default_member_glob) in default {
773774
let normalized_path = paths::normalize_path(&path);
774775
let manifest_path = normalized_path.join("Cargo.toml");
775776
if !self.members.contains(&manifest_path) {
@@ -779,16 +780,19 @@ impl<'gctx> Workspace<'gctx> {
779780
// manifest path, both because `members_paths` doesn't
780781
// include `/Cargo.toml`, and because excluded paths may not
781782
// be crates.
782-
let exclude = members_paths.contains(&normalized_path)
783+
let exclude = members_paths.iter().any(|(m, _)| *m == normalized_path)
783784
&& workspace_config.is_excluded(&normalized_path);
784785
if exclude {
785786
continue;
786787
}
787788
bail!(
788-
"package `{}` is listed in default-members but is not a member\n\
789-
for workspace at {}.",
789+
"package `{}` is listed in default-members{} but is not a member\n\
790+
for workspace at `{}`.",
790791
path.display(),
791-
root_manifest_path.display()
792+
default_member_glob
793+
.map(|g| format!(" via `{g}`"))
794+
.unwrap_or_default(),
795+
root_manifest_path.display(),
792796
)
793797
}
794798
self.default_members.push(manifest_path)
@@ -1872,8 +1876,13 @@ impl WorkspaceRootConfig {
18721876
self.members.is_some()
18731877
}
18741878

1879+
/// Returns expanded paths along with the glob that they were expanded from.
1880+
/// The glob is `None` if the path matched exactly.
18751881
#[tracing::instrument(skip_all)]
1876-
fn members_paths(&self, globs: &[String]) -> CargoResult<Vec<PathBuf>> {
1882+
fn members_paths<'g>(
1883+
&self,
1884+
globs: &'g [String],
1885+
) -> CargoResult<Vec<(PathBuf, Option<&'g str>)>> {
18771886
let mut expanded_list = Vec::new();
18781887

18791888
for glob in globs {
@@ -1883,16 +1892,19 @@ impl WorkspaceRootConfig {
18831892
// If glob does not find any valid paths, then put the original
18841893
// path in the expanded list to maintain backwards compatibility.
18851894
if expanded_paths.is_empty() {
1886-
expanded_list.push(pathbuf);
1895+
expanded_list.push((pathbuf, None));
18871896
} else {
1897+
let used_glob_pattern = expanded_paths.len() > 1 || expanded_paths[0] != pathbuf;
1898+
let glob = used_glob_pattern.then_some(glob.as_str());
1899+
18881900
// Some OS can create system support files anywhere.
18891901
// (e.g. macOS creates `.DS_Store` file if you visit a directory using Finder.)
18901902
// Such files can be reported as a member path unexpectedly.
18911903
// Check and filter out non-directory paths to prevent pushing such accidental unwanted path
18921904
// as a member.
18931905
for expanded_path in expanded_paths {
18941906
if expanded_path.is_dir() {
1895-
expanded_list.push(expanded_path);
1907+
expanded_list.push((expanded_path, glob));
18961908
}
18971909
}
18981910
}

tests/testsuite/workspaces.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ fn virtual_default_member_is_not_a_member() {
948948
.with_status(101)
949949
.with_stderr_data(str![[r#"
950950
[ERROR] package `[ROOT]/foo/something-else` is listed in default-members but is not a member
951-
for workspace at [ROOT]/foo/Cargo.toml.
951+
for workspace at `[ROOT]/foo/Cargo.toml`.
952952
953953
"#]])
954954
.run();
@@ -1731,7 +1731,7 @@ fn excluded_default_members_still_must_be_members() {
17311731
.with_status(101)
17321732
.with_stderr_data(str![[r#"
17331733
[ERROR] package `[ROOT]/foo/bar` is listed in default-members but is not a member
1734-
for workspace at [ROOT]/foo/Cargo.toml.
1734+
for workspace at `[ROOT]/foo/Cargo.toml`.
17351735
17361736
"#]])
17371737
.run();
@@ -1968,7 +1968,7 @@ fn glob_syntax_invalid_members() {
19681968
.with_status(101)
19691969
.with_stderr_data(str![[r#"
19701970
[ERROR] failed to load manifest for workspace member `[ROOT]/foo/crates/bar`
1971-
referenced by workspace at `[ROOT]/foo/Cargo.toml`
1971+
referenced via `crates/*` by workspace at `[ROOT]/foo/Cargo.toml`
19721972
19731973
Caused by:
19741974
failed to read `[ROOT]/foo/crates/bar/Cargo.toml`

0 commit comments

Comments
 (0)