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

Add support for cargo bench (Fixes #9) #12

Merged
merged 2 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 21 additions & 32 deletions src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const DEFAULT_CARGO_ARGS: &[&str] = &["--message-format=json", "--quiet"];
pub(crate) enum CmdKind {
Run,
Test,
Bench,
}

impl CmdKind {
Expand All @@ -21,6 +22,7 @@ impl CmdKind {
match s {
"run" => Some(Run),
"test" => Some(Test),
"bench" => Some(Bench),
_ => None,
}
}
Expand All @@ -30,6 +32,7 @@ impl CmdKind {
match self {
CmdKind::Run => "build",
CmdKind::Test => "test",
CmdKind::Bench => "bench",
}
}
}
Expand Down Expand Up @@ -194,48 +197,34 @@ pub(crate) fn select_buildopt<'a>(
opts: impl IntoIterator<Item = &'a BuildOpt>,
cmd_kind: CmdKind,
) -> Result<&'a BuildOpt, Error> {
let opts = opts.into_iter();

// Target kinds we want to look for
let look_for = &[TargetKind::Bin, TargetKind::Example, TargetKind::Test];
let is_test = cmd_kind == CmdKind::Test;

// Find candidates with the possible target types
let mut candidates = opts
let candidates: Vec<_> = opts
.into_iter()
.filter(|opt| {
// When run as a test we only care about the binary where the profile
// is set as `test`
if is_test {
opt.profile.test
} else {
opt.target
// When run as a test or bench we only care about the
// binary where the profile is set as `test`
match cmd_kind {
CmdKind::Test | CmdKind::Bench => opt.profile.test,
CmdKind::Run => opt
.target
.kind
.iter()
.any(|kind| look_for.iter().any(|lkind| lkind == kind))
.any(|kind| look_for.iter().any(|lkind| lkind == kind)),
}
})
.peekable();

// Get the first candidate
let first = candidates
.next()
.ok_or_else(|| err_msg("Found no possible candidates"))?;

// We found more than one candidate
if candidates.peek().is_some() {
// Make a error string including all the possible candidates
let candidates_str: String = iter::once(first)
.chain(candidates)
.map(|opt| format!("\t- {} ({})\n", opt.target.name, opt.target.kind[0]))
.collect();

if is_test {
Err(format_err!("Found more than one possible candidate:\n\n{}\n\nPlease use `--test`, `--example`, `--bin` or `--lib` to specify exactly what binary you want to examine", candidates_str))?
} else {
Err(format_err!("Found more than one possible candidate:\n\n{}\n\nPlease use `--example` or `--bin` to specify exactly what binary you want to examine", candidates_str))?
}
.collect();
// We expect exactly one candidate; everything else is an error
match candidates.as_slice() {
[] => Err(err_msg("No suitable build artifacts found.")),
[the_one] => Ok(the_one),
the_many => Err(format_err!(
"Found several artifact candidates: \n :{:?}",
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should still print an error messages which suggests ways to solve the error (when many artifacts are found). E.g "Please use --test [...]".

Copy link
Owner Author

Choose a reason for hiding this comment

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

I am out of time for today, but will look into this in the next few days

the_many
)),
}
Ok(first)
}

impl BuildOpt {
Expand Down
21 changes: 13 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ fn process_matches<'a>(
}

fn create_app<'a, 'b>() -> App<'a, 'b> {
let usage = concat!(
let with_usage = concat!(
"<with-cmd> 'Command executed with the cargo-created binary. ",
"Use {bin} to denote the binary. ",
"If omitted the {bin} is added as the last argument'"
"The placeholders {bin} {args} denote the path to the binary and additional arguments.",
"If omitted `{bin} {args}` is appended to `with-cmd`'"
);
let cargo_usage = "<cargo-cmd> 'The Cargo subcommand starting with `test`, `run`, or `bench`'";
App::new(COMMAND_NAME)
.about(COMMAND_DESCRIPTION)
// We have to lie about our binary name since this will be a third party
Expand All @@ -68,11 +69,15 @@ fn create_app<'a, 'b>() -> App<'a, 'b> {
.subcommand(
SubCommand::with_name(COMMAND_NAME)
.about(COMMAND_DESCRIPTION)
.arg(Arg::from_usage(&usage))
.arg(
clap::Arg::from_usage("<cargo-cmd> 'The cargo subcommand `test` or `run`'")
.raw(true),
),
.arg(Arg::from_usage(&with_usage))
.arg(clap::Arg::from_usage(cargo_usage).raw(true))
.after_help(r#"
EXAMPLES:
cargo with echo -- run
cargo with "gdb --args" -- run
cargo with "echo {args} {bin}" -- test -- myargs
"#
)
)
.settings(&[AppSettings::SubcommandRequired])
}
Expand Down