Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List available packages if providing --package with an empty value #8808

Merged
merged 12 commits into from
Oct 28, 2020
15 changes: 13 additions & 2 deletions src/cargo/util/command_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::util::restricted_names::is_glob_pattern;
use crate::util::{paths, toml::TomlProfile, validate_package_name};
use crate::util::{
print_available_benches, print_available_binaries, print_available_examples,
print_available_tests,
print_available_packages, print_available_tests,
};
use crate::CargoResult;
use anyhow::bail;
Expand Down Expand Up @@ -52,7 +52,7 @@ pub trait AppExt: Sized {
}

fn arg_package_spec_simple(self, package: &'static str) -> Self {
self._arg(multi_opt("package", "SPEC", package).short("p"))
self._arg(optional_multi_opt("package", "SPEC", package).short("p"))
}

fn arg_package(self, package: &'static str) -> Self {
Expand Down Expand Up @@ -498,6 +498,13 @@ pub trait ArgMatchesExt {

if let Some(ws) = workspace {
self.check_optional_opts(ws, &opts)?;
} else if self.is_present_with_zero_values("package") {
// As for cargo 0.50.0, this won't occur but if someone sneaks in
// we can still provide this informative message for them.
anyhow::bail!(
"\"--package <SPEC>\" requires a SPEC format value.\n\
Run `cargo help pkgid` for more infomation about SPEC format."
)
}

Ok(opts)
Expand Down Expand Up @@ -588,6 +595,10 @@ about this warning.";
workspace: &Workspace<'_>,
compile_opts: &CompileOptions,
) -> CargoResult<()> {
if self.is_present_with_zero_values("package") {
print_available_packages(workspace)?
}

if self.is_present_with_zero_values("example") {
print_available_examples(workspace, compile_opts)?;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub use self::to_semver::ToSemver;
pub use self::vcs::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
pub use self::workspace::{
print_available_benches, print_available_binaries, print_available_examples,
print_available_tests,
print_available_packages, print_available_tests,
};

mod canonical_url;
Expand Down
40 changes: 31 additions & 9 deletions src/cargo/util/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn get_available_targets<'a>(
filter_fn: fn(&Target) -> bool,
ws: &'a Workspace<'_>,
options: &'a CompileOptions,
) -> CargoResult<Vec<&'a Target>> {
) -> CargoResult<Vec<&'a str>> {
let packages = options.spec.get_packages(ws)?;

let mut targets: Vec<_> = packages
Expand All @@ -19,14 +19,15 @@ fn get_available_targets<'a>(
.iter()
.filter(|target| filter_fn(target))
})
.map(Target::name)
.collect();

targets.sort();

Ok(targets)
}

