Skip to content

Commit 027b415

Browse files
authored
feat: emit error if package not found within workspace (#15071)
### What does this PR try to resolve? Fixes #12978 currently, if `--package `and `--workspace` passe in the same time, the `--package` will be ignore even the package doesnt exist in the workspace, this PR regards this behavior as an error ### How should we test and review this PR? one commit add test, one commit fixes the issue. ### Additional information
2 parents 1687f74 + 23ab2af commit 027b415

File tree

3 files changed

+134
-10
lines changed

3 files changed

+134
-10
lines changed

src/cargo/ops/cargo_compile/packages.rs

+41-9
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ pub enum Packages {
2020
/// Opt in all packages.
2121
///
2222
/// As of the time of this writing, it only works on opting in all workspace members.
23-
All,
23+
/// Keeps the packages passed in to verify that they exist in the workspace.
24+
All(Vec<String>),
2425
/// Opt out of packages passed in.
2526
///
2627
/// As of the time of this writing, it only works on opting out workspace members.
@@ -36,19 +37,21 @@ impl Packages {
3637
(false, 0, 0) => Packages::Default,
3738
(false, 0, _) => Packages::Packages(package),
3839
(false, _, _) => anyhow::bail!("--exclude can only be used together with --workspace"),
39-
(true, 0, _) => Packages::All,
40+
(true, 0, _) => Packages::All(package),
4041
(true, _, _) => Packages::OptOut(exclude),
4142
})
4243
}
4344

