Auto merge of #5715 - euclio:third-party-help, r=alexcrichton

help: display external subcommand help

When invoking `cargo help <subcommand>`, if the subcommand isn't found, but it *is* an external subcommand, call that subcommand with `--help`.

A test should probably be written for this, but I'm not sure how best to mock an external subcommand.
This commit is contained in:
bors 2018-07-13 22:02:09 +00:00
commit 738c42d4dc
3 changed files with 52 additions and 6 deletions

View File

@ -9,7 +9,19 @@ use super::commands;
use command_prelude::*;
pub fn main(config: &mut Config) -> CliResult {
let args = cli().get_matches_safe()?;
let args = match cli().get_matches_safe() {
Ok(args) => args,
Err(e) => {
if e.kind == clap::ErrorKind::UnrecognizedSubcommand {
// An unrecognized subcommand might be an external subcommand.
let cmd = &e.info.as_ref().unwrap()[0].to_owned();
return super::execute_external_subcommand(config, cmd, &[cmd, "--help"])
.map_err(|_| e.into());
} else {
return Err(e)?;
}
}
};
if args.value_of("unstable-features") == Some("help") {
println!(

View File

@ -91,13 +91,24 @@ the `.d` files alongside the artifacts.
Cargo is designed to be extensible with new subcommands without having to modify
Cargo itself. This is achieved by translating a cargo invocation of the form
cargo `(?<command>[^ ]+)` into an invocation of an external tool
`cargo-${command}` that then needs to be present in one of the user's `$PATH`
directories.
`cargo-${command}`. The external tool must be present in one of the user's
`$PATH` directories.
Custom subcommand may use `CARGO` environment variable to call back to
When Cargo invokes a custom subcommand, the first argument to the subcommand
will be the filename of the custom subcommand, as usual. The second argument
will be the subcommand name itself. For example, the second argument would be
`${command}` when invoking `cargo-${command}`. Any additional arguments on the
command line will be forwarded unchanged.
Cargo can also display the help output of a custom subcommand with `cargo help
${command}`. Cargo assumes that the subcommand will print a help message if its
third argument is `--help`. So, `cargo help ${command}` would invoke
`cargo-${command} ${command} --help`.
Custom subcommands may use the `CARGO` environment variable to call back to
Cargo. Alternatively, it can link to `cargo` crate as a library, but this
approach has drawbacks:
* Cargo as a library is unstable, API changes without deprecation,
* Cargo as a library is unstable: the API may change without deprecation
* versions of Cargo library and Cargo binary may be different.
* versions of the linked Cargo library may be different from the Cargo binary

View File

@ -322,6 +322,29 @@ fn cargo_help() {
);
}
#[test]
fn cargo_help_external_subcommand() {
Package::new("cargo-fake-help", "1.0.0")
.file(
"src/main.rs",
r#"
fn main() {
if ::std::env::args().nth(2) == Some(String::from("--help")) {
println!("fancy help output");
}
}"#,
)
.publish();
assert_that(
cargo_process().args(&["install", "cargo-fake-help"]),
execs().with_status(0),
);
assert_that(
cargo_process().args(&["help", "fake-help"]),
execs().with_status(0).with_stdout("fancy help output\n")
);
}
#[test]
fn explain() {
assert_that(