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;