Skip to content

Commit ea1f525

Browse files
committed
Allow user aliases to override built-in aliases
1 parent ebd0ef1 commit ea1f525

File tree

6 files changed

+71
-41
lines changed

6 files changed

+71
-41
lines changed

src/bin/cargo/cli.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use clap::{AppSettings, Arg, ArgMatches};
44

55
use cargo::{self, CliResult, Config};
66

7+
use super::commands::{self, BuiltinExec};
78
use super::list_commands;
8-
use super::commands;
99
use command_prelude::*;
1010

1111
pub fn main(config: &mut Config) -> CliResult {
@@ -107,26 +107,34 @@ fn expand_aliases(
107107
commands::builtin_exec(cmd),
108108
super::aliased_command(config, cmd)?,
109109
) {
110-
(None, Some(mut alias)) => {
111-
alias.extend(
110+
(
111+
Some(BuiltinExec {
112+
alias_for: None, ..
113+
}),
114+
Some(_),
115+
) => {
116+
// User alias conflicts with a built-in subcommand
117+
config.shell().warn(format!(
118+
"user-defined alias `{}` is ignored, because it is shadowed by a built-in command",
119+
cmd,
120+
))?;
121+
}
122+
(_, Some(mut user_alias)) => {
123+
// User alias takes precedence over built-in aliases
124+
user_alias.extend(
112125
args.values_of("")
113126
.unwrap_or_default()
114127
.map(|s| s.to_string()),
115128
);
116129
let args = cli()
117130
.setting(AppSettings::NoBinaryName)
118-
.get_matches_from_safe(alias)?;
131+
.get_matches_from_safe(user_alias)?;
119132
return expand_aliases(config, args);
120133
}
121-
(Some(_), Some(_)) => {
122-
config.shell().warn(format!(
123-
"alias `{}` is ignored, because it is shadowed by a built in command",
124-
cmd
125-
))?;
126-
}
127134
(_, None) => {}
128135
}
129136
};
137+
130138
Ok(args)
131139
}
132140

@@ -152,11 +160,12 @@ fn execute_subcommand(config: &mut Config, args: &ArgMatches) -> CliResult {
152160
args.is_present("frozen"),
153161
args.is_present("locked"),
154162
arg_target_dir,
155-
&args.values_of_lossy("unstable-features")
163+
&args
164+
.values_of_lossy("unstable-features")
156165
.unwrap_or_default(),
157166
)?;
158167

159-
if let Some(exec) = commands::builtin_exec(cmd) {
168+
if let Some(BuiltinExec { exec, .. }) = commands::builtin_exec(cmd) {
160169
return exec(config, subcommand_args);
161170
}
162171

src/bin/cargo/commands/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use cargo::ops;
44

55
pub fn cli() -> App {
66
subcommand("build")
7-
.alias("b")
7+
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases()
8+
// .alias("b")
89
.about("Compile a local package and all of its dependencies")
910
.arg_package_spec(
1011
"Package to build (see `cargo help pkgid`)",

src/bin/cargo/commands/mod.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,15 @@ pub fn builtin() -> Vec<App> {
3535
]
3636
}
3737

38-
pub fn builtin_exec(cmd: &str) -> Option<fn(&mut Config, &ArgMatches) -> CliResult> {
39-
let f = match cmd {
38+
pub struct BuiltinExec<'a> {
39+
pub exec: fn(&'a mut Config, &'a ArgMatches) -> CliResult,
40+
pub alias_for: Option<&'static str>,
41+
}
42+
43+
pub fn builtin_exec(cmd: &str) -> Option<BuiltinExec> {
44+
let exec = match cmd {
4045
"bench" => bench::exec,
41-
"build" => build::exec,
46+
"build" | "b" => build::exec,
4247
"check" => check::exec,
4348
"clean" => clean::exec,
4449
"doc" => doc::exec,
@@ -57,19 +62,27 @@ pub fn builtin_exec(cmd: &str) -> Option<fn(&mut Config, &ArgMatches) -> CliResu
5762
"pkgid" => pkgid::exec,
5863
"publish" => publish::exec,
5964
"read-manifest" => read_manifest::exec,
60-
"run" => run::exec,
65+
"run" | "r" => run::exec,
6166
"rustc" => rustc::exec,
6267
"rustdoc" => rustdoc::exec,
6368
"search" => search::exec,
64-
"test" => test::exec,
69+
"test" | "t" => test::exec,
6570
"uninstall" => uninstall::exec,
6671
"update" => update::exec,
6772
"verify-project" => verify_project::exec,
6873
"version" => version::exec,
6974
"yank" => yank::exec,
7075
_ => return None,
7176
};
72-
Some(f)
77+
78+
let alias_for = match cmd {
79+
"b" => Some("build"),
80+
"r" => Some("run"),
81+
"t" => Some("test"),
82+
_ => None,
83+
};
84+
85+
Some(BuiltinExec { exec, alias_for })
7386
}
7487

7588
pub mod bench;

src/bin/cargo/commands/run.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use cargo::ops::{self, CompileFilter};
55

66
pub fn cli() -> App {
77
subcommand("run")
8-
.alias("r")
8+
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases()
9+
// .alias("r")
910
.setting(AppSettings::TrailingVarArg)
1011
.about("Run the main binary of the local package (src/main.rs)")
1112
.arg(Arg::with_name("args").multiple(true))

src/bin/cargo/commands/test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use cargo::ops::{self, CompileFilter};
44

55
pub fn cli() -> App {
66
subcommand("test")
7-
.alias("t")
7+
// subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases()
8+
// .alias("t")
89
.setting(AppSettings::TrailingVarArg)
910
.about("Execute all unit and integration tests of a local package")
1011
.arg(

tests/testsuite/cargo_alias_config.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,6 @@ expected a list, but found a integer for [..]",
2222
).run();
2323
}
2424

25-
#[test]
26-
fn alias_default_config_overrides_config() {
27-
let p = project()
28-
.file("Cargo.toml", &basic_bin_manifest("foo"))
29-
.file("src/main.rs", "fn main() {}")
30-
.file(
31-
".cargo/config",
32-
r#"
33-
[alias]
34-
b = "not_build"
35-
"#,
36-
).build();
37-
38-
p.cargo("b -v")
39-
.with_stderr_contains("[COMPILING] foo v0.5.0 [..]")
40-
.run();
41-
}
42-
4325
#[test]
4426
fn alias_config() {
4527
let p = project()
@@ -122,7 +104,7 @@ fn alias_with_flags_config() {
122104
}
123105

124106
#[test]
125-
fn cant_shadow_builtin() {
107+
fn alias_cannot_shadow_builtin_command() {
126108
let p = project()
127109
.file("Cargo.toml", &basic_bin_manifest("foo"))
128110
.file("src/main.rs", "fn main() {}")
@@ -137,9 +119,32 @@ fn cant_shadow_builtin() {
137119
p.cargo("build")
138120
.with_stderr(
139121
"\
140-
[WARNING] alias `build` is ignored, because it is shadowed by a built in command
122+
[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command
123+
[COMPILING] foo v0.5.0 ([..])
124+
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
125+
",
126+
).run();
127+
}
128+
129+
#[test]
130+
fn alias_override_builtin_alias() {
131+
let p = project()
132+
.file("Cargo.toml", &basic_bin_manifest("foo"))
133+
.file("src/main.rs", "fn main() {}")
134+
.file(
135+
".cargo/config",
136+
r#"
137+
[alias]
138+
b = "run"
139+
"#,
140+
).build();
141+
142+
p.cargo("b")
143+
.with_stderr(
144+
"\
141145
[COMPILING] foo v0.5.0 ([..])
142146
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
147+
[RUNNING] `target/debug/foo[EXE]`
143148
",
144149
).run();
145150
}

0 commit comments

Comments
 (0)