From 4420152be28704f0780dc06f1871a3af0452a525 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 26 Apr 2022 16:33:27 -0500 Subject: [PATCH 1/2] Extract finding a workspace dependency into its own function --- src/cargo/ops/cargo_add/mod.rs | 50 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index b49a4df251d..3ea5212b1cf 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -543,31 +543,7 @@ fn populate_available_features( let query = dependency.query(config)?; let query = match query { MaybeWorkspace::Workspace(_workspace) => { - let manifest = LocalManifest::try_new(ws.root_manifest())?; - let manifest = manifest - .data - .as_item() - .as_table_like() - .context("could not make `manifest.data` into a table")?; - let workspace = manifest - .get("workspace") - .context("could not find `workspace`")? - .as_table_like() - .context("could not make `manifest.data.workspace` into a table")?; - let dependencies = workspace - .get("dependencies") - .context("could not find `dependencies` table in `workspace`")? - .as_table_like() - .context("could not make `dependencies` into a table")?; - let dep_item = dependencies.get(dependency.toml_key()).context(format!( - "could not find {} in `workspace.dependencies`", - dependency.toml_key() - ))?; - let dep = Dependency::from_toml( - ws.root_manifest().parent().unwrap(), - dependency.toml_key(), - dep_item, - )?; + let dep = find_workspace_dep(dependency.toml_key(), ws.root_manifest())?; if let Some(features) = dep.features.clone() { dependency = dependency.set_inherited_features(features); } @@ -712,3 +688,27 @@ fn is_sorted(mut it: impl Iterator) -> bool { true } + +fn find_workspace_dep(toml_key: &str, root_manifest: &Path) -> CargoResult { + let manifest = LocalManifest::try_new(root_manifest)?; + let manifest = manifest + .data + .as_item() + .as_table_like() + .context("could not make `manifest.data` into a table")?; + let workspace = manifest + .get("workspace") + .context("could not find `workspace`")? + .as_table_like() + .context("could not make `manifest.data.workspace` into a table")?; + let dependencies = workspace + .get("dependencies") + .context("could not find `dependencies` table in `workspace`")? + .as_table_like() + .context("could not make `dependencies` into a table")?; + let dep_item = dependencies.get(toml_key).context(format!( + "could not find {} in `workspace.dependencies`", + toml_key + ))?; + Dependency::from_toml(root_manifest.parent().unwrap(), toml_key, dep_item) +} From bfb9def0e9f4abb095f48efefc770592c1c22df6 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 26 Apr 2022 16:41:12 -0500 Subject: [PATCH 2/2] Detect `cargo add foo` will inherit a workspace dependency --- src/cargo/ops/cargo_add/mod.rs | 8 ++- .../detect_workspace_inherit.in/Cargo.toml | 5 ++ .../dependency/Cargo.toml | 3 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 5 ++ .../primary/src/lib.rs | 0 .../detect_workspace_inherit.out/Cargo.toml | 5 ++ .../dependency/Cargo.toml | 3 + .../primary/Cargo.toml | 8 +++ .../add/detect_workspace_inherit.stderr | 1 + .../add/detect_workspace_inherit.stdout | 0 .../Cargo.toml | 5 ++ .../dependency/Cargo.toml | 14 ++++ .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 5 ++ .../primary/src/lib.rs | 0 .../Cargo.toml | 5 ++ .../dependency/Cargo.toml | 14 ++++ .../primary/Cargo.toml | 8 +++ .../detect_workspace_inherit_features.stderr | 10 +++ .../detect_workspace_inherit_features.stdout | 0 .../Cargo.toml | 5 ++ .../dependency/Cargo.toml | 3 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 5 ++ .../primary/src/lib.rs | 0 .../Cargo.toml | 5 ++ .../dependency/Cargo.toml | 3 + .../primary/Cargo.toml | 8 +++ .../detect_workspace_inherit_optional.stderr | 1 + .../detect_workspace_inherit_optional.stdout | 0 tests/testsuite/cargo_add.rs | 71 +++++++++++++++++++ 32 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 tests/snapshots/add/detect_workspace_inherit.in/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/detect_workspace_inherit.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/detect_workspace_inherit.out/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit.stderr create mode 100644 tests/snapshots/add/detect_workspace_inherit.stdout create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.in/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.out/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.stderr create mode 100644 tests/snapshots/add/detect_workspace_inherit_features.stdout create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.in/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.out/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.stderr create mode 100644 tests/snapshots/add/detect_workspace_inherit_optional.stdout diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index 3ea5212b1cf..dff545f38a0 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -32,7 +32,7 @@ use dependency::RegistrySource; use dependency::Source; use manifest::LocalManifest; -use crate::ops::cargo_add::dependency::MaybeWorkspace; +use crate::ops::cargo_add::dependency::{MaybeWorkspace, WorkspaceSource}; pub use manifest::DepTable; /// Information on what dependencies should be added @@ -281,7 +281,11 @@ fn resolve_dependency( }; if dependency.source().is_none() { - if let Some(package) = ws.members().find(|p| p.name().as_str() == dependency.name) { + // 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() { + 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 // information, otherwise, trust the user. let mut src = PathSource::new(package.root()); diff --git a/tests/snapshots/add/detect_workspace_inherit.in/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit.in/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit.in/dependency/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/detect_workspace_inherit.in/dependency/src/lib.rs b/tests/snapshots/add/detect_workspace_inherit.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit.in/primary/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit.in/primary/Cargo.toml new file mode 100644 index 00000000000..b5022b62a37 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.in/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit.in/primary/src/lib.rs b/tests/snapshots/add/detect_workspace_inherit.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit.out/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit.out/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit.out/dependency/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/detect_workspace_inherit.out/primary/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit.out/primary/Cargo.toml new file mode 100644 index 00000000000..c97da880af7 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.out/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo.workspace = true diff --git a/tests/snapshots/add/detect_workspace_inherit.stderr b/tests/snapshots/add/detect_workspace_inherit.stderr new file mode 100644 index 00000000000..d2efcc0c00c --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit.stderr @@ -0,0 +1 @@ + Adding foo (workspace) to dependencies. diff --git a/tests/snapshots/add/detect_workspace_inherit.stdout b/tests/snapshots/add/detect_workspace_inherit.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit_features.in/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_features.in/Cargo.toml new file mode 100644 index 00000000000..b1d9b399536 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency", features = ["merge"] } diff --git a/tests/snapshots/add/detect_workspace_inherit_features.in/dependency/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_features.in/dependency/Cargo.toml new file mode 100644 index 00000000000..f34d7a68506 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.in/dependency/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "foo" +version = "0.0.0" + +[features] +default-base = [] +default-test-base = [] +default-merge-base = [] +default = ["default-base", "default-test-base", "default-merge-base"] +test-base = [] +test = ["test-base", "default-test-base"] +merge-base = [] +merge = ["merge-base", "default-merge-base"] +unrelated = [] \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit_features.in/dependency/src/lib.rs b/tests/snapshots/add/detect_workspace_inherit_features.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit_features.in/primary/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_features.in/primary/Cargo.toml new file mode 100644 index 00000000000..b5022b62a37 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.in/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit_features.in/primary/src/lib.rs b/tests/snapshots/add/detect_workspace_inherit_features.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit_features.out/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_features.out/Cargo.toml new file mode 100644 index 00000000000..b1d9b399536 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency", features = ["merge"] } diff --git a/tests/snapshots/add/detect_workspace_inherit_features.out/dependency/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_features.out/dependency/Cargo.toml new file mode 100644 index 00000000000..f34d7a68506 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.out/dependency/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "foo" +version = "0.0.0" + +[features] +default-base = [] +default-test-base = [] +default-merge-base = [] +default = ["default-base", "default-test-base", "default-merge-base"] +test-base = [] +test = ["test-base", "default-test-base"] +merge-base = [] +merge = ["merge-base", "default-merge-base"] +unrelated = [] \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit_features.out/primary/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_features.out/primary/Cargo.toml new file mode 100644 index 00000000000..0f91d71a3c8 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.out/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { workspace = true, features = ["test"] } diff --git a/tests/snapshots/add/detect_workspace_inherit_features.stderr b/tests/snapshots/add/detect_workspace_inherit_features.stderr new file mode 100644 index 00000000000..86d9fb3b857 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_features.stderr @@ -0,0 +1,10 @@ + Adding foo (workspace) to dependencies. + Features: + + default-base + + default-merge-base + + default-test-base + + merge + + merge-base + + test + + test-base + - unrelated diff --git a/tests/snapshots/add/detect_workspace_inherit_features.stdout b/tests/snapshots/add/detect_workspace_inherit_features.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.in/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_optional.in/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/src/lib.rs b/tests/snapshots/add/detect_workspace_inherit_optional.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.in/primary/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_optional.in/primary/Cargo.toml new file mode 100644 index 00000000000..b5022b62a37 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.in/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.in/primary/src/lib.rs b/tests/snapshots/add/detect_workspace_inherit_optional.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.out/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_optional.out/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} \ No newline at end of file diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.out/dependency/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_optional.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.out/primary/Cargo.toml b/tests/snapshots/add/detect_workspace_inherit_optional.out/primary/Cargo.toml new file mode 100644 index 00000000000..b3b1ccc5b11 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.out/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { workspace = true, optional = true } diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.stderr b/tests/snapshots/add/detect_workspace_inherit_optional.stderr new file mode 100644 index 00000000000..da03b11f700 --- /dev/null +++ b/tests/snapshots/add/detect_workspace_inherit_optional.stderr @@ -0,0 +1 @@ + Adding foo (workspace) to optional dependencies. diff --git a/tests/snapshots/add/detect_workspace_inherit_optional.stdout b/tests/snapshots/add/detect_workspace_inherit_optional.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_add.rs b/tests/testsuite/cargo_add.rs index 2f43c6ee7f9..a7bf836de55 100644 --- a/tests/testsuite/cargo_add.rs +++ b/tests/testsuite/cargo_add.rs @@ -262,6 +262,77 @@ fn require_weak() { assert().subset_matches("tests/snapshots/add/require_weak.out", &project_root); } +#[cargo_test] +fn detect_workspace_inherit() { + init_registry(); + let project = Project::from_template("tests/snapshots/add/detect_workspace_inherit.in"); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/detect_workspace_inherit.stdout") + .stderr_matches_path("tests/snapshots/add/detect_workspace_inherit.stderr"); + + assert().subset_matches( + "tests/snapshots/add/detect_workspace_inherit.out", + &project_root, + ); +} + +#[cargo_test] +fn detect_workspace_inherit_features() { + init_registry(); + let project = + Project::from_template("tests/snapshots/add/detect_workspace_inherit_features.in"); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar", "--features", "test"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/detect_workspace_inherit_features.stdout") + .stderr_matches_path("tests/snapshots/add/detect_workspace_inherit_features.stderr"); + + assert().subset_matches( + "tests/snapshots/add/detect_workspace_inherit_features.out", + &project_root, + ); +} + +#[cargo_test] +fn detect_workspace_inherit_optional() { + init_registry(); + let project = + Project::from_template("tests/snapshots/add/detect_workspace_inherit_optional.in"); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar", "--optional"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/detect_workspace_inherit_optional.stdout") + .stderr_matches_path("tests/snapshots/add/detect_workspace_inherit_optional.stderr"); + + assert().subset_matches( + "tests/snapshots/add/detect_workspace_inherit_optional.out", + &project_root, + ); +} + #[cargo_test] fn dev() { init_registry();