unicode-xid = "0.2.0"
url = "2.2.2"
walkdir = "2.2"
-clap = "3.2.1"
+clap = "3.2.18"
unicode-width = "0.1.5"
openssl = { version = '0.10.11', optional = true }
im-rc = "15.0.0"
use anyhow::anyhow;
use cargo::core::{features, CliUnstable};
use cargo::{self, drop_print, drop_println, CliResult, Config};
-use clap::{
- error::{ContextKind, ContextValue},
- AppSettings, Arg, ArgMatches,
-};
+use clap::{AppSettings, Arg, ArgMatches};
use itertools::Itertools;
use std::collections::HashMap;
use std::fmt::Write;
// In general, try to avoid loading config values unless necessary (like
// the [alias] table).
- if commands::help::handle_embedded_help(config) {
- return Ok(());
- }
-
- let args = match cli().try_get_matches() {
- Ok(args) => args,
- Err(e) => {
- if e.kind() == clap::ErrorKind::UnrecognizedSubcommand {
- // An unrecognized subcommand might be an external subcommand.
- let cmd = e
- .context()
- .find_map(|c| match c {
- (ContextKind::InvalidSubcommand, &ContextValue::String(ref cmd)) => {
- Some(cmd)
- }
- _ => None,
- })
- .expect("UnrecognizedSubcommand implies the presence of InvalidSubcommand");
- return super::execute_external_subcommand(config, cmd, &[cmd, "--help"])
- .map_err(|_| e.into());
- } else {
- return Err(e.into());
- }
- }
- };
+ let args = cli().try_get_matches()?;
// Global args need to be extracted before expanding aliases because the
// clap code for extracting a subcommand discards global options
}
}
-fn cli() -> App {
+pub fn cli() -> App {
let is_rustup = std::env::var_os("RUSTUP_HOME").is_some();
let usage = if is_rustup {
"cargo [+toolchain] [OPTIONS] [SUBCOMMAND]"
// Doesn't mix well with our list of common cargo commands. See clap-rs/clap#3108 for
// opening clap up to allow us to style our help template
.disable_colored_help(true)
+ // Provide a custom help subcommand for calling into man pages
+ .disable_help_subcommand(true)
.override_usage(usage)
.help_template(
"\
use crate::aliased_command;
+use crate::command_prelude::*;
use cargo::util::errors::CargoResult;
use cargo::{drop_println, Config};
use cargo_util::paths::resolve_executable;
const COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/man.tgz"));
-/// Checks if the `help` command is being issued.
-///
-/// This runs before clap processing, because it needs to intercept the `help`
-/// command if a man page is available.
-///
-/// Returns `true` if help information was successfully displayed to the user.
-/// In this case, Cargo should exit.
-pub fn handle_embedded_help(config: &Config) -> bool {
- match try_help(config) {
- Ok(true) => true,
- Ok(false) => false,
- Err(e) => {
- log::warn!("help failed: {:?}", e);
- false
- }
- }
+pub fn cli() -> App {
+ subcommand("help")
+ .about("Displays help for a cargo subcommand")
+ .arg(Arg::new("SUBCOMMAND"))
}
-fn try_help(config: &Config) -> CargoResult<bool> {
- let mut args = std::env::args_os()
- .skip(1)
- .skip_while(|arg| arg.to_str().map_or(false, |s| s.starts_with('-')));
- if !args
- .next()
- .map_or(false, |arg| arg.to_str() == Some("help"))
- {
- return Ok(false);
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+ let subcommand = args.get_one::<String>("SUBCOMMAND");
+ if let Some(subcommand) = subcommand {
+ if !try_help(config, subcommand)? {
+ crate::execute_external_subcommand(config, subcommand, &[subcommand, "--help"])?;
+ }
+ } else {
+ let mut cmd = crate::cli::cli();
+ let _ = cmd.print_help();
}
- let subcommand = match args.next() {
- Some(arg) => arg,
- None => return Ok(false),
- };
- let subcommand = match subcommand.to_str() {
- Some(s) => s,
- None => return Ok(false),
- };
+ Ok(())
+}
+fn try_help(config: &Config, subcommand: &str) -> CargoResult<bool> {
let subcommand = match check_alias(config, subcommand) {
// If this alias is more than a simple subcommand pass-through, show the alias.
Some(argv) if argv.len() > 1 => {
fix::cli(),
generate_lockfile::cli(),
git_checkout::cli(),
+ help::cli(),
init::cli(),
install::cli(),
locate_project::cli(),
"fix" => fix::exec,
"generate-lockfile" => generate_lockfile::exec,
"git-checkout" => git_checkout::exec,
+ "help" => help::exec,
"init" => init::exec,
"install" => install::exec,
"locate-project" => locate_project::exec,