mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
Auto merge of #10193 - sstangl:help-alias-10138, r=alexcrichton
Display alias target on 'cargo help <alias>` ``` Previously, `cargo help <alias>` resolved the alias and displayed the help for the targeted subcommand. For example, if `br` were aliased to `build --release`, `cargo help br` would display the manpage for cargo-build. With this patch, it will print "'br' is aliased to 'build --release'". ``` Addresses issue #10138. This is my first patch to Cargo. I attempted to follow the style of the surrounding code. Please let me know if any changes are required: happy to make them. In particular, I wasn't sure if any tests exist for this path.
This commit is contained in:
commit
c689f55b8c
@ -803,6 +803,15 @@ impl Execs {
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run_expect_error(&mut self) {
|
||||
self.ran = true;
|
||||
let p = (&self.process_builder).clone().unwrap();
|
||||
if self.match_process(&p).is_ok() {
|
||||
panic!("test was expected to fail, but succeeded running {}", p);
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the process, checks the expected output, and returns the first
|
||||
/// JSON object on stdout.
|
||||
#[track_caller]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::aliased_command;
|
||||
use cargo::util::errors::CargoResult;
|
||||
use cargo::Config;
|
||||
use cargo::{drop_println, Config};
|
||||
use cargo_util::paths::resolve_executable;
|
||||
use flate2::read::GzDecoder;
|
||||
use std::ffi::OsString;
|
||||
@ -15,14 +15,14 @@ const COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/man.tgz"
|
||||
/// This runs before clap processing, because it needs to intercept the `help`
|
||||
/// command if a man page is available.
|
||||
///
|
||||
/// Returns `true` if a man page was displayed. In this case, Cargo should
|
||||
/// exit.
|
||||
/// 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!("man failed: {:?}", e);
|
||||
log::warn!("help failed: {:?}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -46,11 +46,28 @@ fn try_help(config: &Config) -> CargoResult<bool> {
|
||||
Some(s) => s,
|
||||
None => return Ok(false),
|
||||
};
|
||||
// Check if this is a built-in command (or alias);
|
||||
|
||||
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 => {
|
||||
let alias = argv.join(" ");
|
||||
drop_println!(config, "`{}` is aliased to `{}`", subcommand, alias);
|
||||
return Ok(true);
|
||||
}
|
||||
// Otherwise, resolve the alias into its subcommand.
|
||||
Some(argv) => {
|
||||
// An alias with an empty argv can be created via `"empty-alias" = ""`.
|
||||
let first = argv.get(0).map(String::as_str).unwrap_or(subcommand);
|
||||
first.to_string()
|
||||
}
|
||||
None => subcommand.to_string(),
|
||||
};
|
||||
|
||||
let subcommand = match check_builtin(&subcommand) {
|
||||
Some(s) => s,
|
||||
None => return Ok(false),
|
||||
};
|
||||
|
||||
if resolve_executable(Path::new("man")).is_ok() {
|
||||
let man = match extract_man(&subcommand, "1") {
|
||||
Some(man) => man,
|
||||
@ -73,24 +90,18 @@ fn try_help(config: &Config) -> CargoResult<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Checks if the given subcommand is a built-in command (possibly via an alias).
|
||||
/// Checks if the given subcommand is an alias.
|
||||
///
|
||||
/// Returns None if it is not an alias.
|
||||
fn check_alias(config: &Config, subcommand: &str) -> Option<Vec<String>> {
|
||||
aliased_command(config, subcommand).ok().flatten()
|
||||
}
|
||||
|
||||
/// Checks if the given subcommand is a built-in command (not via an alias).
|
||||
///
|
||||
/// Returns None if it is not a built-in command.
|
||||
fn check_alias(config: &Config, subcommand: &str) -> Option<String> {
|
||||
if super::builtin_exec(subcommand).is_some() {
|
||||
return Some(subcommand.to_string());
|
||||
}
|
||||
match aliased_command(config, subcommand) {
|
||||
Ok(Some(alias)) => {
|
||||
let alias = alias.into_iter().next()?;
|
||||
if super::builtin_exec(&alias).is_some() {
|
||||
Some(alias)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
fn check_builtin(subcommand: &str) -> Option<&str> {
|
||||
super::builtin_exec(subcommand).map(|_| subcommand)
|
||||
}
|
||||
|
||||
/// Extracts the given man page from the compressed archive.
|
||||
|
@ -110,6 +110,20 @@ fn help_with_man_and_path(
|
||||
assert_eq!(stdout, contents);
|
||||
}
|
||||
|
||||
fn help_with_stdout_and_path(subcommand: &str, path: &Path) -> String {
|
||||
let output = process(&cargo_exe())
|
||||
.arg("help")
|
||||
.arg(subcommand)
|
||||
.env("PATH", path)
|
||||
.exec_with_output()
|
||||
.unwrap();
|
||||
assert!(output.status.success());
|
||||
let stderr = from_utf8(&output.stderr).unwrap();
|
||||
assert_eq!(stderr, "");
|
||||
let stdout = from_utf8(&output.stdout).unwrap();
|
||||
stdout.to_string()
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn help_man() {
|
||||
// Checks that `help command` displays the man page using the given command.
|
||||
@ -132,11 +146,25 @@ fn help_alias() {
|
||||
config,
|
||||
r#"
|
||||
[alias]
|
||||
my-alias = ["build", "--release"]
|
||||
empty-alias = ""
|
||||
simple-alias = "build"
|
||||
complex-alias = ["build", "--release"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
help_with_man_and_path("", "my-alias", "build", Path::new(""));
|
||||
|
||||
// The `empty-alias` returns an error.
|
||||
cargo_process("help empty-alias")
|
||||
.env("PATH", Path::new(""))
|
||||
.with_stderr_contains("[..]The subcommand 'empty-alias' wasn't recognized[..]")
|
||||
.run_expect_error();
|
||||
|
||||
// Because `simple-alias` aliases a subcommand with no arguments, help shows the manpage.
|
||||
help_with_man_and_path("", "simple-alias", "build", Path::new(""));
|
||||
|
||||
// Help for `complex-alias` displays the full alias command.
|
||||
let out = help_with_stdout_and_path("complex-alias", Path::new(""));
|
||||
assert_eq!(out, "`complex-alias` is aliased to `build --release`\n");
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user