Skip to content

Commit 1c5e68b

Browse files
committed
Include aliases with other commands
The principal result is that they are now automatically included in the `cargo --list` output. Fixes #8486.
1 parent 33edacd commit 1c5e68b

File tree

5 files changed

+51
-17
lines changed

5 files changed

+51
-17
lines changed

src/bin/cargo/cli.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'",
112112
drop_println!(config, " {}", name);
113113
}
114114
}
115+
CommandInfo::Alias { name, target } => {
116+
drop_println!(config, " {:<20} {}", name, target.iter().join(" "));
117+
}
115118
}
116119
}
117120
return Ok(());

src/bin/cargo/main.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![warn(clippy::redundant_clone)]
55

66
use cargo::core::shell::Shell;
7+
use cargo::util::toml::StringOrVec;
78
use cargo::util::CliError;
89
use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
910
use cargo_util::{ProcessBuilder, ProcessError};
@@ -127,15 +128,17 @@ fn list_commands(config: &Config) -> BTreeSet<CommandInfo> {
127128
});
128129
}
129130

130-
commands
131-
}
132-
133-
/// List all runnable aliases
134-
fn list_aliases(config: &Config) -> Vec<String> {
135-
match config.get::<BTreeMap<String, String>>("alias") {
136-
Ok(aliases) => aliases.keys().map(|a| a.to_string()).collect(),
137-
Err(_) => Vec::new(),
131+
// Add the user-defined aliases
132+
if let Ok(aliases) = config.get::<BTreeMap<String, StringOrVec>>("alias") {
133+
for (name, target) in aliases.iter() {
134+
commands.insert(CommandInfo::Alias {
135+
name: name.to_string(),
136+
target: target.clone(),
137+
});
138+
}
138139
}
140+
141+
commands
139142
}
140143

141144
fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
@@ -147,13 +150,11 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> Cli
147150
let command = match path {
148151
Some(command) => command,
149152
None => {
150-
let commands: Vec<String> = list_commands(config)
153+
let suggestions: Vec<_> = list_commands(config)
151154
.iter()
152155
.map(|c| c.name().to_string())
153156
.collect();
154-
let aliases = list_aliases(config);
155-
let suggestions = commands.iter().chain(aliases.iter());
156-
let did_you_mean = closest_msg(cmd, suggestions, |c| c);
157+
let did_you_mean = closest_msg(cmd, suggestions.iter(), |c| c);
157158
let err = anyhow::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean);
158159
return Err(CliError::new(err, 101));
159160
}

src/cargo/util/command_prelude.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ use crate::sources::CRATES_IO_REGISTRY;
66
use crate::util::important_paths::find_root_manifest_for_wd;
77
use crate::util::interning::InternedString;
88
use crate::util::restricted_names::is_glob_pattern;
9+
use crate::util::toml::{StringOrVec, TomlProfile};
10+
use crate::util::validate_package_name;
911
use crate::util::{
1012
print_available_benches, print_available_binaries, print_available_examples,
1113
print_available_packages, print_available_tests,
1214
};
13-
use crate::util::{toml::TomlProfile, validate_package_name};
1415
use crate::CargoResult;
1516
use anyhow::bail;
1617
use cargo_util::paths;
@@ -715,17 +716,19 @@ pub fn values_os(args: &ArgMatches<'_>, name: &str) -> Vec<OsString> {
715716
args._values_of_os(name)
716717
}
717718

718-
#[derive(PartialEq, PartialOrd, Eq, Ord)]
719+
#[derive(PartialEq, Eq, PartialOrd, Ord)]
719720
pub enum CommandInfo {
720721
BuiltIn { name: String, about: Option<String> },
721722
External { name: String, path: PathBuf },
723+
Alias { name: String, target: StringOrVec },
722724
}
723725

724726
impl CommandInfo {
725727
pub fn name(&self) -> &str {
726728
match self {
727729
CommandInfo::BuiltIn { name, .. } => name,
728730
CommandInfo::External { name, .. } => name,
731+
CommandInfo::Alias { name, .. } => name,
729732
}
730733
}
731734
}

src/cargo/util/toml/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,9 @@ impl TomlProfile {
760760
}
761761
}
762762

763-
#[derive(Clone, Debug, Serialize, Eq, PartialEq)]
763+
/// A StringOrVec can be parsed from either a TOML string or array,
764+
/// but is always stored as a vector.
765+
#[derive(Clone, Debug, Serialize, Eq, PartialEq, PartialOrd, Ord)]
764766
pub struct StringOrVec(Vec<String>);
765767

766768
impl<'de> de::Deserialize<'de> for StringOrVec {
@@ -797,6 +799,12 @@ impl<'de> de::Deserialize<'de> for StringOrVec {
797799
}
798800
}
799801

802+
impl StringOrVec {
803+
pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, String> {
804+
self.0.iter()
805+
}
806+
}
807+
800808
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
801809
#[serde(untagged, expecting = "expected a boolean or a string")]
802810
pub enum StringOrBool {

tests/testsuite/cargo_command.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::str;
1010
use cargo_test_support::cargo_process;
1111
use cargo_test_support::paths;
1212
use cargo_test_support::registry::Package;
13-
use cargo_test_support::{basic_bin_manifest, basic_manifest, cargo_exe, project};
13+
use cargo_test_support::{basic_bin_manifest, basic_manifest, cargo_exe, project, project_in_home};
1414

1515
fn path() -> Vec<PathBuf> {
1616
env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
@@ -32,7 +32,7 @@ fn list_commands_with_descriptions() {
3232
}
3333

3434
#[cargo_test]
35-
fn list_aliases_with_descriptions() {
35+
fn list_builtin_aliases_with_descriptions() {
3636
let p = project().build();
3737
p.cargo("--list")
3838
.with_stdout_contains(" b alias: build")
@@ -42,6 +42,25 @@ fn list_aliases_with_descriptions() {
4242
.run();
4343
}
4444

45+
#[cargo_test]
46+
fn list_custom_aliases_with_descriptions() {
47+
let p = project_in_home("proj")
48+
.file(
49+
&paths::home().join(".cargo").join("config"),
50+
r#"
51+
[alias]
52+
myaliasstr = "foo --bar"
53+
myaliasvec = ["foo", "--bar"]
54+
"#,
55+
)
56+
.build();
57+
58+
p.cargo("--list")
59+
.with_stdout_contains(" myaliasstr foo --bar")
60+
.with_stdout_contains(" myaliasvec foo --bar")
61+
.run();
62+
}
63+
4564
#[cargo_test]
4665
fn list_command_looks_at_path() {
4766
let proj = project()

0 commit comments

Comments
 (0)