feat(install): check if given crate argument would be valid with inserted @ symbol, suggest fixed argument

This commit is contained in:
dawe 2025-04-21 18:14:40 +02:00
parent ab0d6a7bd2
commit 98326ac0f5
No known key found for this signature in database
4 changed files with 22 additions and 2 deletions

1
Cargo.lock generated
View File

@ -376,6 +376,7 @@ dependencies = [
"tracing-subscriber",
"unicase",
"unicode-width",
"unicode-xid",
"url",
"walkdir",
"windows-sys 0.59.0",

View File

@ -216,6 +216,7 @@ tracing = { workspace = true, features = ["attributes"] }
tracing-subscriber.workspace = true
unicase.workspace = true
unicode-width.workspace = true
unicode-xid.workspace = true
url.workspace = true
walkdir.workspace = true

View File

@ -8,6 +8,7 @@ use cargo::ops;
use cargo::util::IntoUrl;
use cargo::util::VersionExt;
use cargo::CargoResult;
use cargo_util_schemas::manifest::PackageName;
use itertools::Itertools;
use semver::VersionReq;
@ -133,6 +134,22 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
.collect::<crate::CargoResult<Vec<_>>>()?;
for (crate_name, _) in krates.iter() {
let package_name = PackageName::new(crate_name);
if !crate_name.contains("@") && package_name.is_err() {
for (idx, ch) in crate_name.char_indices() {
if !(unicode_xid::UnicodeXID::is_xid_continue(ch) || ch == '-') {
let mut suggested_crate_name = crate_name.to_string();
suggested_crate_name.insert_str(idx, "@");
if let Ok((_, Some(_))) = parse_crate(&suggested_crate_name.as_str()) {
let err = package_name.unwrap_err();
return Err(
anyhow::format_err!("{err}\n\n\
help: if this is meant to be a package name followed by a version, insert an `@` like `{suggested_crate_name}`").into());
}
}
}
}
if let Some(toolchain) = crate_name.strip_prefix("+") {
return Err(anyhow!(
"invalid character `+` in package name: `+{toolchain}`

View File

@ -402,8 +402,9 @@ fn missing_at_symbol_before_version() {
cargo_process("install foo=0.2.0")
.with_status(101)
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[ERROR] could not find `foo=0.2.0` in registry `crates-io` with version `*`
[ERROR] invalid character `=` in package name: `foo=0.2.0`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)
[HELP] if this is meant to be a package name followed by a version, insert an `@` like `foo@=0.2.0`
"#]])
.run();