diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index e431a5939..d4da7276b 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -261,6 +261,21 @@ fn expand_aliases( } (None, None) => {} (_, Some(mut alias)) => { + // Check if this alias is shadowing an external subcommand + // (binary of the form `cargo-`) + // Currently this is only a warning, but after a transition period this will become + // a hard error. + if let Some(path) = super::find_external_subcommand(config, cmd) { + config.shell().warn(format!( + "\ +user-defined alias `{}` is shadowing an external subcommand found at: `{}` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 .", + cmd, + path.display(), + ))?; + } + alias.extend( args.values_of("") .unwrap_or_default() diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 58056aa83..57895b766 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -147,12 +147,16 @@ fn list_commands(config: &Config) -> BTreeMap { commands } -fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult { +fn find_external_subcommand(config: &Config, cmd: &str) -> Option { let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX); - let path = search_directories(config) + search_directories(config) .iter() .map(|dir| dir.join(&command_exe)) - .find(|file| is_executable(file)); + .find(|file| is_executable(file)) +} + +fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult { + let path = find_external_subcommand(config, cmd); let command = match path { Some(command) => command, None => { diff --git a/tests/testsuite/cargo_alias_config.rs b/tests/testsuite/cargo_alias_config.rs index 6e2804fd2..6777aeabf 100644 --- a/tests/testsuite/cargo_alias_config.rs +++ b/tests/testsuite/cargo_alias_config.rs @@ -76,6 +76,38 @@ fn dependent_alias() { .run(); } +#[cargo_test] +fn alias_shadowing_external_subcommand() { + let echo = echo_subcommand(); + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config", + r#" + [alias] + echo = "build" + "#, + ) + .build(); + + let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); + paths.push(echo.target_debug_dir()); + let path = env::join_paths(paths).unwrap(); + + p.cargo("echo") + .env("PATH", &path) + .with_stderr("\ +[WARNING] user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 . +[COMPILING] foo v0.5.0 [..] +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", + ) + .run(); +} + #[cargo_test] fn default_args_alias() { let echo = echo_subcommand(); @@ -100,14 +132,24 @@ fn default_args_alias() { p.cargo("echo") .env("PATH", &path) .with_status(101) - .with_stderr("error: alias echo has unresolvable recursive definition: echo -> echo") + .with_stderr("\ +[WARNING] user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 . +error: alias echo has unresolvable recursive definition: echo -> echo +", + ) .run(); p.cargo("test-1") .env("PATH", &path) .with_status(101) - .with_stderr( - "error: alias test-1 has unresolvable recursive definition: test-1 -> echo -> echo", + .with_stderr("\ +[WARNING] user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 . +error: alias test-1 has unresolvable recursive definition: test-1 -> echo -> echo +", ) .run();