diff --git a/src/bin/cargo/commands/add.rs b/src/bin/cargo/commands/add.rs index 90c4f4dd5..52fc38b74 100644 --- a/src/bin/cargo/commands/add.rs +++ b/src/bin/cargo/commands/add.rs @@ -242,7 +242,20 @@ fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult>(); + let mut infer_crate_name = false; + + for (crate_name, _) in crates.iter() { + let crate_name = crate_name.as_ref().unwrap(); + + if let Some(toolchain) = crate_name.strip_prefix("+") { + anyhow::bail!( + "invalid character `+` in dependency name: `+{toolchain}` + Use `cargo +{toolchain} add` if you meant to use the `{toolchain}` toolchain." + ); + } + } + if crates.is_empty() { if path.is_some() || git.is_some() { crates.insert(None, None); diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index 8197a1690..3bb90c2d5 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -1,5 +1,6 @@ use crate::command_prelude::*; +use anyhow::anyhow; use cargo::core::{GitReference, SourceId, Workspace}; use cargo::ops; use cargo::util::IntoUrl; @@ -108,6 +109,16 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { .map(|k| resolve_crate(k, version)) .collect::>>()?; + for (crate_name, _) in krates.iter() { + if let Some(toolchain) = crate_name.strip_prefix("+") { + return Err(anyhow!( + "invalid character `+` in package name: `+{toolchain}` + Use `cargo +{toolchain} install` if you meant to use the `{toolchain}` toolchain." + ) + .into()); + } + } + let mut from_cwd = false; let source = if let Some(url) = args.get_one::("git") { diff --git a/tests/testsuite/cargo_add/add_toolchain/in b/tests/testsuite/cargo_add/add_toolchain/in new file mode 120000 index 000000000..6c6a27fcf --- /dev/null +++ b/tests/testsuite/cargo_add/add_toolchain/in @@ -0,0 +1 @@ +../add-basic.in \ No newline at end of file diff --git a/tests/testsuite/cargo_add/add_toolchain/mod.rs b/tests/testsuite/cargo_add/add_toolchain/mod.rs new file mode 100644 index 000000000..905b8c8a2 --- /dev/null +++ b/tests/testsuite/cargo_add/add_toolchain/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::Project; + +use cargo_test_support::curr_dir; + +#[cargo_test] +fn case() { + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("+nightly") + .current_dir(cwd) + .assert() + .failure() + .stdout_matches_path(curr_dir!().join("stdout.log")) + .stderr_matches_path(curr_dir!().join("stderr.log")); + + assert_ui().subset_matches(curr_dir!().join("out"), &project_root); +} diff --git a/tests/testsuite/cargo_add/add_toolchain/out/Cargo.toml b/tests/testsuite/cargo_add/add_toolchain/out/Cargo.toml new file mode 100644 index 000000000..3ecdb6681 --- /dev/null +++ b/tests/testsuite/cargo_add/add_toolchain/out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] + +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" diff --git a/tests/testsuite/cargo_add/add_toolchain/stderr.log b/tests/testsuite/cargo_add/add_toolchain/stderr.log new file mode 100644 index 000000000..0593685ad --- /dev/null +++ b/tests/testsuite/cargo_add/add_toolchain/stderr.log @@ -0,0 +1,2 @@ +error: invalid character `+` in dependency name: `+nightly` + Use `cargo +nightly add` if you meant to use the `nightly` toolchain. diff --git a/tests/testsuite/cargo_add/add_toolchain/stdout.log b/tests/testsuite/cargo_add/add_toolchain/stdout.log new file mode 100644 index 000000000..e69de29bb diff --git a/tests/testsuite/cargo_add/mod.rs b/tests/testsuite/cargo_add/mod.rs index 4a03220dd..be7a1546b 100644 --- a/tests/testsuite/cargo_add/mod.rs +++ b/tests/testsuite/cargo_add/mod.rs @@ -1,6 +1,7 @@ mod add_basic; mod add_multiple; mod add_normalized_name_external; +mod add_toolchain; mod build; mod build_prefer_existing_version; mod change_rename_target; diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index 9b881dfdc..2609d8048 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -57,6 +57,20 @@ fn simple() { assert_has_not_installed_exe(cargo_home(), "foo"); } +#[cargo_test] +fn toolchain() { + pkg("foo", "0.0.1"); + + cargo_process("install +nightly") + .with_status(101) + .with_stderr( + "\ +[ERROR] invalid character `+` in package name: `+nightly` + Use `cargo +nightly install` if you meant to use the `nightly` toolchain.", + ) + .run(); +} + #[cargo_test] fn simple_with_message_format() { pkg("foo", "0.0.1");