Skip to content

Commit 9391bfb

Browse files
committed
Fix #10680, Fix #13702
1 parent 140911c commit 9391bfb

File tree

17 files changed

+138
-11
lines changed

17 files changed

+138
-11
lines changed

src/cargo/ops/cargo_add/mod.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,9 @@ fn resolve_dependency(
361361
};
362362
selected_dep = populate_dependency(selected_dep, arg);
363363

364-
let old_dep = get_existing_dependency(manifest, selected_dep.toml_key(), section)?;
364+
let lookup = |dep_key: &_| get_existing_dependency(manifest, dep_key, section);
365+
let old_dep = fuzzy_lookup(&mut selected_dep, lookup, gctx)?;
366+
365367
let mut dependency = if let Some(mut old_dep) = old_dep.clone() {
366368
if old_dep.name != selected_dep.name {
367369
// Assuming most existing keys are not relevant when the package changes
@@ -383,7 +385,8 @@ fn resolve_dependency(
383385
if dependency.source().is_none() {
384386
// Checking for a workspace dependency happens first since a member could be specified
385387
// in the workspace dependencies table as a dependency
386-
if let Some(_dep) = find_workspace_dep(dependency.toml_key(), ws.root_manifest()).ok() {
388+
let lookup = |toml_key: &_| Ok(find_workspace_dep(toml_key, ws.root_manifest()).ok());
389+
if let Some(_dep) = fuzzy_lookup(&mut dependency, lookup, gctx)? {
387390
dependency = dependency.set_source(WorkspaceSource::new());
388391
} else if let Some(package) = ws.members().find(|p| p.name().as_str() == dependency.name) {
389392
// Only special-case workspaces when the user doesn't provide any extra
@@ -449,6 +452,42 @@ fn resolve_dependency(
449452
Ok(dependency)
450453
}
451454

455+
fn fuzzy_lookup(
456+
dependency: &mut Dependency,
457+
lookup: impl Fn(&str) -> CargoResult<Option<Dependency>>,
458+
gctx: &GlobalContext,
459+
) -> CargoResult<Option<Dependency>> {
460+
if let Some(rename) = dependency.rename() {
461+
// Manually implement `toml_key` to restrict fuzzy lookups to only package names to mirror `PackageRegistry::query()`
462+
return lookup(rename);
463+
}
464+
465+
for name_permutation in [
466+
dependency.name.clone(),
467+
dependency.name.replace('-', "_"),
468+
dependency.name.replace('_', "-"),
469+
] {
470+
let Some(dep) = lookup(&name_permutation)? else {
471+
continue;
472+
};
473+
474+
if dependency.name != name_permutation {
475+
// Mirror the fuzzy matching policy of `PackageRegistry::query()`
476+
if !matches!(dep.source, Some(Source::Registry(_))) {
477+
continue;
478+
}
479+
gctx.shell().warn(format!(
480+
"translating `{}` to `{}`",
481+
dependency.name, &name_permutation,
482+
))?;
483+
dependency.name = name_permutation;
484+
}
485+
return Ok(Some(dep));
486+
}
487+
488+
Ok(None)
489+
}
490+
452491
/// When { workspace = true } you cannot define other keys that configure
453492
/// the source of the dependency such as `version`, `registry`, `registry-index`,
454493
/// `path`, `git`, `branch`, `tag`, `rev`, or `package`. You can also not define

tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[workspace]
2+
members = ["primary", "fuzzy_name"]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[package]
2+
name = "fuzzy_name"
3+
version = "0.0.0"
4+
edition = "2015"

tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/fuzzy_name/src/lib.rs

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "bar"
3+
version = "0.0.0"
4+
edition = "2015"
5+
6+
[dependencies]
7+
fuzzy_name = { path = "../fuzzy_name" }

tests/testsuite/cargo_add/add_workspace_non_fuzzy/in/primary/src/lib.rs

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::current_dir;
3+
use cargo_test_support::file;
4+
use cargo_test_support::prelude::*;
5+
use cargo_test_support::str;
6+
use cargo_test_support::Project;
7+
8+
#[cargo_test]
9+
fn case() {
10+
let project = Project::from_template(current_dir!().join("in"));
11+
let project_root = project.root();
12+
let cwd = &project_root;
13+
14+
snapbox::cmd::Command::cargo_ui()
15+
.arg("add")
16+
.args(["fuzzy-name", "-p", "bar"])
17+
.current_dir(cwd)
18+
.assert()
19+
.code(101)
20+
.stdout_eq(str![""])
21+
.stderr_eq(file!["stderr.term.svg"]);
22+
23+
assert_ui().subset_matches(current_dir!().join("out"), &project_root);
24+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[workspace]
2+
members = ["primary", "fuzzy_name"]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "bar"
3+
version = "0.0.0"
4+
edition = "2015"
5+
6+
[dependencies]
7+
fuzzy_name = { path = "../fuzzy_name" }

0 commit comments

Comments
 (0)