Skip to content

Commit dff0ec0

Browse files
committed
Handle dev-dep-only features in remove_dev_deps
1 parent bd7e1b8 commit dff0ec0

2 files changed

Lines changed: 92 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
1212

1313
## [Unreleased]
1414

15+
- Fix bug casing ["feature `...` includes `..`, but `..` is not a dependency" error](https://github.com/taiki-e/cargo-minimal-versions/issues/34).
16+
1517
## [0.6.38] - 2025-09-07
1618

1719
- Distribute prebuilt binaries for powerpc64le/riscv64gc/s390x Linux.

src/manifest.rs

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0 OR MIT
22

33
use std::{
4-
collections::{BTreeMap, BTreeSet},
4+
collections::{BTreeMap, BTreeSet, HashSet},
55
path::Path,
66
};
77

@@ -189,13 +189,68 @@ pub(crate) fn with(cx: &Context, f: impl FnOnce() -> Result<()>) -> Result<()> {
189189
}
190190

191191
fn remove_dev_deps(doc: &mut toml_edit::DocumentMut) {
192-
const KEY: &str = "dev-dependencies";
192+
// Collect dependency names from [dependencies], [build-dependencies], [target.'...'.dependencies], and [target.'...'.build-dependencies].
193+
let mut keeping_features = HashSet::new();
194+
let mut collect_features = |table: &dyn toml_edit::TableLike| {
195+
for key in ["dependencies", "build-dependencies"] {
196+
if let Some(table) = table.get(key).and_then(toml_edit::Item::as_table_like) {
197+
keeping_features.reserve(table.len());
198+
for (name, _) in table.iter() {
199+
keeping_features.insert(name.to_owned());
200+
}
201+
}
202+
}
203+
};
204+
let table = doc.as_table();
205+
collect_features(table);
206+
if let Some(table) = table.get("target").and_then(toml_edit::Item::as_table_like) {
207+
for (_, val) in table.iter() {
208+
if let Some(table) = val.as_table_like() {
209+
collect_features(table);
210+
}
211+
}
212+
}
213+
214+
// Remove [dev-dependencies] and [target.'...'.dev-dependencies], and collect dependency names from it.
193215
let table = doc.as_table_mut();
194-
table.remove(KEY);
216+
let mut removing_features = HashSet::new();
217+
let mut remove_dev_deps = |table: &mut dyn toml_edit::TableLike| {
218+
let removed = table.remove("dev-dependencies");
219+
if let Some(table) = removed.as_ref().and_then(toml_edit::Item::as_table_like) {
220+
for (name, _) in table.iter() {
221+
if !keeping_features.contains(name) {
222+
removing_features.insert(name.to_owned());
223+
}
224+
}
225+
}
226+
};
227+
remove_dev_deps(table);
195228
if let Some(table) = table.get_mut("target").and_then(toml_edit::Item::as_table_like_mut) {
196229
for (_, val) in table.iter_mut() {
197230
if let Some(table) = val.as_table_like_mut() {
198-
table.remove(KEY);
231+
remove_dev_deps(table);
232+
}
233+
}
234+
}
235+
drop(keeping_features);
236+
237+
// Remove dev-dependency-only dependency names from [features].
238+
if let Some(table) = table.get_mut("features").and_then(toml_edit::Item::as_table_like_mut) {
239+
let mut indices = vec![];
240+
for (_, val) in table.iter_mut() {
241+
if let Some(array) = val.as_array_mut() {
242+
for (i, v) in array.iter().enumerate() {
243+
if let Some(v) = v.as_str() {
244+
if let Some((name, _)) = v.split_once('/') {
245+
if removing_features.contains(name) {
246+
indices.push(i);
247+
}
248+
}
249+
}
250+
}
251+
for i in indices.drain(..).rev() {
252+
array.remove(i);
253+
}
199254
}
200255
}
201256
}
@@ -431,4 +486,35 @@ foo = [
431486
]
432487
"
433488
);
489+
490+
test!(
491+
dep_future,
492+
r#"
493+
[features]
494+
f1 = ["d1/f", "d2/f", "d4/f"]
495+
f2 = ["d3/f", "d2/f", "d1/f"]
496+
f3 = ["d2/f"]
497+
498+
[dependencies]
499+
d1 = "1"
500+
[target.'cfg(unix)'.dependencies]
501+
d3 = "1"
502+
[dev-dependencies]
503+
d1 = "1"
504+
d2 = "1"
505+
[target.'cfg(unix)'.dev-dependencies]
506+
d4 = "1"
507+
"#,
508+
r#"
509+
[features]
510+
f1 = ["d1/f"]
511+
f2 = ["d3/f", "d1/f"]
512+
f3 = []
513+
514+
[dependencies]
515+
d1 = "1"
516+
[target.'cfg(unix)'.dependencies]
517+
d3 = "1"
518+
"#
519+
);
434520
}

0 commit comments

Comments
 (0)