mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-04 11:34:35 +00:00
fix(run): Disambiguate bins from different packages that share a name (#15298)
### What does this PR try to resolve? This builds on the work done in #15199 to improve target selection errors to also disambiguate when the same binary name is used in multiple packages. This also makes the errors from #15199 more consistent with the rustc style guide and reduces code duplication. Fixes #13312 ### How should we test and review this PR? This is a first pass and does not do the full `--package foo --bin bar` syntax. I wanted to focus on the basic functionality before we iterated on it, e.g. investigating how well we can predict the CLI flags, how much noise they might add, etc. ### Additional information
This commit is contained in:
commit
bc577dc6c4
@ -259,24 +259,27 @@ impl<'a> UnitGenerator<'a, '_> {
|
|||||||
};
|
};
|
||||||
let proposals = self.filter_targets(filter, true, mode);
|
let proposals = self.filter_targets(filter, true, mode);
|
||||||
if proposals.is_empty() {
|
if proposals.is_empty() {
|
||||||
let targets = self
|
let mut targets = std::collections::BTreeMap::new();
|
||||||
.packages
|
for (pkg, target) in self.packages.iter().flat_map(|pkg| {
|
||||||
.iter()
|
|
||||||
.flat_map(|pkg| {
|
|
||||||
pkg.targets()
|
pkg.targets()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|target| is_expected_kind(target))
|
.filter(|target| is_expected_kind(target))
|
||||||
})
|
.map(move |t| (pkg, t))
|
||||||
.collect::<Vec<_>>();
|
}) {
|
||||||
let suggestion = closest_msg(target_name, targets.iter(), |t| t.name(), "target");
|
targets
|
||||||
|
.entry(target.name())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push((pkg, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
let suggestion = closest_msg(target_name, targets.keys(), |t| t, "target");
|
||||||
let targets_elsewhere = self.get_targets_from_other_packages(filter)?;
|
let targets_elsewhere = self.get_targets_from_other_packages(filter)?;
|
||||||
let need_append_targets_elsewhere = !targets_elsewhere.is_empty();
|
let append_targets_elsewhere = |msg: &mut String| {
|
||||||
let append_targets_elsewhere = |msg: &mut String, prefix: &str| {
|
|
||||||
let mut available_msg = Vec::new();
|
let mut available_msg = Vec::new();
|
||||||
for (package, targets) in targets_elsewhere {
|
for (package, targets) in &targets_elsewhere {
|
||||||
if !targets.is_empty() {
|
if !targets.is_empty() {
|
||||||
available_msg.push(format!(
|
available_msg.push(format!(
|
||||||
"help: Available {target_desc} in `{package}` package:"
|
"help: available {target_desc} in `{package}` package:"
|
||||||
));
|
));
|
||||||
for target in targets {
|
for target in targets {
|
||||||
available_msg.push(format!(" {target}"));
|
available_msg.push(format!(" {target}"));
|
||||||
@ -284,12 +287,12 @@ impl<'a> UnitGenerator<'a, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !available_msg.is_empty() {
|
if !available_msg.is_empty() {
|
||||||
write!(msg, "{prefix}{}", available_msg.join("\n"))?;
|
write!(msg, "\n{}", available_msg.join("\n"))?;
|
||||||
}
|
}
|
||||||
CargoResult::Ok(())
|
CargoResult::Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
let unmatched_packages = || match self.spec {
|
let unmatched_packages = match self.spec {
|
||||||
Packages::Default | Packages::OptOut(_) | Packages::All(_) => {
|
Packages::Default | Packages::OptOut(_) | Packages::All(_) => {
|
||||||
"default-run packages".to_owned()
|
"default-run packages".to_owned()
|
||||||
}
|
}
|
||||||
@ -305,33 +308,25 @@ impl<'a> UnitGenerator<'a, '_> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let named = if is_glob { "matches pattern" } else { "named" };
|
||||||
|
|
||||||
let mut msg = String::new();
|
let mut msg = String::new();
|
||||||
if !suggestion.is_empty() {
|
|
||||||
write!(
|
write!(
|
||||||
msg,
|
msg,
|
||||||
"no {} target {} `{}` in {}{}",
|
"no {target_desc} target {named} `{target_name}` in {unmatched_packages}{suggestion}",
|
||||||
target_desc,
|
|
||||||
if is_glob { "matches pattern" } else { "named" },
|
|
||||||
target_name,
|
|
||||||
unmatched_packages(),
|
|
||||||
suggestion,
|
|
||||||
)?;
|
)?;
|
||||||
append_targets_elsewhere(&mut msg, "\n")?;
|
if !targets_elsewhere.is_empty() {
|
||||||
|
append_targets_elsewhere(&mut msg)?;
|
||||||
|
} else if suggestion.is_empty() && !targets.is_empty() {
|
||||||
|
write!(msg, "\nhelp: available {} targets:", target_desc)?;
|
||||||
|
for (target_name, pkgs) in targets {
|
||||||
|
if pkgs.len() == 1 {
|
||||||
|
write!(msg, "\n {target_name}")?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(
|
for (pkg, _) in pkgs {
|
||||||
msg,
|
let pkg_name = pkg.name();
|
||||||
"no {} target {} `{}` in {}.",
|
write!(msg, "\n {target_name} in package {pkg_name}")?;
|
||||||
target_desc,
|
}
|
||||||
if is_glob { "matches pattern" } else { "named" },
|
|
||||||
target_name,
|
|
||||||
unmatched_packages()
|
|
||||||
)?;
|
|
||||||
|
|
||||||
append_targets_elsewhere(&mut msg, "")?;
|
|
||||||
if !targets.is_empty() && !need_append_targets_elsewhere {
|
|
||||||
writeln!(msg, "Available {} targets:", target_desc)?;
|
|
||||||
for target in targets {
|
|
||||||
writeln!(msg, " {}", target.name())?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
use std::fmt::Write as _;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
@ -69,10 +70,20 @@ pub fn run(
|
|||||||
names.join(", ")
|
names.join(", ")
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!(
|
let mut message = "`cargo run` can run at most one executable, but \
|
||||||
"`cargo run` can run at most one executable, but \
|
|
||||||
multiple were specified"
|
multiple were specified"
|
||||||
)
|
.to_owned();
|
||||||
|
write!(&mut message, "\nhelp: available targets:")?;
|
||||||
|
for (pkg, bin) in &bins {
|
||||||
|
write!(
|
||||||
|
&mut message,
|
||||||
|
"\n {} `{}` in package `{}`",
|
||||||
|
bin.kind().description(),
|
||||||
|
bin.name(),
|
||||||
|
pkg.name()
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
anyhow::bail!(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1337,11 +1337,10 @@ fn cargo_compile_with_filename() {
|
|||||||
p.cargo("build --bin bin.rs")
|
p.cargo("build --bin bin.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `bin.rs` in default-run packages.
|
[ERROR] no bin target named `bin.rs` in default-run packages
|
||||||
Available bin targets:
|
[HELP] available bin targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
@ -1358,11 +1357,10 @@ Available bin targets:
|
|||||||
p.cargo("build --example example.rs")
|
p.cargo("build --example example.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `example.rs` in default-run packages.
|
[ERROR] no example target named `example.rs` in default-run packages
|
||||||
Available example targets:
|
[HELP] available example targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
@ -623,11 +623,10 @@ automatically infer them to be a target, such as in subfolders.
|
|||||||
|
|
||||||
For more information on this warning you can consult
|
For more information on this warning you can consult
|
||||||
https://github.com/rust-lang/cargo/issues/5330
|
https://github.com/rust-lang/cargo/issues/5330
|
||||||
[ERROR] no example target named `a` in default-run packages.
|
[ERROR] no example target named `a` in default-run packages
|
||||||
Available example targets:
|
[HELP] available example targets:
|
||||||
do_magic
|
do_magic
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -655,11 +654,10 @@ fn run_example_autodiscover_2015_with_autoexamples_disabled() {
|
|||||||
p.cargo("run --example a")
|
p.cargo("run --example a")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `a` in default-run packages.
|
[ERROR] no example target named `a` in default-run packages
|
||||||
Available example targets:
|
[HELP] available example targets:
|
||||||
do_magic
|
do_magic
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -743,11 +741,10 @@ fn run_with_filename() {
|
|||||||
p.cargo("run --bin bin.rs")
|
p.cargo("run --bin bin.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `bin.rs` in default-run packages.
|
[ERROR] no bin target named `bin.rs` in default-run packages
|
||||||
Available bin targets:
|
[HELP] available bin targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
@ -764,11 +761,10 @@ Available bin targets:
|
|||||||
p.cargo("run --example example.rs")
|
p.cargo("run --example example.rs")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `example.rs` in default-run packages.
|
[ERROR] no example target named `example.rs` in default-run packages
|
||||||
Available example targets:
|
[HELP] available example targets:
|
||||||
a
|
a
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
@ -783,6 +779,235 @@ Available example targets:
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
fn ambiguous_bin_name() {
|
||||||
|
let p = project()
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = ["crate1", "crate2", "crate3", "crate4"]
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate1/src/bin/ambiguous.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate1/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate2/src/bin/ambiguous.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate2/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate2"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate3/src/bin/ambiguous.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate3/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate3"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate4/src/bin/ambiguous.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate4/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate4"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
let p = p.build();
|
||||||
|
|
||||||
|
p.cargo("run --bin ambiguous")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] `cargo run` can run at most one executable, but multiple were specified
|
||||||
|
[HELP] available targets:
|
||||||
|
bin `ambiguous` in package `crate1`
|
||||||
|
bin `ambiguous` in package `crate2`
|
||||||
|
bin `ambiguous` in package `crate3`
|
||||||
|
bin `ambiguous` in package `crate4`
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("run --bin crate1/ambiguous")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate1/ambiguous` in default-run packages
|
||||||
|
[HELP] available bin targets:
|
||||||
|
ambiguous in package crate1
|
||||||
|
ambiguous in package crate2
|
||||||
|
ambiguous in package crate3
|
||||||
|
ambiguous in package crate4
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// See rust-lang/cargo#14544
|
||||||
|
#[cargo_test]
|
||||||
|
fn print_available_targets_within_virtual_workspace() {
|
||||||
|
let p = project()
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = ["crate1", "crate2", "pattern1", "pattern2"]
|
||||||
|
|
||||||
|
default-members = ["crate1"]
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate1/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate1/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("crate2/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"crate2/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "crate2"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("pattern1/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"pattern1/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "pattern1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("pattern2/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"pattern2/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "pattern2"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("another/src/main.rs", "fn main(){}")
|
||||||
|
.file(
|
||||||
|
"another/Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "another"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let p = p.build();
|
||||||
|
p.cargo("run --bin")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] "--bin" takes one argument.
|
||||||
|
Available binaries:
|
||||||
|
crate1
|
||||||
|
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("run -p crate1 --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in `crate1` package
|
||||||
|
|
||||||
|
[HELP] a target with a similar name exists: `crate1`
|
||||||
|
[HELP] available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("check -p crate1 -p pattern1 -p pattern2 --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in `crate1`, ... packages
|
||||||
|
|
||||||
|
[HELP] a target with a similar name exists: `crate1`
|
||||||
|
[HELP] available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("run --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in default-run packages
|
||||||
|
|
||||||
|
[HELP] a target with a similar name exists: `crate1`
|
||||||
|
[HELP] available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("check --bin pattern*")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target matches pattern `pattern*` in default-run packages
|
||||||
|
[HELP] available bin in `pattern1` package:
|
||||||
|
pattern1
|
||||||
|
[HELP] available bin in `pattern2` package:
|
||||||
|
pattern2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// This another branch that none of similar name exists, and print available targets in the
|
||||||
|
// default-members.
|
||||||
|
p.change_file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = ["crate1", "crate2", "another"]
|
||||||
|
|
||||||
|
default-members = ["another"]
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
p.cargo("run --bin crate2")
|
||||||
|
.with_status(101)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] no bin target named `crate2` in default-run packages
|
||||||
|
[HELP] available bin in `crate2` package:
|
||||||
|
crate2
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn either_name_or_example() {
|
fn either_name_or_example() {
|
||||||
let p = project()
|
let p = project()
|
||||||
@ -794,6 +1019,9 @@ fn either_name_or_example() {
|
|||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] `cargo run` can run at most one executable, but multiple were specified
|
[ERROR] `cargo run` can run at most one executable, but multiple were specified
|
||||||
|
[HELP] available targets:
|
||||||
|
bin `a` in package `foo`
|
||||||
|
example `b` in package `foo`
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
@ -2447,16 +2447,14 @@ fn bad_example() {
|
|||||||
p.cargo("run --example foo")
|
p.cargo("run --example foo")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no example target named `foo` in default-run packages.
|
[ERROR] no example target named `foo` in default-run packages
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
p.cargo("run --bin foo")
|
p.cargo("run --bin foo")
|
||||||
.with_status(101)
|
.with_status(101)
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
[ERROR] no bin target named `foo` in default-run packages.
|
[ERROR] no bin target named `foo` in default-run packages
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
@ -2716,152 +2716,3 @@ fn nonexistence_package_together_with_workspace() {
|
|||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See rust-lang/cargo#14544
|
|
||||||
#[cargo_test]
|
|
||||||
fn print_available_targets_within_virtual_workspace() {
|
|
||||||
let p = project()
|
|
||||||
.file(
|
|
||||||
"Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[workspace]
|
|
||||||
resolver = "3"
|
|
||||||
members = ["crate1", "crate2", "pattern1", "pattern2"]
|
|
||||||
|
|
||||||
default-members = ["crate1"]
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.file("crate1/src/main.rs", "fn main(){}")
|
|
||||||
.file(
|
|
||||||
"crate1/Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[package]
|
|
||||||
name = "crate1"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.file("crate2/src/main.rs", "fn main(){}")
|
|
||||||
.file(
|
|
||||||
"crate2/Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[package]
|
|
||||||
name = "crate2"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.file("pattern1/src/main.rs", "fn main(){}")
|
|
||||||
.file(
|
|
||||||
"pattern1/Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[package]
|
|
||||||
name = "pattern1"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.file("pattern2/src/main.rs", "fn main(){}")
|
|
||||||
.file(
|
|
||||||
"pattern2/Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[package]
|
|
||||||
name = "pattern2"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.file("another/src/main.rs", "fn main(){}")
|
|
||||||
.file(
|
|
||||||
"another/Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[package]
|
|
||||||
name = "another"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
|
|
||||||
let p = p.build();
|
|
||||||
p.cargo("run --bin")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr_data(str![[r#"
|
|
||||||
[ERROR] "--bin" takes one argument.
|
|
||||||
Available binaries:
|
|
||||||
crate1
|
|
||||||
|
|
||||||
|
|
||||||
"#]])
|
|
||||||
.run();
|
|
||||||
|
|
||||||
p.cargo("run -p crate1 --bin crate2")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr_data(str![[r#"
|
|
||||||
[ERROR] no bin target named `crate2` in `crate1` package
|
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `crate1`
|
|
||||||
[HELP] Available bin in `crate2` package:
|
|
||||||
crate2
|
|
||||||
|
|
||||||
"#]])
|
|
||||||
.run();
|
|
||||||
|
|
||||||
p.cargo("check -p crate1 -p pattern1 -p pattern2 --bin crate2")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr_data(str![[r#"
|
|
||||||
[ERROR] no bin target named `crate2` in `crate1`, ... packages
|
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `crate1`
|
|
||||||
[HELP] Available bin in `crate2` package:
|
|
||||||
crate2
|
|
||||||
|
|
||||||
"#]])
|
|
||||||
.run();
|
|
||||||
|
|
||||||
p.cargo("run --bin crate2")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr_data(str![[r#"
|
|
||||||
[ERROR] no bin target named `crate2` in default-run packages
|
|
||||||
|
|
||||||
[HELP] a target with a similar name exists: `crate1`
|
|
||||||
[HELP] Available bin in `crate2` package:
|
|
||||||
crate2
|
|
||||||
|
|
||||||
"#]])
|
|
||||||
.run();
|
|
||||||
|
|
||||||
p.cargo("check --bin pattern*")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr_data(str![[r#"
|
|
||||||
[ERROR] no bin target matches pattern `pattern*` in default-run packages.
|
|
||||||
[HELP] Available bin in `pattern1` package:
|
|
||||||
pattern1
|
|
||||||
[HELP] Available bin in `pattern2` package:
|
|
||||||
pattern2
|
|
||||||
|
|
||||||
"#]])
|
|
||||||
.run();
|
|
||||||
|
|
||||||
// This another branch that none of similar name exists, and print available targets in the
|
|
||||||
// default-members.
|
|
||||||
p.change_file(
|
|
||||||
"Cargo.toml",
|
|
||||||
r#"
|
|
||||||
[workspace]
|
|
||||||
resolver = "3"
|
|
||||||
members = ["crate1", "crate2", "another"]
|
|
||||||
|
|
||||||
default-members = ["another"]
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
|
|
||||||
p.cargo("run --bin crate2")
|
|
||||||
.with_status(101)
|
|
||||||
.with_stderr_data(str![[r#"
|
|
||||||
[ERROR] no bin target named `crate2` in default-run packages.
|
|
||||||
[HELP] Available bin in `crate2` package:
|
|
||||||
crate2
|
|
||||||
|
|
||||||
"#]])
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user