Fix built-in aliases taking arguments.

This commit is contained in:
Eric Huss 2018-12-05 09:29:10 -08:00
parent d27b47baf6
commit e8f37daeff
8 changed files with 52 additions and 59 deletions

View File

@ -4,7 +4,7 @@ use clap::{AppSettings, Arg, ArgMatches};
use cargo::{self, CliResult, Config}; use cargo::{self, CliResult, Config};
use super::commands::{self, BuiltinExec}; use super::commands;
use super::list_commands; use super::list_commands;
use command_prelude::*; use command_prelude::*;
@ -107,28 +107,22 @@ fn expand_aliases(
commands::builtin_exec(cmd), commands::builtin_exec(cmd),
super::aliased_command(config, cmd)?, super::aliased_command(config, cmd)?,
) { ) {
( (Some(_), Some(_)) => {
Some(BuiltinExec {
alias_for: None, ..
}),
Some(_),
) => {
// User alias conflicts with a built-in subcommand // User alias conflicts with a built-in subcommand
config.shell().warn(format!( config.shell().warn(format!(
"user-defined alias `{}` is ignored, because it is shadowed by a built-in command", "user-defined alias `{}` is ignored, because it is shadowed by a built-in command",
cmd, cmd,
))?; ))?;
} }
(_, Some(mut user_alias)) => { (_, Some(mut alias)) => {
// User alias takes precedence over built-in aliases alias.extend(
user_alias.extend(
args.values_of("") args.values_of("")
.unwrap_or_default() .unwrap_or_default()
.map(|s| s.to_string()), .map(|s| s.to_string()),
); );
let args = cli() let args = cli()
.setting(AppSettings::NoBinaryName) .setting(AppSettings::NoBinaryName)
.get_matches_from_safe(user_alias)?; .get_matches_from_safe(alias)?;
return expand_aliases(config, args); return expand_aliases(config, args);
} }
(_, None) => {} (_, None) => {}
@ -165,7 +159,7 @@ fn execute_subcommand(config: &mut Config, args: &ArgMatches) -> CliResult {
.unwrap_or_default(), .unwrap_or_default(),
)?; )?;
if let Some(BuiltinExec { exec, .. }) = commands::builtin_exec(cmd) { if let Some(exec) = commands::builtin_exec(cmd) {
return exec(config, subcommand_args); return exec(config, subcommand_args);
} }

View File

