diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index c6f71847df38..7ef5bc3fd06a 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -361,7 +361,9 @@ fn resolve_dependency( }; selected_dep = populate_dependency(selected_dep, arg); - let old_dep = get_existing_dependency(manifest, selected_dep.toml_key(), section)?; + let lookup = |dep_key: &_| get_existing_dependency(manifest, dep_key, section); + let old_dep = fuzzy_lookup(&mut selected_dep, lookup, gctx)?; + let mut dependency = if let Some(mut old_dep) = old_dep.clone() { if old_dep.name != selected_dep.name { // Assuming most existing keys are not relevant when the package changes @@ -383,7 +385,8 @@ fn resolve_dependency( if dependency.source().is_none() { // Checking for a workspace dependency happens first since a member could be specified // in the workspace dependencies table as a dependency - if let Some(_dep) = find_workspace_dep(dependency.toml_key(), ws.root_manifest()).ok() { + let lookup = |toml_key: &_| Ok(find_workspace_dep(toml_key, ws.root_manifest()).ok()); + if let Some(_dep) = fuzzy_lookup(&mut dependency, lookup, gctx)? { dependency = dependency.set_source(WorkspaceSource::new()); } else if let Some(package) = ws.members().find(|p| p.name().as_str() == dependency.name) { // Only special-case workspaces when the user doesn't provide any extra @@ -449,6 +452,45 @@ fn resolve_dependency( Ok(dependency) } +fn fuzzy_lookup( + dependency: &mut Dependency, + lookup: impl Fn(&str) -> CargoResult>, + gctx: &GlobalContext, +) -> CargoResult> { + if let Some(rename) = dependency.rename() { + // If it has a rename only lookup that name - analogue to Dependency::toml_key() + return lookup(rename); + } + + for name_permutation in [ + dependency.name.clone(), + dependency.name.replace('-', "_"), + dependency.name.replace('_', "-"), + ] + .into_iter() + .dedup() + { + let Some(dep) = lookup(&name_permutation)? else { + continue; + }; + + if dependency.name != name_permutation { + // Ignore fuzzy matches with non-registry sources + if !matches!(dep.source, Some(Source::Registry(_))) { + continue; + } + gctx.shell().warn(format!( + "translating `{}` to `{}`", + dependency.name, &name_permutation, + ))?; + dependency.name = name_permutation; + } + return Ok(Some(dep)); + } + + Ok(None) +} + /// When { workspace = true } you cannot define other keys that configure /// the source of the dependency such as `version`, `registry`, `registry-index`, /// `path`, `git`, `branch`, `tag`, `rev`, or `package`. You can also not define diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.lock b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.lock new file mode 100644 index 000000000000..8c304c1c338a --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.lock @@ -0,0 +1,11 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bar" +version = "0.0.0" + +[[package]] +name = "fuzzy_name" +version = "0.0.0" diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.toml b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.toml new file mode 100644 index 000000000000..fcfea321a63d --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["primary", "fuzzy_name"] diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/fuzzy_name/Cargo.toml b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/fuzzy_name/Cargo.toml new file mode 100644 index 000000000000..4c2f380e12f5 --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/fuzzy_name/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "fuzzy_name" +version = "0.0.0" +edition = "2015" diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/fuzzy_name/src/lib.rs b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/fuzzy_name/src/lib.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/primary/Cargo.toml b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/primary/Cargo.toml new file mode 100644 index 000000000000..85cf9b05ced6 --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/primary/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bar" +version = "0.0.0" +edition = "2015" + +[dependencies] +fuzzy_name = { path = "../fuzzy_name" } diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/primary/src/lib.rs b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/primary/src/lib.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/mod.rs b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/mod.rs new file mode 100644 index 000000000000..19c865242225 --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["fuzzy-name", "-p", "bar"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/Cargo.toml b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/Cargo.toml new file mode 100644 index 000000000000..fcfea321a63d --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["primary", "fuzzy_name"] diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/primary/Cargo.toml b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/primary/Cargo.toml new file mode 100644 index 000000000000..85cf9b05ced6 --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/primary/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bar" +version = "0.0.0" +edition = "2015" + +[dependencies] +fuzzy_name = { path = "../fuzzy_name" } diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/primary/src/lib.rs b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/out/primary/src/lib.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_add/add_workspace_non_fuzzy/stderr.term.svg b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/stderr.term.svg new file mode 100644 index 000000000000..6c9588b1a203 --- /dev/null +++ b/tests/testsuite/cargo_add/add_workspace_non_fuzzy/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating crates.io index + + error: the crate `fuzzy-name` could not be found in registry index. + + + + + + diff --git a/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/out/primary/Cargo.toml b/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/out/primary/Cargo.toml index 1ae5f7b63618..22737f576822 100644 --- a/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/out/primary/Cargo.toml +++ b/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/out/primary/Cargo.toml @@ -4,4 +4,4 @@ version = "0.0.0" edition = "2015" [dependencies] -fuzzy_dependency = "1.0.0" +fuzzy_dependency.workspace = true diff --git a/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/stderr.term.svg b/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/stderr.term.svg index 2530de071942..a2a8a98f0e84 100644 --- a/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/stderr.term.svg +++ b/tests/testsuite/cargo_add/detect_workspace_inherit_fuzzy/stderr.term.svg @@ -19,11 +19,11 @@ - Updating `dummy-registry` index + warning: translating `fuzzy-dependency` to `fuzzy_dependency` - warning: translating `fuzzy-dependency` to `fuzzy_dependency` + Updating `dummy-registry` index - Adding fuzzy_dependency v1.0.0 to dependencies + Adding fuzzy_dependency (workspace) to dependencies Locking 1 package to latest compatible version diff --git a/tests/testsuite/cargo_add/features_fuzzy/out/Cargo.toml b/tests/testsuite/cargo_add/features_fuzzy/out/Cargo.toml index a50d1f6d256d..42049792df28 100644 --- a/tests/testsuite/cargo_add/features_fuzzy/out/Cargo.toml +++ b/tests/testsuite/cargo_add/features_fuzzy/out/Cargo.toml @@ -6,4 +6,4 @@ version = "0.0.0" edition = "2015" [dependencies] -your_face = { version = "99999.0.0" } +your_face = { version = "99999.0.0", features = ["eyes"] } diff --git a/tests/testsuite/cargo_add/features_fuzzy/stderr.term.svg b/tests/testsuite/cargo_add/features_fuzzy/stderr.term.svg index 8f5778eb5c3a..70eb9fefc9cc 100644 --- a/tests/testsuite/cargo_add/features_fuzzy/stderr.term.svg +++ b/tests/testsuite/cargo_add/features_fuzzy/stderr.term.svg @@ -20,17 +20,17 @@ - Updating `dummy-registry` index + warning: translating `your-face` to `your_face` - warning: translating `your-face` to `your_face` + Updating `dummy-registry` index Adding your_face v99999.0.0 to dependencies Features: - - ears + + eyes - - eyes + - ears - mouth diff --git a/tests/testsuite/cargo_add/mod.rs b/tests/testsuite/cargo_add/mod.rs index efe5680431ab..8207d5fd387e 100644 --- a/tests/testsuite/cargo_add/mod.rs +++ b/tests/testsuite/cargo_add/mod.rs @@ -4,6 +4,7 @@ mod add_no_vendored_package_with_alter_registry; mod add_no_vendored_package_with_vendor; mod add_normalized_name_external; mod add_toolchain; +mod add_workspace_non_fuzzy; mod build; mod build_prefer_existing_version; mod change_rename_target;