From d652f2485f7a1306340483d88fbe61d0441fce84 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 26 Apr 2022 10:16:26 -0500 Subject: [PATCH 1/7] chore: Upgrade toml_edit --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e5b9144506a..7851d070735 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ strip-ansi-escapes = "0.1.0" tar = { version = "0.4.36", default-features = false } tempfile = "3.0" termcolor = "1.1" -toml_edit = { version = "0.13.4", features = ["serde", "easy"] } +toml_edit = { version = "0.14.3", features = ["serde", "easy", "perf"] } unicode-xid = "0.2.0" url = "2.2.2" walkdir = "2.2" From f217a6cd6d919eba07e341dc70bb2c0056ca6792 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Mon, 25 Apr 2022 12:35:01 -0500 Subject: [PATCH 2/7] Allow running `cargo add foo` when a `foo.workspace = true` already exists --- src/cargo/ops/cargo_add/dependency.rs | 112 ++++++++++-- src/cargo/ops/cargo_add/mod.rs | 161 ++++++++++++------ .../Cargo.toml | 5 + .../dependency/Cargo.toml | 6 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 + .../primary/src/lib.rs | 0 .../Cargo.toml | 5 + .../dependency/Cargo.toml | 6 + .../primary/Cargo.toml | 8 + .../overwrite_inherit_features_noop.stderr | 3 + .../overwrite_inherit_features_noop.stdout | 0 .../add/overwrite_inherit_noop.in/Cargo.toml | 5 + .../dependency/Cargo.toml | 3 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 + .../primary/src/lib.rs | 0 .../add/overwrite_inherit_noop.out/Cargo.toml | 5 + .../dependency/Cargo.toml | 3 + .../primary/Cargo.toml | 8 + .../add/overwrite_inherit_noop.stderr | 1 + .../add/overwrite_inherit_noop.stdout | 0 .../Cargo.toml | 5 + .../dependency/Cargo.toml | 3 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 + .../primary/src/lib.rs | 0 .../Cargo.toml | 5 + .../dependency/Cargo.toml | 3 + .../primary/Cargo.toml | 8 + .../overwrite_inherit_optional_noop.stderr | 1 + .../overwrite_inherit_optional_noop.stdout | 0 tests/testsuite/cargo_add.rs | 77 +++++++++ 33 files changed, 396 insertions(+), 61 deletions(-) create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.in/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.out/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.stderr create mode 100644 tests/snapshots/add/overwrite_inherit_features_noop.stdout create mode 100644 tests/snapshots/add/overwrite_inherit_noop.in/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_noop.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_noop.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_inherit_noop.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_noop.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_inherit_noop.out/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_noop.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_noop.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_noop.stderr create mode 100644 tests/snapshots/add/overwrite_inherit_noop.stdout create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.in/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.out/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.stderr create mode 100644 tests/snapshots/add/overwrite_inherit_optional_noop.stdout diff --git a/src/cargo/ops/cargo_add/dependency.rs b/src/cargo/ops/cargo_add/dependency.rs index 23b3373fc2d..caf2314e025 100644 --- a/src/cargo/ops/cargo_add/dependency.rs +++ b/src/cargo/ops/cargo_add/dependency.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; use indexmap::IndexSet; @@ -74,6 +75,7 @@ impl Dependency { Some(Source::Git(git)) => { git.version = None; } + Some(Source::Workspace(_workspace)) => {} None => {} } self @@ -161,6 +163,7 @@ impl Dependency { Source::Registry(src) => Some(src.version.as_str()), Source::Path(src) => src.version.as_deref(), Source::Git(src) => src.version.as_deref(), + Source::Workspace(_) => None, } } @@ -185,29 +188,47 @@ impl Dependency { } /// Get the SourceID for this dependency - pub fn source_id(&self, config: &Config) -> CargoResult { + pub fn source_id(&self, config: &Config) -> CargoResult> { match &self.source.as_ref() { Some(Source::Registry(_)) | None => { if let Some(r) = self.registry() { let source_id = SourceId::alt_registry(config, r)?; - Ok(source_id) + Ok(MaybeWorkspace::Other(source_id)) } else { let source_id = SourceId::crates_io(config)?; - Ok(source_id) + Ok(MaybeWorkspace::Other(source_id)) } } - Some(Source::Path(source)) => source.source_id(), - Some(Source::Git(source)) => source.source_id(), + Some(Source::Path(source)) => Ok(MaybeWorkspace::Other(source.source_id()?)), + Some(Source::Git(source)) => Ok(MaybeWorkspace::Other(source.source_id()?)), + Some(Source::Workspace(workspace)) => Ok(MaybeWorkspace::Workspace(workspace.clone())), } } /// Query to find this dependency - pub fn query(&self, config: &Config) -> CargoResult { + pub fn query( + &self, + config: &Config, + ) -> CargoResult> { let source_id = self.source_id(config)?; - crate::core::dependency::Dependency::parse(self.name.as_str(), self.version(), source_id) + match source_id { + MaybeWorkspace::Workspace(workspace) => Ok(MaybeWorkspace::Workspace(workspace)), + MaybeWorkspace::Other(source_id) => Ok(MaybeWorkspace::Other( + crate::core::dependency::Dependency::parse( + self.name.as_str(), + self.version(), + source_id, + )?, + )), + } } } +pub enum MaybeWorkspace { + Workspace(WorkspaceSource), + Other(T), +} + impl Dependency { /// Create a dependency from a TOML table entry pub fn from_toml(crate_root: &Path, key: &str, item: &toml_edit::Item) -> CargoResult { @@ -271,6 +292,15 @@ impl Dependency { invalid_type(key, "version", version.type_name(), "string") })?); src.into() + } else if let Some(workspace) = table.get("workspace") { + let workspace_bool = workspace.as_bool().ok_or_else(|| { + invalid_type(key, "workspace", workspace.type_name(), "bool") + })?; + if !workspace_bool { + anyhow::bail!("`{key}.workspace = false` is unsupported") + } + let src = WorkspaceSource::new(); + src.into() } else { anyhow::bail!("Unrecognized dependency source for `{key}`"); }; @@ -367,6 +397,12 @@ impl Dependency { None, None, ) => toml_edit::value(v), + (false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => { + let mut table = toml_edit::InlineTable::default(); + table.set_dotted(true); + table.insert("workspace", true.into()); + toml_edit::value(toml_edit::Value::InlineTable(table)) + } // Other cases are represented as an inline table (_, _, _, _, _, _) => { let mut table = toml_edit::InlineTable::default(); @@ -397,6 +433,9 @@ impl Dependency { table.insert("version", r.into()); } } + Some(Source::Workspace(_)) => { + table.insert("workspace", true.into()); + } None => {} } if table.contains_key("version") { @@ -436,7 +475,7 @@ impl Dependency { Some(Source::Registry(src)) => { table.insert("version", toml_edit::value(src.version.as_str())); - for key in ["path", "git", "branch", "tag", "rev"] { + for key in ["path", "git", "branch", "tag", "rev", "workspace"] { table.remove(key); } } @@ -449,7 +488,7 @@ impl Dependency { table.remove("version"); } - for key in ["git", "branch", "tag", "rev"] { + for key in ["git", "branch", "tag", "rev", "workspace"] { table.remove(key); } } @@ -476,7 +515,23 @@ impl Dependency { table.remove("version"); } - for key in ["path"] { + for key in ["path", "workspace"] { + table.remove(key); + } + } + Some(Source::Workspace(_)) => { + table.set_dotted(true); + for key in [ + "version", + "registry", + "registry-index", + "path", + "git", + "branch", + "tag", + "rev", + "package", + ] { table.remove(key); } } @@ -516,12 +571,14 @@ impl Dependency { .unwrap_or_default(); features.extend(new_features.iter().map(|s| s.as_str())); let features = toml_edit::value(features.into_iter().collect::()); + table.set_dotted(false); table.insert("features", features); } else { table.remove("features"); } match self.optional { Some(v) => { + table.set_dotted(false); table.insert("optional", toml_edit::value(v)); } None => { @@ -596,6 +653,8 @@ pub enum Source { Path(PathSource), /// Dependency from a git repo Git(GitSource), + /// Dependency from a workspace + Workspace(WorkspaceSource), } impl Source { @@ -624,6 +683,15 @@ impl Source { _ => None, } } + + /// Access the workspace source, if present + #[allow(dead_code)] + pub fn as_workspace(&self) -> Option<&WorkspaceSource> { + match self { + Self::Workspace(src) => Some(src), + _ => None, + } + } } impl std::fmt::Display for Source { @@ -632,6 +700,7 @@ impl std::fmt::Display for Source { Self::Registry(src) => src.fmt(f), Self::Path(src) => src.fmt(f), Self::Git(src) => src.fmt(f), + Self::Workspace(src) => src.fmt(f), } } } @@ -660,6 +729,12 @@ impl From for Source { } } +impl From for Source { + fn from(inner: WorkspaceSource) -> Self { + Self::Workspace(inner) + } +} + /// Dependency from a registry #[derive(Debug, Hash, PartialEq, Eq, Clone)] #[non_exhaustive] @@ -822,6 +897,23 @@ impl std::fmt::Display for GitSource { } } +/// Dependency from a workspace +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct WorkspaceSource; + +impl WorkspaceSource { + pub fn new() -> Self { + Self + } +} + +impl Display for WorkspaceSource { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + "workspace".fmt(f) + } +} + #[cfg(test)] mod tests { use std::path::Path; diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index 20cc26ece22..4033f1af1bb 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -4,6 +4,7 @@ mod crate_spec; mod dependency; mod manifest; +use anyhow::Context; use std::collections::BTreeSet; use std::collections::VecDeque; use std::path::Path; @@ -31,6 +32,7 @@ use dependency::RegistrySource; use dependency::Source; use manifest::LocalManifest; +use crate::ops::cargo_add::dependency::MaybeWorkspace; pub use manifest::DepTable; /// Information on what dependencies should be added @@ -313,7 +315,7 @@ fn resolve_dependency( dependency = dependency.clear_version(); } - dependency = populate_available_features(dependency, config, registry)?; + dependency = populate_available_features(dependency, config, registry, ws)?; Ok(dependency) } @@ -389,31 +391,40 @@ fn get_latest_dependency( registry: &mut PackageRegistry<'_>, ) -> CargoResult { let query = dependency.query(config)?; - let possibilities = loop { - let fuzzy = true; - match registry.query_vec(&query, fuzzy) { - std::task::Poll::Ready(res) => { - break res?; + match query { + MaybeWorkspace::Workspace(_) => { + unreachable!("registry dependencies required, found a workspace dependency"); + } + MaybeWorkspace::Other(query) => { + let possibilities = loop { + let fuzzy = true; + match registry.query_vec(&query, fuzzy) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + }; + let latest = possibilities + .iter() + .max_by_key(|s| { + // Fallback to a pre-release if no official release is available by sorting them as + // less. + let stable = s.version().pre.is_empty(); + (stable, s.version()) + }) + .ok_or_else(|| { + anyhow::format_err!( + "the crate `{dependency}` could not be found in registry index." + ) + })?; + let mut dep = Dependency::from(latest); + if let Some(reg_name) = dependency.registry.as_deref() { + dep = dep.set_registry(reg_name); } - std::task::Poll::Pending => registry.block_until_ready()?, + Ok(dep) } - }; - let latest = possibilities - .iter() - .max_by_key(|s| { - // Fallback to a pre-release if no official release is available by sorting them as - // less. - let stable = s.version().pre.is_empty(); - (stable, s.version()) - }) - .ok_or_else(|| { - anyhow::format_err!("the crate `{dependency}` could not be found in registry index.") - })?; - let mut dep = Dependency::from(latest); - if let Some(reg_name) = dependency.registry.as_deref() { - dep = dep.set_registry(reg_name); } - Ok(dep) } fn select_package( @@ -422,36 +433,43 @@ fn select_package( registry: &mut PackageRegistry<'_>, ) -> CargoResult { let query = dependency.query(config)?; - let possibilities = loop { - let fuzzy = false; // Returns all for path/git - match registry.query_vec(&query, fuzzy) { - std::task::Poll::Ready(res) => { - break res?; - } - std::task::Poll::Pending => registry.block_until_ready()?, + match query { + MaybeWorkspace::Workspace(_) => { + unreachable!("path or git dependency expected, found workspace dependency"); } - }; - match possibilities.len() { - 0 => { - let source = dependency - .source() - .expect("source should be resolved before here"); - anyhow::bail!("the crate `{dependency}` could not be found at `{source}`") - } - 1 => { - let mut dep = Dependency::from(&possibilities[0]); - if let Some(reg_name) = dependency.registry.as_deref() { - dep = dep.set_registry(reg_name); + MaybeWorkspace::Other(query) => { + let possibilities = loop { + let fuzzy = false; // Returns all for path/git + match registry.query_vec(&query, fuzzy) { + std::task::Poll::Ready(res) => { + break res?; + } + std::task::Poll::Pending => registry.block_until_ready()?, + } + }; + match possibilities.len() { + 0 => { + let source = dependency + .source() + .expect("source should be resolved before here"); + anyhow::bail!("the crate `{dependency}` could not be found at `{source}`") + } + 1 => { + let mut dep = Dependency::from(&possibilities[0]); + if let Some(reg_name) = dependency.registry.as_deref() { + dep = dep.set_registry(reg_name); + } + Ok(dep) + } + _ => { + let source = dependency + .source() + .expect("source should be resolved before here"); + anyhow::bail!( + "unexpectedly found multiple copies of crate `{dependency}` at `{source}`" + ) + } } - Ok(dep) - } - _ => { - let source = dependency - .source() - .expect("source should be resolved before here"); - anyhow::bail!( - "unexpectedly found multiple copies of crate `{dependency}` at `{source}`" - ) } } } @@ -512,12 +530,50 @@ fn populate_available_features( mut dependency: Dependency, config: &Config, registry: &mut PackageRegistry<'_>, + ws: &Workspace<'_>, ) -> CargoResult { if !dependency.available_features.is_empty() { return Ok(dependency); } 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 query = dep.query(config)?; + match query { + MaybeWorkspace::Workspace(_) => { + unreachable!("This should have been caught when parsing a workspace root") + } + MaybeWorkspace::Other(query) => query, + } + } + MaybeWorkspace::Other(query) => query, + }; let possibilities = loop { match registry.query_vec(&query, true) { std::task::Poll::Ready(res) => { @@ -567,6 +623,9 @@ fn print_msg(shell: &mut Shell, dep: &Dependency, section: &[String]) -> CargoRe Some(Source::Git(_)) => { write!(message, " (git)")?; } + Some(Source::Workspace(_)) => { + write!(message, " (workspace)")?; + } None => {} } write!(message, " to")?; diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.in/Cargo.toml b/tests/snapshots/add/overwrite_inherit_features_noop.in/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.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/overwrite_inherit_features_noop.in/dependency/Cargo.toml b/tests/snapshots/add/overwrite_inherit_features_noop.in/dependency/Cargo.toml new file mode 100644 index 00000000000..bed9320474a --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.in/dependency/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "foo" +version = "0.0.0" + +[features] +test = [] \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.in/dependency/src/lib.rs b/tests/snapshots/add/overwrite_inherit_features_noop.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.in/primary/Cargo.toml b/tests/snapshots/add/overwrite_inherit_features_noop.in/primary/Cargo.toml new file mode 100644 index 00000000000..7ab3f9dd2c1 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.in/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { workspace = true, features = ["test"] } \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.in/primary/src/lib.rs b/tests/snapshots/add/overwrite_inherit_features_noop.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.out/Cargo.toml b/tests/snapshots/add/overwrite_inherit_features_noop.out/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.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/overwrite_inherit_features_noop.out/dependency/Cargo.toml b/tests/snapshots/add/overwrite_inherit_features_noop.out/dependency/Cargo.toml new file mode 100644 index 00000000000..bed9320474a --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.out/dependency/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "foo" +version = "0.0.0" + +[features] +test = [] \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.out/primary/Cargo.toml b/tests/snapshots/add/overwrite_inherit_features_noop.out/primary/Cargo.toml new file mode 100644 index 00000000000..0f91d71a3c8 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.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/overwrite_inherit_features_noop.stderr b/tests/snapshots/add/overwrite_inherit_features_noop.stderr new file mode 100644 index 00000000000..0eee2e6bd46 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_features_noop.stderr @@ -0,0 +1,3 @@ + Adding foo (workspace) to dependencies. + Features: + + test diff --git a/tests/snapshots/add/overwrite_inherit_features_noop.stdout b/tests/snapshots/add/overwrite_inherit_features_noop.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_noop.in/Cargo.toml b/tests/snapshots/add/overwrite_inherit_noop.in/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.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/overwrite_inherit_noop.in/dependency/Cargo.toml b/tests/snapshots/add/overwrite_inherit_noop.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/overwrite_inherit_noop.in/dependency/src/lib.rs b/tests/snapshots/add/overwrite_inherit_noop.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_noop.in/primary/Cargo.toml b/tests/snapshots/add/overwrite_inherit_noop.in/primary/Cargo.toml new file mode 100644 index 00000000000..aaadbceb163 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.in/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo.workspace = true \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_inherit_noop.in/primary/src/lib.rs b/tests/snapshots/add/overwrite_inherit_noop.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_noop.out/Cargo.toml b/tests/snapshots/add/overwrite_inherit_noop.out/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.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/overwrite_inherit_noop.out/dependency/Cargo.toml b/tests/snapshots/add/overwrite_inherit_noop.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/overwrite_inherit_noop.out/primary/Cargo.toml b/tests/snapshots/add/overwrite_inherit_noop.out/primary/Cargo.toml new file mode 100644 index 00000000000..c97da880af7 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.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/overwrite_inherit_noop.stderr b/tests/snapshots/add/overwrite_inherit_noop.stderr new file mode 100644 index 00000000000..d2efcc0c00c --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_noop.stderr @@ -0,0 +1 @@ + Adding foo (workspace) to dependencies. diff --git a/tests/snapshots/add/overwrite_inherit_noop.stdout b/tests/snapshots/add/overwrite_inherit_noop.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.in/Cargo.toml b/tests/snapshots/add/overwrite_inherit_optional_noop.in/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.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/overwrite_inherit_optional_noop.in/dependency/Cargo.toml b/tests/snapshots/add/overwrite_inherit_optional_noop.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.in/dependency/src/lib.rs b/tests/snapshots/add/overwrite_inherit_optional_noop.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/Cargo.toml b/tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/Cargo.toml new file mode 100644 index 00000000000..ffb5719c788 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { workspace = true, optional = true } \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/src/lib.rs b/tests/snapshots/add/overwrite_inherit_optional_noop.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.out/Cargo.toml b/tests/snapshots/add/overwrite_inherit_optional_noop.out/Cargo.toml new file mode 100644 index 00000000000..24c50556bb5 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.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/overwrite_inherit_optional_noop.out/dependency/Cargo.toml b/tests/snapshots/add/overwrite_inherit_optional_noop.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.out/primary/Cargo.toml b/tests/snapshots/add/overwrite_inherit_optional_noop.out/primary/Cargo.toml new file mode 100644 index 00000000000..b3b1ccc5b11 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.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/overwrite_inherit_optional_noop.stderr b/tests/snapshots/add/overwrite_inherit_optional_noop.stderr new file mode 100644 index 00000000000..da03b11f700 --- /dev/null +++ b/tests/snapshots/add/overwrite_inherit_optional_noop.stderr @@ -0,0 +1 @@ + Adding foo (workspace) to optional dependencies. diff --git a/tests/snapshots/add/overwrite_inherit_optional_noop.stdout b/tests/snapshots/add/overwrite_inherit_optional_noop.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_add.rs b/tests/testsuite/cargo_add.rs index 20a48ddbe3f..1b44c2f5364 100644 --- a/tests/testsuite/cargo_add.rs +++ b/tests/testsuite/cargo_add.rs @@ -50,6 +50,16 @@ pub fn cargo_command() -> snapbox::cmd::Command { cmd } +pub trait CommandExt { + fn masquerade_as_nightly_cargo(self) -> Self; +} + +impl CommandExt for snapbox::cmd::Command { + fn masquerade_as_nightly_cargo(self) -> Self { + self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly") + } +} + pub fn project_from_template(template_path: impl AsRef) -> std::path::PathBuf { let root = cargo_test_support::paths::root(); let project_root = root.join("case"); @@ -1504,6 +1514,73 @@ fn overwrite_inline_features() { ); } +#[cargo_test] +fn overwrite_inherit_features_noop() { + let project_root = + project_from_template("tests/snapshots/add/overwrite_inherit_features_noop.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/overwrite_inherit_features_noop.stdout") + .stderr_matches_path("tests/snapshots/add/overwrite_inherit_features_noop.stderr"); + + assert().subset_matches( + "tests/snapshots/add/overwrite_inherit_features_noop.out", + &project_root, + ); +} + +#[cargo_test] +fn overwrite_inherit_noop() { + init_registry(); + let project_root = project_from_template("tests/snapshots/add/overwrite_inherit_noop.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/overwrite_inherit_noop.stdout") + .stderr_matches_path("tests/snapshots/add/overwrite_inherit_noop.stderr"); + + assert().subset_matches( + "tests/snapshots/add/overwrite_inherit_noop.out", + &project_root, + ); +} + +#[cargo_test] +fn overwrite_inherit_optional_noop() { + init_registry(); + let project_root = + project_from_template("tests/snapshots/add/overwrite_inherit_optional_noop.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/overwrite_inherit_optional_noop.stdout") + .stderr_matches_path("tests/snapshots/add/overwrite_inherit_optional_noop.stderr"); + + assert().subset_matches( + "tests/snapshots/add/overwrite_inherit_optional_noop.out", + &project_root, + ); +} + #[cargo_test] fn overwrite_name_dev_noop() { init_alt_registry(); From 1b70c2295f21fdd0f4757f11ceb8d96a611ea49d Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Mon, 25 Apr 2022 18:18:56 -0500 Subject: [PATCH 3/7] Show the merged set of activated features to the user when inheriting from a workspace dependency --- src/cargo/ops/cargo_add/dependency.rs | 10 +++++ src/cargo/ops/cargo_add/mod.rs | 36 +++++++++------- .../merge_activated_features.in/Cargo.toml | 5 +++ .../dependency/Cargo.toml | 14 +++++++ .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 ++++ .../primary/src/lib.rs | 0 .../merge_activated_features.out/Cargo.toml | 5 +++ .../dependency/Cargo.toml | 14 +++++++ .../primary/Cargo.toml | 8 ++++ .../add/merge_activated_features.stderr | 10 +++++ .../add/merge_activated_features.stdout | 0 .../unknown_inherited_feature.in/Cargo.toml | 5 +++ .../dependency/Cargo.toml | 14 +++++++ .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 ++++ .../primary/src/lib.rs | 0 .../unknown_inherited_feature.out/Cargo.toml | 5 +++ .../dependency/Cargo.toml | 14 +++++++ .../primary/Cargo.toml | 8 ++++ .../add/unknown_inherited_feature.stderr | 12 ++++++ .../add/unknown_inherited_feature.stdout | 0 tests/testsuite/cargo_add.rs | 42 +++++++++++++++++++ 23 files changed, 204 insertions(+), 14 deletions(-) create mode 100644 tests/snapshots/add/merge_activated_features.in/Cargo.toml create mode 100644 tests/snapshots/add/merge_activated_features.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/merge_activated_features.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/merge_activated_features.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/merge_activated_features.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/merge_activated_features.out/Cargo.toml create mode 100644 tests/snapshots/add/merge_activated_features.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/merge_activated_features.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/merge_activated_features.stderr create mode 100644 tests/snapshots/add/merge_activated_features.stdout create mode 100644 tests/snapshots/add/unknown_inherited_feature.in/Cargo.toml create mode 100644 tests/snapshots/add/unknown_inherited_feature.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/unknown_inherited_feature.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/unknown_inherited_feature.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/unknown_inherited_feature.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/unknown_inherited_feature.out/Cargo.toml create mode 100644 tests/snapshots/add/unknown_inherited_feature.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/unknown_inherited_feature.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/unknown_inherited_feature.stderr create mode 100644 tests/snapshots/add/unknown_inherited_feature.stdout diff --git a/src/cargo/ops/cargo_add/dependency.rs b/src/cargo/ops/cargo_add/dependency.rs index caf2314e025..560b68302a2 100644 --- a/src/cargo/ops/cargo_add/dependency.rs +++ b/src/cargo/ops/cargo_add/dependency.rs @@ -28,6 +28,8 @@ pub struct Dependency { pub features: Option>, /// Whether default features are enabled pub default_features: Option, + /// List of features inherited from a workspace dependency + pub inherited_features: Option>, /// Where the dependency comes from pub source: Option, @@ -50,6 +52,7 @@ impl Dependency { optional: None, features: None, default_features: None, + inherited_features: None, source: None, registry: None, rename: None, @@ -152,6 +155,12 @@ impl Dependency { self } + /// Set features as an array of string (does some basic parsing) + pub fn set_inherited_features(mut self, features: IndexSet) -> Self { + self.inherited_features = Some(features); + self + } + /// Get the dependency source pub fn source(&self) -> Option<&Source> { self.source.as_ref() @@ -350,6 +359,7 @@ impl Dependency { features, available_features, optional, + inherited_features: None, }; Ok(dep) } else { diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index 4033f1af1bb..b49a4df251d 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -106,23 +106,27 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<( ) } } + + let available_features = dep + .available_features + .keys() + .map(|s| s.as_ref()) + .collect::>(); + let mut unknown_features: Vec<&str> = Vec::new(); if let Some(req_feats) = dep.features.as_ref() { let req_feats: BTreeSet<_> = req_feats.iter().map(|s| s.as_str()).collect(); - - let available_features = dep - .available_features - .keys() - .map(|s| s.as_ref()) - .collect::>(); - - let mut unknown_features: Vec<&&str> = - req_feats.difference(&available_features).collect(); - unknown_features.sort(); - - if !unknown_features.is_empty() { - anyhow::bail!("unrecognized features: {unknown_features:?}"); - } + unknown_features.extend(req_feats.difference(&available_features).copied()); } + if let Some(inherited_features) = dep.inherited_features.as_ref() { + let inherited_features: BTreeSet<_> = + inherited_features.iter().map(|s| s.as_str()).collect(); + unknown_features.extend(inherited_features.difference(&available_features).copied()); + } + unknown_features.sort(); + if !unknown_features.is_empty() { + anyhow::bail!("unrecognized features: {unknown_features:?}"); + } + manifest.insert_into_table(&dep_table, &dep)?; manifest.gc_dep(dep.toml_key()); } @@ -564,6 +568,9 @@ fn populate_available_features( dependency.toml_key(), dep_item, )?; + if let Some(features) = dep.features.clone() { + dependency = dependency.set_inherited_features(features); + } let query = dep.query(config)?; match query { MaybeWorkspace::Workspace(_) => { @@ -645,6 +652,7 @@ fn print_msg(shell: &mut Shell, dep: &Dependency, section: &[String]) -> CargoRe if dep.default_features().unwrap_or(true) { activated.insert("default"); } + activated.extend(dep.inherited_features.iter().flatten().map(|s| s.as_str())); let mut walk: VecDeque<_> = activated.iter().cloned().collect(); while let Some(next) = walk.pop_front() { walk.extend( diff --git a/tests/snapshots/add/merge_activated_features.in/Cargo.toml b/tests/snapshots/add/merge_activated_features.in/Cargo.toml new file mode 100644 index 00000000000..b1d9b399536 --- /dev/null +++ b/tests/snapshots/add/merge_activated_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/merge_activated_features.in/dependency/Cargo.toml b/tests/snapshots/add/merge_activated_features.in/dependency/Cargo.toml new file mode 100644 index 00000000000..f34d7a68506 --- /dev/null +++ b/tests/snapshots/add/merge_activated_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/merge_activated_features.in/dependency/src/lib.rs b/tests/snapshots/add/merge_activated_features.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/merge_activated_features.in/primary/Cargo.toml b/tests/snapshots/add/merge_activated_features.in/primary/Cargo.toml new file mode 100644 index 00000000000..7ab3f9dd2c1 --- /dev/null +++ b/tests/snapshots/add/merge_activated_features.in/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { workspace = true, features = ["test"] } \ No newline at end of file diff --git a/tests/snapshots/add/merge_activated_features.in/primary/src/lib.rs b/tests/snapshots/add/merge_activated_features.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/merge_activated_features.out/Cargo.toml b/tests/snapshots/add/merge_activated_features.out/Cargo.toml new file mode 100644 index 00000000000..b1d9b399536 --- /dev/null +++ b/tests/snapshots/add/merge_activated_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/merge_activated_features.out/dependency/Cargo.toml b/tests/snapshots/add/merge_activated_features.out/dependency/Cargo.toml new file mode 100644 index 00000000000..f34d7a68506 --- /dev/null +++ b/tests/snapshots/add/merge_activated_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/merge_activated_features.out/primary/Cargo.toml b/tests/snapshots/add/merge_activated_features.out/primary/Cargo.toml new file mode 100644 index 00000000000..0f91d71a3c8 --- /dev/null +++ b/tests/snapshots/add/merge_activated_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/merge_activated_features.stderr b/tests/snapshots/add/merge_activated_features.stderr new file mode 100644 index 00000000000..86d9fb3b857 --- /dev/null +++ b/tests/snapshots/add/merge_activated_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/merge_activated_features.stdout b/tests/snapshots/add/merge_activated_features.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/unknown_inherited_feature.in/Cargo.toml b/tests/snapshots/add/unknown_inherited_feature.in/Cargo.toml new file mode 100644 index 00000000000..b2a34c92e4c --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency", features = ["not_recognized"] } diff --git a/tests/snapshots/add/unknown_inherited_feature.in/dependency/Cargo.toml b/tests/snapshots/add/unknown_inherited_feature.in/dependency/Cargo.toml new file mode 100644 index 00000000000..f34d7a68506 --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.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/unknown_inherited_feature.in/dependency/src/lib.rs b/tests/snapshots/add/unknown_inherited_feature.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/unknown_inherited_feature.in/primary/Cargo.toml b/tests/snapshots/add/unknown_inherited_feature.in/primary/Cargo.toml new file mode 100644 index 00000000000..0f91d71a3c8 --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.in/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/unknown_inherited_feature.in/primary/src/lib.rs b/tests/snapshots/add/unknown_inherited_feature.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/unknown_inherited_feature.out/Cargo.toml b/tests/snapshots/add/unknown_inherited_feature.out/Cargo.toml new file mode 100644 index 00000000000..b2a34c92e4c --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency", features = ["not_recognized"] } diff --git a/tests/snapshots/add/unknown_inherited_feature.out/dependency/Cargo.toml b/tests/snapshots/add/unknown_inherited_feature.out/dependency/Cargo.toml new file mode 100644 index 00000000000..f34d7a68506 --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.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/unknown_inherited_feature.out/primary/Cargo.toml b/tests/snapshots/add/unknown_inherited_feature.out/primary/Cargo.toml new file mode 100644 index 00000000000..0f91d71a3c8 --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.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/unknown_inherited_feature.stderr b/tests/snapshots/add/unknown_inherited_feature.stderr new file mode 100644 index 00000000000..693e8872105 --- /dev/null +++ b/tests/snapshots/add/unknown_inherited_feature.stderr @@ -0,0 +1,12 @@ + Adding foo (workspace) to dependencies. + Features: + + default-base + + default-merge-base + + default-test-base + + not_recognized + + test + + test-base + - merge + - merge-base + - unrelated +error: unrecognized features: ["not_recognized"] diff --git a/tests/snapshots/add/unknown_inherited_feature.stdout b/tests/snapshots/add/unknown_inherited_feature.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_add.rs b/tests/testsuite/cargo_add.rs index 1b44c2f5364..475bc5df464 100644 --- a/tests/testsuite/cargo_add.rs +++ b/tests/testsuite/cargo_add.rs @@ -1231,6 +1231,27 @@ fn manifest_path_package() { ); } +#[cargo_test] +fn merge_activated_features() { + let project_root = project_from_template("tests/snapshots/add/merge_activated_features.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/merge_activated_features.stdout") + .stderr_matches_path("tests/snapshots/add/merge_activated_features.stderr"); + + assert().subset_matches( + "tests/snapshots/add/merge_activated_features.out", + &project_root, + ); +} + #[cargo_test] fn multiple_conflicts_with_features() { init_registry(); @@ -2066,6 +2087,27 @@ fn target_cfg() { assert().subset_matches("tests/snapshots/add/target_cfg.out", &project_root); } +#[cargo_test] +fn unknown_inherited_feature() { + let project_root = project_from_template("tests/snapshots/add/unknown_inherited_feature.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_matches_path("tests/snapshots/add/unknown_inherited_feature.stdout") + .stderr_matches_path("tests/snapshots/add/unknown_inherited_feature.stderr"); + + assert().subset_matches( + "tests/snapshots/add/unknown_inherited_feature.out", + &project_root, + ); +} + #[cargo_test] fn vers() { init_registry(); From 036145b2eae6c174d6f944cbc992de0db9c98320 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 26 Apr 2022 16:33:27 -0500 Subject: [PATCH 4/7] 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 9ee3cffb9efea1a4c23862fe53f043dfa27acc2c Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 26 Apr 2022 16:41:12 -0500 Subject: [PATCH 5/7] 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 | 68 +++++++++++++++++++ 32 files changed, 195 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 475bc5df464..e7e8d79c4a7 100644 --- a/tests/testsuite/cargo_add.rs +++ b/tests/testsuite/cargo_add.rs @@ -341,6 +341,74 @@ fn require_weak() { assert().subset_matches("tests/snapshots/add/require_weak.out", &project_root); } +#[cargo_test] +fn detect_workspace_inherit() { + init_registry(); + let project_root = project_from_template("tests/snapshots/add/detect_workspace_inherit.in"); + let cwd = &project_root; + + cargo_command() + .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_root = + project_from_template("tests/snapshots/add/detect_workspace_inherit_features.in"); + let cwd = &project_root; + + cargo_command() + .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_root = + project_from_template("tests/snapshots/add/detect_workspace_inherit_optional.in"); + let cwd = &project_root; + + cargo_command() + .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(); From cf2202ca65396d657fdb77c80289fdacb7d80f4f Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 27 Apr 2022 10:33:51 -0500 Subject: [PATCH 6/7] Error if any invalid keys are defined when inheriting a workspace dependency --- src/cargo/ops/cargo_add/mod.rs | 38 +++++++++++ .../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 | 5 ++ .../add/invalid_key_inherit_dependency.stderr | 1 + .../add/invalid_key_inherit_dependency.stdout | 0 .../Cargo.toml | 5 ++ .../dependency/Cargo.toml | 3 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 +++ .../primary/src/lib.rs | 0 .../Cargo.toml | 5 ++ .../dependency/Cargo.toml | 3 + .../primary/Cargo.toml | 8 +++ ...id_key_overwrite_inherit_dependency.stderr | 1 + ...id_key_overwrite_inherit_dependency.stdout | 0 .../Cargo.toml | 5 ++ .../dependency-alt/Cargo.toml | 3 + .../dependency-alt/src/lib.rs | 0 .../dependency/Cargo.toml | 3 + .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 5 ++ .../primary/src/lib.rs | 0 .../Cargo.toml | 5 ++ .../dependency-alt/Cargo.toml | 3 + .../dependency/Cargo.toml | 3 + .../primary/Cargo.toml | 5 ++ ...valid_key_rename_inherit_dependency.stderr | 1 + ...valid_key_rename_inherit_dependency.stdout | 0 tests/testsuite/cargo_add.rs | 66 +++++++++++++++++++ 35 files changed, 197 insertions(+) create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.in/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.out/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.stderr create mode 100644 tests/snapshots/add/invalid_key_inherit_dependency.stdout create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stderr create mode 100644 tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stdout create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.out/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency-alt/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.stderr create mode 100644 tests/snapshots/add/invalid_key_rename_inherit_dependency.stdout diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index dff545f38a0..dff93e91b02 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -312,6 +312,10 @@ fn resolve_dependency( } } + if let Some(Source::Workspace(_)) = dependency.source() { + check_invalid_ws_keys(dependency.toml_key(), arg)?; + } + let version_required = dependency.source().and_then(|s| s.as_registry()).is_some(); let version_optional_in_section = section.kind() == DepKind::Development; let preserve_existing_version = old_dep @@ -328,6 +332,40 @@ fn resolve_dependency( Ok(dependency) } +/// 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 +/// `default-features`. +/// +/// Only `default-features`, `registry` and `rename` need to be checked +/// for currently. This is because `git` and its associated keys, `path`, and +/// `version` should all bee checked before this is called. `rename` is checked +/// for as it turns into `package` +fn check_invalid_ws_keys(toml_key: &str, arg: &DepOp) -> CargoResult<()> { + fn err_msg(toml_key: &str, flag: &str, field: &str) -> String { + format!( + "cannot override workspace dependency with `{flag}`, \ + either change `workspace.dependencies.{toml_key}.{field}` \ + or define the dependency exclusively in the package's manifest" + ) + } + + if arg.default_features.is_some() { + anyhow::bail!( + "{}", + err_msg(toml_key, "--default-features", "default-features") + ) + } + if arg.registry.is_some() { + anyhow::bail!("{}", err_msg(toml_key, "--registry", "registry")) + } + // rename is `package` + if arg.rename.is_some() { + anyhow::bail!("{}", err_msg(toml_key, "--rename", "package")) + } + Ok(()) +} + /// Provide the existing dependency for the target table /// /// If it doesn't exist but exists in another table, let's use that as most likely users diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.in/Cargo.toml b/tests/snapshots/add/invalid_key_inherit_dependency.in/Cargo.toml new file mode 100644 index 00000000000..afd30d446e0 --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/Cargo.toml b/tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/src/lib.rs b/tests/snapshots/add/invalid_key_inherit_dependency.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.in/primary/Cargo.toml b/tests/snapshots/add/invalid_key_inherit_dependency.in/primary/Cargo.toml new file mode 100644 index 00000000000..668cbd854db --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.in/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.in/primary/src/lib.rs b/tests/snapshots/add/invalid_key_inherit_dependency.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.out/Cargo.toml b/tests/snapshots/add/invalid_key_inherit_dependency.out/Cargo.toml new file mode 100644 index 00000000000..afd30d446e0 --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.out/dependency/Cargo.toml b/tests/snapshots/add/invalid_key_inherit_dependency.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.out/primary/Cargo.toml b/tests/snapshots/add/invalid_key_inherit_dependency.out/primary/Cargo.toml new file mode 100644 index 00000000000..668cbd854db --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.out/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.stderr b/tests/snapshots/add/invalid_key_inherit_dependency.stderr new file mode 100644 index 00000000000..85bd8da0a82 --- /dev/null +++ b/tests/snapshots/add/invalid_key_inherit_dependency.stderr @@ -0,0 +1 @@ +error: cannot override workspace dependency with `--default-features`, either change `workspace.dependencies.foo.default-features` or define the dependency exclusively in the package's manifest diff --git a/tests/snapshots/add/invalid_key_inherit_dependency.stdout b/tests/snapshots/add/invalid_key_inherit_dependency.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/Cargo.toml b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/Cargo.toml new file mode 100644 index 00000000000..afd30d446e0 --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/Cargo.toml b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/src/lib.rs b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/primary/Cargo.toml b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/primary/Cargo.toml new file mode 100644 index 00000000000..c97da880af7 --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/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/invalid_key_overwrite_inherit_dependency.in/primary/src/lib.rs b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/Cargo.toml b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/Cargo.toml new file mode 100644 index 00000000000..afd30d446e0 --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/dependency/Cargo.toml b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/primary/Cargo.toml b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out/primary/Cargo.toml new file mode 100644 index 00000000000..c97da880af7 --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.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/invalid_key_overwrite_inherit_dependency.stderr b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stderr new file mode 100644 index 00000000000..85bd8da0a82 --- /dev/null +++ b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stderr @@ -0,0 +1 @@ +error: cannot override workspace dependency with `--default-features`, either change `workspace.dependencies.foo.default-features` or define the dependency exclusively in the package's manifest diff --git a/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stdout b/tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/Cargo.toml new file mode 100644 index 00000000000..12c6ee5fed1 --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency", "dependency-alt"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/Cargo.toml new file mode 100644 index 00000000000..bb647290158 --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo-alt" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/src/lib.rs b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency-alt/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/src/lib.rs b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/Cargo.toml new file mode 100644 index 00000000000..668cbd854db --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/src/lib.rs b/tests/snapshots/add/invalid_key_rename_inherit_dependency.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/Cargo.toml new file mode 100644 index 00000000000..12c6ee5fed1 --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = ["primary", "dependency", "dependency-alt"] + +[workspace.dependencies] +foo = { version = "0.0.0", path = "./dependency"} diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency-alt/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency-alt/Cargo.toml new file mode 100644 index 00000000000..bb647290158 --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency-alt/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo-alt" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/primary/Cargo.toml b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/primary/Cargo.toml new file mode 100644 index 00000000000..668cbd854db --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.out/primary/Cargo.toml @@ -0,0 +1,5 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.stderr b/tests/snapshots/add/invalid_key_rename_inherit_dependency.stderr new file mode 100644 index 00000000000..35bcdb6946b --- /dev/null +++ b/tests/snapshots/add/invalid_key_rename_inherit_dependency.stderr @@ -0,0 +1 @@ +error: cannot override workspace dependency with `--rename`, either change `workspace.dependencies.foo.package` or define the dependency exclusively in the package's manifest diff --git a/tests/snapshots/add/invalid_key_rename_inherit_dependency.stdout b/tests/snapshots/add/invalid_key_rename_inherit_dependency.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_add.rs b/tests/testsuite/cargo_add.rs index e7e8d79c4a7..6e23c7e5416 100644 --- a/tests/testsuite/cargo_add.rs +++ b/tests/testsuite/cargo_add.rs @@ -1091,6 +1091,72 @@ fn invalid_git_external() { ); } +#[cargo_test] +fn invalid_key_inherit_dependency() { + let project_root = + project_from_template("tests/snapshots/add/invalid_key_inherit_dependency.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "--default-features", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_matches_path("tests/snapshots/add/invalid_key_inherit_dependency.stdout") + .stderr_matches_path("tests/snapshots/add/invalid_key_inherit_dependency.stderr"); + + assert().subset_matches( + "tests/snapshots/add/invalid_key_inherit_dependency.out", + &project_root, + ); +} + +#[cargo_test] +fn invalid_key_rename_inherit_dependency() { + let project_root = + project_from_template("tests/snapshots/add/invalid_key_rename_inherit_dependency.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["--rename", "foo", "foo-alt", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_matches_path("tests/snapshots/add/invalid_key_rename_inherit_dependency.stdout") + .stderr_matches_path("tests/snapshots/add/invalid_key_rename_inherit_dependency.stderr"); + + assert().subset_matches( + "tests/snapshots/add/invalid_key_rename_inherit_dependency.out", + &project_root, + ); +} + +#[cargo_test] +fn invalid_key_overwrite_inherit_dependency() { + let project_root = + project_from_template("tests/snapshots/add/invalid_key_overwrite_inherit_dependency.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "--default-features", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_matches_path("tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stdout") + .stderr_matches_path("tests/snapshots/add/invalid_key_overwrite_inherit_dependency.stderr"); + + assert().subset_matches( + "tests/snapshots/add/invalid_key_overwrite_inherit_dependency.out", + &project_root, + ); +} + #[cargo_test] fn invalid_path() { init_registry(); From aa7d116a4a288a36b126534d83be03424c863fc8 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 27 Apr 2022 14:15:49 -0500 Subject: [PATCH 7/7] Support overwriting a `foo.workspace = true` with a dependency from a different source --- src/cargo/ops/cargo_add/dependency.rs | 11 ++++- src/cargo/ops/cargo_add/manifest.rs | 8 +++- .../add/overwrite_workspace_dep.in/Cargo.toml | 5 +++ .../dependency/Cargo.toml | 3 ++ .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 ++++ .../primary/src/lib.rs | 0 .../overwrite_workspace_dep.out/Cargo.toml | 5 +++ .../dependency/Cargo.toml | 3 ++ .../primary/Cargo.toml | 8 ++++ .../add/overwrite_workspace_dep.stderr | 1 + .../add/overwrite_workspace_dep.stdout | 0 .../Cargo.toml | 5 +++ .../dependency/Cargo.toml | 14 ++++++ .../dependency/src/lib.rs | 0 .../primary/Cargo.toml | 8 ++++ .../primary/src/lib.rs | 0 .../Cargo.toml | 5 +++ .../dependency/Cargo.toml | 14 ++++++ .../primary/Cargo.toml | 8 ++++ .../overwrite_workspace_dep_features.stderr | 10 +++++ .../overwrite_workspace_dep_features.stdout | 0 tests/testsuite/cargo_add.rs | 45 +++++++++++++++++++ 23 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 tests/snapshots/add/overwrite_workspace_dep.in/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_workspace_dep.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_workspace_dep.out/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep.stderr create mode 100644 tests/snapshots/add/overwrite_workspace_dep.stdout create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.in/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.in/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.in/dependency/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.in/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.in/primary/src/lib.rs create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.out/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.out/dependency/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.out/primary/Cargo.toml create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.stderr create mode 100644 tests/snapshots/add/overwrite_workspace_dep_features.stdout diff --git a/src/cargo/ops/cargo_add/dependency.rs b/src/cargo/ops/cargo_add/dependency.rs index 560b68302a2..0f297872fcf 100644 --- a/src/cargo/ops/cargo_add/dependency.rs +++ b/src/cargo/ops/cargo_add/dependency.rs @@ -3,6 +3,7 @@ use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; use indexmap::IndexSet; +use toml_edit::KeyMut; use super::manifest::str_or_1_len_table; use crate::core::FeatureMap; @@ -476,10 +477,18 @@ impl Dependency { } /// Modify existing entry to match this dependency - pub fn update_toml(&self, crate_root: &Path, item: &mut toml_edit::Item) { + pub fn update_toml<'k>( + &self, + crate_root: &Path, + key: &mut KeyMut<'k>, + item: &mut toml_edit::Item, + ) { if str_or_1_len_table(item) { // Nothing to preserve *item = self.to_toml(crate_root); + if self.source != Some(Source::Workspace(WorkspaceSource)) { + key.fmt(); + } } else if let Some(table) = item.as_table_like_mut() { match &self.source { Some(Source::Registry(src)) => { diff --git a/src/cargo/ops/cargo_add/manifest.rs b/src/cargo/ops/cargo_add/manifest.rs index 63cab6a701d..b90b7808392 100644 --- a/src/cargo/ops/cargo_add/manifest.rs +++ b/src/cargo/ops/cargo_add/manifest.rs @@ -349,8 +349,12 @@ impl LocalManifest { let dep_key = dep.toml_key(); let table = self.get_table_mut(table_path)?; - if let Some(dep_item) = table.as_table_like_mut().unwrap().get_mut(dep_key) { - dep.update_toml(&crate_root, dep_item); + if let Some((mut dep_key, dep_item)) = table + .as_table_like_mut() + .unwrap() + .get_key_value_mut(dep_key) + { + dep.update_toml(&crate_root, &mut dep_key, dep_item); } else { let new_dependency = dep.to_toml(&crate_root); table[dep_key] = new_dependency; diff --git a/tests/snapshots/add/overwrite_workspace_dep.in/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep.in/Cargo.toml new file mode 100644 index 00000000000..a80d4994911 --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.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/overwrite_workspace_dep.in/dependency/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep.in/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.in/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/overwrite_workspace_dep.in/dependency/src/lib.rs b/tests/snapshots/add/overwrite_workspace_dep.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_workspace_dep.in/primary/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep.in/primary/Cargo.toml new file mode 100644 index 00000000000..aaadbceb163 --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.in/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo.workspace = true \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_workspace_dep.in/primary/src/lib.rs b/tests/snapshots/add/overwrite_workspace_dep.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_workspace_dep.out/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep.out/Cargo.toml new file mode 100644 index 00000000000..a80d4994911 --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.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/overwrite_workspace_dep.out/dependency/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep.out/dependency/Cargo.toml new file mode 100644 index 00000000000..2d247d4d26c --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.out/dependency/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "foo" +version = "0.0.0" diff --git a/tests/snapshots/add/overwrite_workspace_dep.out/primary/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep.out/primary/Cargo.toml new file mode 100644 index 00000000000..d44f047917c --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.out/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { version = "0.0.0", path = "../dependency" } diff --git a/tests/snapshots/add/overwrite_workspace_dep.stderr b/tests/snapshots/add/overwrite_workspace_dep.stderr new file mode 100644 index 00000000000..d1bc507572f --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep.stderr @@ -0,0 +1 @@ + Adding foo (local) to dependencies. diff --git a/tests/snapshots/add/overwrite_workspace_dep.stdout b/tests/snapshots/add/overwrite_workspace_dep.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.in/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep_features.in/Cargo.toml new file mode 100644 index 00000000000..a80d4994911 --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_features.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/overwrite_workspace_dep_features.in/dependency/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep_features.in/dependency/Cargo.toml new file mode 100644 index 00000000000..ef9ec7701ba --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_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 = [] diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.in/dependency/src/lib.rs b/tests/snapshots/add/overwrite_workspace_dep_features.in/dependency/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.in/primary/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep_features.in/primary/Cargo.toml new file mode 100644 index 00000000000..7ab3f9dd2c1 --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_features.in/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { workspace = true, features = ["test"] } \ No newline at end of file diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.in/primary/src/lib.rs b/tests/snapshots/add/overwrite_workspace_dep_features.in/primary/src/lib.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.out/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep_features.out/Cargo.toml new file mode 100644 index 00000000000..a80d4994911 --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_features.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/overwrite_workspace_dep_features.out/dependency/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep_features.out/dependency/Cargo.toml new file mode 100644 index 00000000000..ef9ec7701ba --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_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 = [] diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.out/primary/Cargo.toml b/tests/snapshots/add/overwrite_workspace_dep_features.out/primary/Cargo.toml new file mode 100644 index 00000000000..c7301765f5a --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_features.out/primary/Cargo.toml @@ -0,0 +1,8 @@ +cargo-features = ["workspace-inheritance"] + +[package] +name = "bar" +version = "0.0.0" + +[dependencies] +foo = { features = ["test"], path = "../dependency", version = "0.0.0" } diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.stderr b/tests/snapshots/add/overwrite_workspace_dep_features.stderr new file mode 100644 index 00000000000..18ed7c2d8fa --- /dev/null +++ b/tests/snapshots/add/overwrite_workspace_dep_features.stderr @@ -0,0 +1,10 @@ + Adding foo (local) to dependencies. + Features: + + default-base + + default-merge-base + + default-test-base + + test + + test-base + - merge + - merge-base + - unrelated diff --git a/tests/snapshots/add/overwrite_workspace_dep_features.stdout b/tests/snapshots/add/overwrite_workspace_dep_features.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/testsuite/cargo_add.rs b/tests/testsuite/cargo_add.rs index 6e23c7e5416..4f7b5cd13b8 100644 --- a/tests/testsuite/cargo_add.rs +++ b/tests/testsuite/cargo_add.rs @@ -2108,6 +2108,51 @@ fn overwrite_with_rename() { ); } +#[cargo_test] +fn overwrite_workspace_dep() { + init_registry(); + let project_root = project_from_template("tests/snapshots/add/overwrite_workspace_dep.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "--path", "./dependency", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/overwrite_workspace_dep.stdout") + .stderr_matches_path("tests/snapshots/add/overwrite_workspace_dep.stderr"); + + assert().subset_matches( + "tests/snapshots/add/overwrite_workspace_dep.out", + &project_root, + ); +} + +#[cargo_test] +fn overwrite_workspace_dep_features() { + init_registry(); + let project_root = + project_from_template("tests/snapshots/add/overwrite_workspace_dep_features.in"); + let cwd = &project_root; + + cargo_command() + .masquerade_as_nightly_cargo() + .arg("add") + .args(["foo", "--path", "./dependency", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path("tests/snapshots/add/overwrite_workspace_dep_features.stdout") + .stderr_matches_path("tests/snapshots/add/overwrite_workspace_dep_features.stderr"); + + assert().subset_matches( + "tests/snapshots/add/overwrite_workspace_dep_features.out", + &project_root, + ); +} + #[cargo_test] fn preserve_sorted() { init_registry();