4445
/// Converts selected packages to [`PackageIdSpec`]s.
4546
pub fn to_package_id_specs(&self, ws: &Workspace<'_>) -> CargoResult<Vec<PackageIdSpec>> {
4647
let specs = match self {
47-
Packages::All => ws
48-
.members()
49-
.map(Package::package_id)
50-
.map(|id| id.to_spec())
51-
.collect(),
48+
Packages::All(packages) => {
49+
emit_packages_not_found_within_workspace(ws, packages)?;
50+
ws.members()
51+
.map(Package::package_id)
52+
.map(|id| id.to_spec())
53+
.collect()
54+
}
5255
Packages::OptOut(opt_out) => {
5356
let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;
5457
let specs = ws
@@ -111,7 +114,10 @@ impl Packages {
111114
pub fn get_packages<'ws>(&self, ws: &'ws Workspace<'_>) -> CargoResult<Vec<&'ws Package>> {
112115
let packages: Vec<_> = match self {
113116
Packages::Default => ws.default_members().collect(),
114-
Packages::All => ws.members().collect(),
117+
Packages::All(packages) => {
118+
emit_packages_not_found_within_workspace(ws, packages)?;
119+
ws.members().collect()
120+
}
115121
Packages::OptOut(opt_out) => {
116122
let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;
117123
let packages = ws
@@ -161,7 +167,7 @@ impl Packages {
161167
pub fn needs_spec_flag(&self, ws: &Workspace<'_>) -> bool {
162168
match self {
163169
Packages::Default => ws.default_members().count() > 1,
164-
Packages::All => ws.members().count() > 1,
170+
Packages::All(_) => ws.members().count() > 1,
165171
Packages::Packages(_) => true,
166172
Packages::OptOut(_) => true,
167173
}
@@ -207,6 +213,32 @@ fn emit_pattern_not_found(
207213
Ok(())
208214
}
209215

216+
fn emit_packages_not_found_within_workspace(
217+
ws: &Workspace<'_>,
218+
packages: &[String],
219+
) -> CargoResult<()> {
220+
let (mut patterns, mut ids) = opt_patterns_and_ids(packages)?;
221+
let _: Vec<_> = ws
222+
.members()
223+
.filter(|pkg| {
224+
let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();
225+
if let Some(id) = &id {
226+
ids.remove(id);
227+
}
228+
!id.is_some() && !match_patterns(pkg, &mut patterns)
229+
})
230+
.map(Package::package_id)
231+
.map(|id| id.to_spec())
232+
.collect();
233+
let names = ids
234+
.into_iter()
235+
.map(|id| id.to_string())
236+
.collect::<BTreeSet<_>>();
237+
emit_package_not_found(ws, names, false)?;
238+
emit_pattern_not_found(ws, patterns, false)?;
239+
Ok(())
240+
}
241+
210242
/// Given a list opt-in or opt-out package selection strings, generates two
211243
/// collections that represent glob patterns and package id specs respectively.
212244
fn opt_patterns_and_ids(

src/cargo/ops/cargo_output_metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ fn build_resolve_graph(
136136
CompileKind::from_requested_targets(ws.gctx(), &metadata_opts.filter_platforms)?;
137137
let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;
138138
// Resolve entire workspace.
139-
let specs = Packages::All.to_package_id_specs(ws)?;
139+
let specs = Packages::All(Vec::new()).to_package_id_specs(ws)?;
140140
let force_all = if metadata_opts.filter_platforms.is_empty() {
141141
crate::core::resolver::features::ForceAllTargets::Yes
142142
} else {

tests/testsuite/workspaces.rs

+92
Original file line numberDiff line numberDiff line change
@@ -2624,3 +2624,95 @@ foo v0.1.0 ([ROOT]/foo/sub/foo)
26242624
"#]])
26252625
.run();
26262626
}
2627+
2628+
#[cargo_test]
2629+
fn nonexistence_package_togother_with_workspace() {
2630+
let p = project()
2631+
.file(
2632+
"Cargo.toml",
2633+
r#"
2634+
[package]
2635+
name = "foo"
2636+
version = "0.1.0"
2637+
authors = []
2638+
edition = "2021"
2639+
2640+
[workspace]
2641+
members = ["baz"]
2642+
"#,
2643+
)
2644+
.file("src/lib.rs", "")
2645+
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
2646+
.file("baz/src/lib.rs", "");
2647+
2648+
let p = p.build();
2649+
2650+
p.cargo("check --package nonexistence --workspace")
2651+
.with_status(101)
2652+
.with_stderr_data(
2653+
str![[r#"
2654+
[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`
2655+
2656+
"#]]
2657+
.unordered(),
2658+
)
2659+
.run();
2660+
// With pattern *
2661+
p.cargo("check --package nonpattern* --workspace")
2662+
.with_status(101)
2663+
.with_stderr_data(str![[r#"
2664+
[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`
2665+
2666+
"#]])
2667+
.run();
2668+
2669+
p.cargo("package --package nonexistence --workspace")
2670+
.with_status(101)
2671+
.with_stderr_data(str![[r#"
2672+
[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`
2673+
2674+
"#]])
2675+
.run();
2676+
// With pattern *
2677+
p.cargo("package --package nonpattern* --workspace")
2678+
.with_status(101)
2679+
.with_stderr_data(str![[r#"
2680+
[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`
2681+
2682+
"#]])
2683+
.run();
2684+
2685+
p.cargo("publish --dry-run --package nonexistence -Zpackage-workspace --workspace")
2686+
.with_status(101)
2687+
.with_stderr_data(str![[r#"
2688+
[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`
2689+
2690+
"#]])
2691+
.masquerade_as_nightly_cargo(&["package-workspace"])
2692+
.run();
2693+
// With pattern *
2694+
p.cargo("publish --dry-run --package nonpattern* -Zpackage-workspace --workspace")
2695+
.with_status(101)
2696+
.with_stderr_data(str![[r#"
2697+
[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`
2698+
2699+
"#]])
2700+
.masquerade_as_nightly_cargo(&["package-workspace"])
2701+
.run();
2702+
2703+
p.cargo("tree --package nonexistence --workspace")
2704+
.with_status(101)
2705+
.with_stderr_data(str![[r#"
2706+
[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`
2707+
2708+
"#]])
2709+
.run();
2710+
// With pattern *
2711+
p.cargo("tree --package nonpattern* --workspace")
2712+
.with_status(101)
2713+
.with_stderr_data(str![[r#"
2714+
[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`
2715+
2716+
"#]])
2717+
.run();
2718+
}

0 commit comments

Comments
 (0)