Skip to content

Commit 2b6302b

Browse files
committed
feat(install): check if given crate argument would be valid with inserted @ symbol, suggest fixed argument
1 parent a70997e commit 2b6302b

File tree

4 files changed

+22
-2
lines changed

4 files changed

+22
-2
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ tracing = { workspace = true, features = ["attributes"] }
216216
tracing-subscriber.workspace = true
217217
unicase.workspace = true
218218
unicode-width.workspace = true
219+
unicode-xid.workspace = true
219220
url.workspace = true
220221
walkdir.workspace = true
221222

src/bin/cargo/commands/install.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use cargo::ops;
88
use cargo::util::IntoUrl;
99
use cargo::util::VersionExt;
1010
use cargo::CargoResult;
11+
use cargo_util_schemas::manifest::PackageName;
1112
use itertools::Itertools;
1213
use semver::VersionReq;
1314

@@ -133,6 +134,22 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
133134
.collect::<crate::CargoResult<Vec<_>>>()?;
134135

135136
for (crate_name, _) in krates.iter() {
137+
let package_name = PackageName::new(crate_name);
138+
if !crate_name.contains("@") && package_name.is_err() {
139+
for (idx, ch) in crate_name.char_indices() {
140+
if !(unicode_xid::UnicodeXID::is_xid_continue(ch) || ch == '-') {
141+
let mut suggested_crate_name = crate_name.to_string();
142+
suggested_crate_name.insert_str(idx, "@");
143+
if let Ok((_, Some(_))) = parse_crate(&suggested_crate_name.as_str()) {
144+
let err = package_name.unwrap_err();
145+
return Err(
146+
anyhow::format_err!("{err}\n\n\
147+
help: if this is meant to be a package name followed by a version, insert an `@` like `{suggested_crate_name}`").into());
148+
}
149+
}
150+
}
151+
}
152+
136153
if let Some(toolchain) = crate_name.strip_prefix("+") {
137154
return Err(anyhow!(
138155
"invalid character `+` in package name: `+{toolchain}`

tests/testsuite/install.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,9 @@ fn missing_at_symbol_before_version() {
402402
cargo_process("install foo=0.2.0")
403403
.with_status(101)
404404
.with_stderr_data(str![[r#"
405-
[UPDATING] `dummy-registry` index
406-
[ERROR] could not find `foo=0.2.0` in registry `crates-io` with version `*`
405+
[ERROR] invalid character `=` in package name: `foo=0.2.0`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
406+
407+
[HELP] if this is meant to be a package name followed by a version, insert an `@` like `foo@=0.2.0`
407408
408409
"#]])
409410
.run();

0 commit comments

Comments
 (0)