@ -4,7 +4,7 @@ use cargo::ops;
pub fn cli() -> App { pub fn cli() -> App {
subcommand("build") subcommand("build")
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() // subcommand aliases are handled in aliased_command()
// .alias("b") // .alias("b")
.about("Compile a local package and all of its dependencies") .about("Compile a local package and all of its dependencies")
.arg_package_spec( .arg_package_spec(

View File

@ -4,7 +4,7 @@ use cargo::ops;
pub fn cli() -> App { pub fn cli() -> App {
subcommand("check") subcommand("check")
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() // subcommand aliases are handled in aliased_command()
// .alias("c") // .alias("c")
.about("Check a local package and all of its dependencies for errors") .about("Check a local package and all of its dependencies for errors")
.arg_package_spec( .arg_package_spec(

View File

@ -35,16 +35,11 @@ pub fn builtin() -> Vec<App> {
] ]
} }
pub struct BuiltinExec<'a> { pub fn builtin_exec(cmd: &str) -> Option<fn(&mut Config, &ArgMatches) -> CliResult> {
pub exec: fn(&'a mut Config, &'a ArgMatches) -> CliResult, let f = match cmd {
pub alias_for: Option<&'static str>,
}
pub fn builtin_exec(cmd: &str) -> Option<BuiltinExec> {
let exec = match cmd {
"bench" => bench::exec, "bench" => bench::exec,
"build" | "b" => build::exec, "build" => build::exec,
"check" | "c" => check::exec, "check" => check::exec,
"clean" => clean::exec, "clean" => clean::exec,
"doc" => doc::exec, "doc" => doc::exec,
"fetch" => fetch::exec, "fetch" => fetch::exec,
@ -62,11 +57,11 @@ pub fn builtin_exec(cmd: &str) -> Option<BuiltinExec> {
"pkgid" => pkgid::exec, "pkgid" => pkgid::exec,
"publish" => publish::exec, "publish" => publish::exec,
"read-manifest" => read_manifest::exec, "read-manifest" => read_manifest::exec,
"run" | "r" => run::exec, "run" => run::exec,
"rustc" => rustc::exec, "rustc" => rustc::exec,
"rustdoc" => rustdoc::exec, "rustdoc" => rustdoc::exec,
"search" => search::exec, "search" => search::exec,
"test" | "t" => test::exec, "test" => test::exec,
"uninstall" => uninstall::exec, "uninstall" => uninstall::exec,
"update" => update::exec, "update" => update::exec,
"verify-project" => verify_project::exec, "verify-project" => verify_project::exec,
@ -74,16 +69,7 @@ pub fn builtin_exec(cmd: &str) -> Option<BuiltinExec> {
"yank" => yank::exec, "yank" => yank::exec,
_ => return None, _ => return None,
}; };
Some(f)
let alias_for = match cmd {
"b" => Some("build"),
"c" => Some("check"),
"r" => Some("run"),
"t" => Some("test"),
_ => None,
};
Some(BuiltinExec { exec, alias_for })
} }
pub mod bench; pub mod bench;

View File

@ -5,7 +5,7 @@ use cargo::ops::{self, CompileFilter};
pub fn cli() -> App { pub fn cli() -> App {
subcommand("run") subcommand("run")
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() // subcommand aliases are handled in aliased_command()
// .alias("r") // .alias("r")
.setting(AppSettings::TrailingVarArg) .setting(AppSettings::TrailingVarArg)
.about("Run the main binary of the local package (src/main.rs)") .about("Run the main binary of the local package (src/main.rs)")

View File

@ -4,7 +4,7 @@ use cargo::ops::{self, CompileFilter};
pub fn cli() -> App { pub fn cli() -> App {
subcommand("test") subcommand("test")
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() // subcommand aliases are handled in aliased_command()
// .alias("t") // .alias("t")
.setting(AppSettings::TrailingVarArg) .setting(AppSettings::TrailingVarArg)
.about("Execute all unit and integration tests of a local package") .about("Execute all unit and integration tests of a local package")

View File

@ -63,28 +63,27 @@ fn main() {
fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> { fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
let alias_name = format!("alias.{}", command); let alias_name = format!("alias.{}", command);
let mut result = Ok(None); let user_alias = match config.get_string(&alias_name) {
match config.get_string(&alias_name) { Ok(Some(record)) => Some(
Ok(value) => { record
if let Some(record) = value {
let alias_commands = record
.val .val
.split_whitespace() .split_whitespace()
.map(|s| s.to_string()) .map(|s| s.to_string())
.collect(); .collect(),
result = Ok(Some(alias_commands)); ),
} Ok(None) => None,
} Err(_) => config
Err(_) => { .get_list(&alias_name)?
let value = config.get_list(&alias_name)?; .map(|record| record.val.iter().map(|s| s.0.to_string()).collect()),
if let Some(record) = value { };
let alias_commands: Vec<String> = let result = user_alias.or_else(|| match command {
record.val.iter().map(|s| s.0.to_string()).collect(); "b" => Some(vec!["build".to_string()]),
result = Ok(Some(alias_commands)); "c" => Some(vec!["check".to_string()]),
} "r" => Some(vec!["run".to_string()]),
} "t" => Some(vec!["test".to_string()]),
} _ => None,
result });
Ok(result)
} }
/// List all runnable commands /// List all runnable commands

View File

@ -148,3 +148,17 @@ fn alias_override_builtin_alias() {
", ",
).run(); ).run();
} }
#[test]
fn builtin_alias_takes_options() {
// #6381
let p = project()
.file("src/lib.rs", "")
.file(
"examples/ex1.rs",
r#"fn main() { println!("{}", std::env::args().skip(1).next().unwrap()) }"#,
)
.build();
p.cargo("r --example ex1 -- asdf").with_stdout("asdf").run();
}