Skip to content

Commit 7b64cb8

Browse files
committed
Show the merged set of activated features to the user when inheriting from a workspace dependency
1 parent 4f1b9b1 commit 7b64cb8

File tree

23 files changed

+206
-14
lines changed

23 files changed

+206
-14
lines changed

src/cargo/ops/cargo_add/dependency.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub struct Dependency {
2828
pub features: Option<IndexSet<String>>,
2929
/// Whether default features are enabled
3030
pub default_features: Option<bool>,
31+
/// List of features inherited from a workspace dependency
32+
pub inherited_features: Option<IndexSet<String>>,
3133

3234
/// Where the dependency comes from
3335
pub source: Option<Source>,
@@ -50,6 +52,7 @@ impl Dependency {
5052
optional: None,
5153
features: None,
5254
default_features: None,
55+
inherited_features: None,
5356
source: None,
5457
registry: None,
5558
rename: None,
@@ -152,6 +155,12 @@ impl Dependency {
152155
self
153156
}
154157

158+
/// Set features as an array of string (does some basic parsing)
159+
pub fn set_inherited_features(mut self, features: IndexSet<String>) -> Self {
160+
self.inherited_features = Some(features);
161+
self
162+
}
163+
155164
/// Get the dependency source
156165
pub fn source(&self) -> Option<&Source> {
157166
self.source.as_ref()
@@ -350,6 +359,7 @@ impl Dependency {
350359
features,
351360
available_features,
352361
optional,
362+
inherited_features: None,
353363
};
354364
Ok(dep)
355365
} else {

src/cargo/ops/cargo_add/mod.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,27 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<(
106106
)
107107
}
108108
}
109+
110+
let available_features = dep
111+
.available_features
112+
.keys()
113+
.map(|s| s.as_ref())
114+
.collect::<BTreeSet<&str>>();
115+
let mut unknown_features: Vec<&str> = Vec::new();
109116
if let Some(req_feats) = dep.features.as_ref() {
110117
let req_feats: BTreeSet<_> = req_feats.iter().map(|s| s.as_str()).collect();
111-
112-
let available_features = dep
113-
.available_features
114-
.keys()
115-
.map(|s| s.as_ref())
116-
.collect::<BTreeSet<&str>>();
117-
118-
let mut unknown_features: Vec<&&str> =
119-
req_feats.difference(&available_features).collect();
120-
unknown_features.sort();
121-
122-
if !unknown_features.is_empty() {
123-
anyhow::bail!("unrecognized features: {unknown_features:?}");
124-
}
118+
unknown_features.extend(req_feats.difference(&available_features).copied());
125119
}
120+
if let Some(inherited_features) = dep.inherited_features.as_ref() {
121+
let inherited_features: BTreeSet<_> =
122+
inherited_features.iter().map(|s| s.as_str()).collect();
123+
unknown_features.extend(inherited_features.difference(&available_features).copied());
124+
}
125+
unknown_features.sort();
126+
if !unknown_features.is_empty() {
127+
anyhow::bail!("unrecognized features: {unknown_features:?}");
128+
}
129+
126130
manifest.insert_into_table(&dep_table, &dep)?;
127131
manifest.gc_dep(dep.toml_key());
128132
}
@@ -564,6 +568,9 @@ fn populate_available_features(
564568
dependency.toml_key(),
565569
dep_item,
566570
)?;
571+
if let Some(features) = dep.features.clone() {
572+
dependency = dependency.set_inherited_features(features);
573+
}
567574
let query = dep.query(config)?;
568575
match query {
569576
MaybeWorkspace::Workspace(_) => {
@@ -645,6 +652,7 @@ fn print_msg(shell: &mut Shell, dep: &Dependency, section: &[String]) -> CargoRe
645652
if dep.default_features().unwrap_or(true) {
646653
activated.insert("default");
647654
}
655+
activated.extend(dep.inherited_features.iter().flatten().map(|s| s.as_str()));
648656
let mut walk: VecDeque<_> = activated.iter().cloned().collect();
649657
while let Some(next) = walk.pop_front() {
650658
walk.extend(
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = ["primary", "dependency"]
3+
4+
[workspace.dependencies]
5+
foo = { version = "0.0.0", path = "./dependency", features = ["merge"] }
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "foo"
3+
version = "0.0.0"
4+
5+
[features]
6+
default-base = []
7+
default-test-base = []
8+
default-merge-base = []
9+
default = ["default-base", "default-test-base", "default-merge-base"]
10+
test-base = []
11+
test = ["test-base", "default-test-base"]
12+
merge-base = []
13+
merge = ["merge-base", "default-merge-base"]
14+
unrelated = []

tests/snapshots/add/merge_activated_features.in/dependency/src/lib.rs

Whitespace-only changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
cargo-features = ["workspace-inheritance"]
2+
3+
[package]
4+
name = "bar"
5+
version = "0.0.0"
6+
7+
[dependencies]
8+
foo = { workspace = true, features = ["test"] }

tests/snapshots/add/merge_activated_features.in/primary/src/lib.rs

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = ["primary", "dependency"]
3+
4+
[workspace.dependencies]
5+
foo = { version = "0.0.0", path = "./dependency", features = ["merge"] }
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "foo"
3+
version = "0.0.0"
4+
5+
[features]
6+
default-base = []
7+
default-test-base = []
8+
default-merge-base = []
9+
default = ["default-base", "default-test-base", "default-merge-base"]
10+
test-base = []
11+
test = ["test-base", "default-test-base"]
12+
merge-base = []
13+
merge = ["merge-base", "default-merge-base"]
14+
unrelated = []
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
cargo-features = ["workspace-inheritance"]
2+
3+
[package]
4+
name = "bar"
5+
version = "0.0.0"
6+
7+
[dependencies]
8+
foo = { workspace = true, features = ["test"] }

0 commit comments

Comments
 (0)