fn print_available(
fn print_available_targets(
filter_fn: fn(&Target) -> bool,
ws: &Workspace<'_>,
options: &CompileOptions,
Expand All @@ -38,29 +39,50 @@ fn print_available(
let mut output = String::new();
writeln!(output, "\"{}\" takes one argument.", option_name)?;

if targets.is_empty() {
print_availables(output, &targets, plural_name)
}

fn print_availables(output: String, availables: &[&str], plural_name: &str) -> CargoResult<()> {
let mut output = output;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn print_availables(output: String, availables: &[&str], plural_name: &str) -> CargoResult<()> {
let mut output = output;
fn print_availables(mut output: String, availables: &[&str], plural_name: &str) -> CargoResult<()> {

if availables.is_empty() {
writeln!(output, "No {} available.", plural_name)?;
} else {
writeln!(output, "Available {}:", plural_name)?;
for target in targets {
writeln!(output, " {}", target.name())?;
for available in availables {
writeln!(output, " {}", available)?;
}
}
bail!("{}", output)
}

pub fn print_available_packages(ws: &Workspace<'_>) -> CargoResult<()> {
let packages = ws
.members()
.map(|pkg| pkg.name().as_str())
.collect::<Vec<_>>();

let mut output = String::new();
writeln!(
output,
"\"--package <SPEC>\" requires a SPEC format value.\n\
Run `cargo help pkgid` for more infomation about SPEC format."
)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut output = String::new();
writeln!(
output,
"\"--package <SPEC>\" requires a SPEC format value.\n\
Run `cargo help pkgid` for more infomation about SPEC format."
)?;
let output = "\"--package <SPEC>\" requires a SPEC format value.\n\
Run `cargo help pkgid` for more infomation about SPEC format.\n"
.to_string();


print_availables(output, &packages, "packages")
}

pub fn print_available_examples(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {
print_available(Target::is_example, ws, options, "--example", "examples")
print_available_targets(Target::is_example, ws, options, "--example", "examples")
}

pub fn print_available_binaries(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {
print_available(Target::is_bin, ws, options, "--bin", "binaries")
print_available_targets(Target::is_bin, ws, options, "--bin", "binaries")
}

pub fn print_available_benches(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {
print_available(Target::is_bench, ws, options, "--bench", "benches")
print_available_targets(Target::is_bench, ws, options, "--bench", "benches")
}

pub fn print_available_tests(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {
print_available(Target::is_test, ws, options, "--test", "tests")
print_available_targets(Target::is_test, ws, options, "--test", "tests")
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
//! Tests for target filter flags giving suggestions on which targets are available.
//! Tests for packages/target filter flags giving suggestions on which
//! packages/targets are available.

use cargo_test_support::project;

const EXAMPLE: u8 = 0x1;
const BIN: u8 = 0x2;
const TEST: u8 = 0x4;
const BENCH: u8 = 0x8;
const EXAMPLE: u8 = 1 << 0;
const BIN: u8 = 1 << 1;
const TEST: u8 = 1 << 2;
const BENCH: u8 = 1 << 3;
const PACKAGE: u8 = 1 << 4;

fn list_targets_test(command: &str, targets: u8) {
fn list_availables_test(command: &str, targets: u8) {
let full_project = project()
.file("examples/a.rs", "fn main() { }")
.file("examples/b.rs", "fn main() { }")
Expand Down Expand Up @@ -75,6 +77,22 @@ Available tests:
test1
test2

",
)
.with_status(101)
.run();
}

if targets & PACKAGE != 0 {
full_project
.cargo(&format!("{} -p", command))
.with_stderr(
"\
[ERROR] \"--package <SPEC>\" requires a SPEC format value.
Run `cargo help pkgid` for more infomation about SPEC format.
Available packages:
foo

",
)
.with_status(101)
Expand Down Expand Up @@ -141,51 +159,51 @@ No tests available.
}

#[cargo_test]
fn build_list_targets() {
list_targets_test("build", EXAMPLE | BIN | TEST | BENCH);
fn build_list_availables() {
list_availables_test("build", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
}

#[cargo_test]
fn check_list_targets() {
list_targets_test("check", EXAMPLE | BIN | TEST | BENCH);
fn check_list_availables() {
list_availables_test("check", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
}

#[cargo_test]
fn doc_list_targets() {
list_targets_test("doc", BIN);
fn doc_list_availables() {
list_availables_test("doc", BIN | PACKAGE);
}

#[cargo_test]
fn fix_list_targets() {
list_targets_test("fix", EXAMPLE | BIN | TEST | BENCH);
fn fix_list_availables() {
list_availables_test("fix", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
}

#[cargo_test]
fn run_list_targets() {
list_targets_test("run", EXAMPLE | BIN);
fn run_list_availables() {
list_availables_test("run", EXAMPLE | BIN);
}

#[cargo_test]
fn test_list_targets() {
list_targets_test("test", EXAMPLE | BIN | TEST | BENCH);
fn test_list_availables() {
list_availables_test("test", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
}

#[cargo_test]
fn bench_list_targets() {
list_targets_test("bench", EXAMPLE | BIN | TEST | BENCH);
fn bench_list_availables() {
list_availables_test("bench", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
}

#[cargo_test]
fn install_list_targets() {
list_targets_test("install", EXAMPLE | BIN);
fn install_list_availables() {
list_availables_test("install", EXAMPLE | BIN);
}

#[cargo_test]
fn rustdoc_list_targets() {
list_targets_test("rustdoc", EXAMPLE | BIN | TEST | BENCH);
fn rustdoc_list_availables() {
list_availables_test("rustdoc", EXAMPLE | BIN | TEST | BENCH);
}

#[cargo_test]
fn rustc_list_targets() {
list_targets_test("rustc", EXAMPLE | BIN | TEST | BENCH);
fn rustc_list_availables() {
list_availables_test("rustc", EXAMPLE | BIN | TEST | BENCH);
}
2 changes: 1 addition & 1 deletion tests/testsuite/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ mod init;
mod install;
mod install_upgrade;
mod jobserver;
mod list_targets;
mod list_availables;
mod local_registry;
mod locate_project;
mod lockfile_compat;
Expand Down