Skip to content

Commit a668956

Browse files
committed
improve error message and add related tests
1 parent d4249c9 commit a668956

File tree

2 files changed

+98
-12
lines changed

2 files changed

+98
-12
lines changed

src/cargo/ops/common_for_install_and_uninstall.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -616,9 +616,9 @@ where
616616
let examples = candidates
617617
.iter()
618618
.filter(|cand| cand.targets().iter().filter(|t| t.is_example()).count() > 0);
619-
let pkg = match one(binaries, |v| multi_err("binaries", v))? {
619+
let pkg = match one(binaries, |v| multi_err("binaries", source, v))? {
620620
Some(p) => p,
621-
None => match one(examples, |v| multi_err("examples", v))? {
621+
None => match one(examples, |v| multi_err("examples", source, v))? {
622622
Some(p) => p,
623623
None => bail!(
624624
"no packages found with binaries or \
@@ -629,17 +629,23 @@ where
629629
Ok(pkg.clone())
630630
};
631631

632-
fn multi_err(kind: &str, mut pkgs: Vec<&Package>) -> String {
632+
fn multi_err<T>(kind: &str, source: &T, mut pkgs: Vec<&Package>) -> String
633+
where
634+
T: Source
635+
{
633636
pkgs.sort_unstable_by_key(|a| a.name());
637+
let first_pkg = pkgs.iter().nth(0).unwrap();
634638
format!(
635639
"multiple packages with {} found: {}. When installing a git repository, \
636-
cargo will always search the entire repo for any Cargo.toml. \
637-
Please specify which to install.",
640+
cargo will always search the entire repo for any Cargo.toml.\n\
641+
Please specify a package, e.g. `cargo install --git {} {}`.",
638642
kind,
639643
pkgs.iter()
640644
.map(|p| p.name().as_str())
641645
.collect::<Vec<_>>()
642-
.join(", ")
646+
.join(", "),
647+
source.source_id().url().as_str(),
648+
first_pkg.name()
643649
)
644650
}
645651
}

tests/testsuite/install.rs

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fs::{self, OpenOptions};
44
use std::io::prelude::*;
55
use std::path::Path;
66

7-
use cargo_test_support::compare;
7+
use cargo_test_support::{compare};
88
use cargo_test_support::cross_compile;
99
use cargo_test_support::git;
1010
use cargo_test_support::registry::{self, registry_path, Package};
@@ -560,28 +560,107 @@ Available binaries:
560560
}
561561

562562
#[cargo_test]
563-
fn multiple_crates_error() {
563+
fn multiple_binaries_error() {
564564
let p = git::repo(&paths::root().join("foo"))
565565
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
566566
.file("src/main.rs", "fn main() {}")
567567
.file("a/Cargo.toml", &basic_manifest("bar", "0.1.0"))
568568
.file("a/src/main.rs", "fn main() {}")
569569
.build();
570570

571+
let git_url = p.url().to_string();
571572
cargo_process("install --git")
572573
.arg(p.url().to_string())
573574
.with_status(101)
574575
.with_stderr(
575-
"\
576+
format!("\
576577
[UPDATING] git repository [..]
577578
[ERROR] multiple packages with binaries found: bar, foo. \
578-
When installing a git repository, cargo will always search the entire repo for any Cargo.toml. \
579-
Please specify which to install.
580-
",
579+
When installing a git repository, cargo will always search the entire repo for any Cargo.toml.\n\
580+
Please specify a package, e.g. `cargo install --git {git_url} bar`.
581+
"),
581582
)
582583
.run();
583584
}
584585

586+
#[cargo_test]
587+
fn multiple_examples_error() {
588+
let p = git::repo(&paths::root().join("foo"))
589+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
590+
.file("src/lib.rs", "")
591+
.file("examples/ex1.rs", "fn main() {}")
592+
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
593+
.file("bar/src/lib.rs", "")
594+
.file("bar/examples/ex1.rs", "fn main() {}",)
595+
.build();
596+
597+
let git_url = p.url().to_string();
598+
cargo_process("install --example ex1 --git")
599+
.arg(p.url().to_string())
600+
.with_status(101)
601+
.with_stderr(format!("\
602+
[UPDATING] git repository [..]
603+
[ERROR] multiple packages with examples found: bar, foo. \
604+
When installing a git repository, cargo will always search the entire repo for any Cargo.toml.\n\
605+
Please specify a package, e.g. `cargo install --git {git_url} bar`."))
606+
.run();
607+
}
608+
609+
#[cargo_test]
610+
fn multiple_binaries_deep_select_uses_package_name() {
611+
let p = git::repo(&paths::root().join("foo"))
612+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
613+
.file("src/main.rs", "fn main() {}")
614+
.file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
615+
.file("bar/baz/src/main.rs", "fn main() {}")
616+
.build();
617+
618+
cargo_process("install --git")
619+
.arg(p.url().to_string())
620+
.arg("baz")
621+
.run();
622+
}
623+
624+
#[cargo_test]
625+
fn multiple_binaries_in_selected_package_installs_all() {
626+
let p = git::repo(&paths::root().join("foo"))
627+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
628+
.file("src/lib.rs", "")
629+
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
630+
.file("bar/src/bin/bin1.rs", "fn main() {}")
631+
.file("bar/src/bin/bin2.rs", "fn main() {}")
632+
.build();
633+
634+
cargo_process("install --git")
635+
.arg(p.url().to_string())
636+
.arg("bar")
637+
.run();
638+
639+
let cargo_home = cargo_home();
640+
assert_has_installed_exe(&cargo_home, "bin1");
641+
assert_has_installed_exe(&cargo_home, "bin2");
642+
}
643+
644+
#[cargo_test]
645+
fn multiple_binaries_in_selected_package_with_bin_option_installs_only_one() {
646+
let p = git::repo(&paths::root().join("foo"))
647+
.file("Cargo.toml", &basic_manifest("foo", "0.1.0"))
648+
.file("src/lib.rs", "")
649+
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
650+
.file("bar/src/bin/bin1.rs", "fn main() {}")
651+
.file("bar/src/bin/bin2.rs", "fn main() {}")
652+
.build();
653+
654+
cargo_process("install --bin bin1 --git")
655+
.arg(p.url().to_string())
656+
.arg("bar")
657+
.run();
658+
659+
let cargo_home = cargo_home();
660+
assert_has_installed_exe(&cargo_home, "bin1");
661+
assert_has_not_installed_exe(&cargo_home, "bin2");
662+
}
663+
585664
#[cargo_test]
586665
fn multiple_crates_select() {
587666
let p = git::repo(&paths::root().join("foo"))
@@ -689,6 +768,7 @@ fn multiple_crates_auto_examples() {
689768
assert_has_installed_exe(cargo_home(), "foo");
690769
}
691770

771+
692772
#[cargo_test]
693773
fn no_binaries_or_examples() {
694774
let p = project()

0 commit comments

Comments
 (0)