From a9aba2dab397b7ae36b30c22b6b58a4972a746ea Mon Sep 17 00:00:00 2001 From: tobinio Date: Sun, 5 May 2024 07:51:42 +0200 Subject: [PATCH 1/2] display removed features --- Cargo.lock | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 6 ++-- src/prune.rs | 7 +++-- 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 559f715..0c769b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,6 +217,7 @@ dependencies = [ "once_cell", "owo-colors", "tracing-error", + "url", ] [[package]] @@ -287,6 +288,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "fuzzy-matcher" version = "0.3.7" @@ -314,6 +324,16 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indenter" version = "0.3.3" @@ -351,6 +371,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "kstring" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" +dependencies = [ + "static_assertions", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -411,6 +440,12 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -505,6 +540,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -552,6 +593,21 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml" version = "0.8.12" @@ -580,6 +636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", + "kstring", "serde", "serde_spanned", "toml_datetime", @@ -627,12 +684,38 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index c76084a..720b4dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.64.0" include = ["src/**/*", "LICENSE", "README.md"] [dependencies] -color-eyre = "0.6.3" +color-eyre = { version = "0.6.3", features = ["issue-url"] } cargo-platform = "0.1.8" cargo_metadata = "0.18.1" clap = { version = "4.5.4", features = ["derive"] } @@ -22,10 +22,10 @@ clap_complete = "4.5.2" console = { version = "0.15.8", default-features = false } ctrlc = "3.4.4" fuzzy-matcher = "0.3.7" -itertools = { version = "0.12.1", default-features = false, features = ["use_alloc"] } +itertools = "0.12.1" semver = { version = "1.0.22", default-features = false } toml = { version = "0.8.12", default-features = false, features = ["parse"] } -toml_edit = { version = "0.22.12", default-features = false, features = ["display"] } +toml_edit = { version = "0.22.12", features = ["perf", "serde", "unbounded"] } [[bin]] name = "cargo-features" diff --git a/src/prune.rs b/src/prune.rs index c98a8e5..fb7151a 100644 --- a/src/prune.rs +++ b/src/prune.rs @@ -239,11 +239,12 @@ fn prune_features( features .iter() .filter(|feature| to_be_disabled.contains(feature)) - .count(), + .map(|feature| style(format!("-{}", feature)).red().to_string()) + .join(","), ); - if to_be_disabled.is_empty().not() { - disabled_count = disabled_count.red(); + if to_be_disabled.is_empty() { + disabled_count = style("0".to_string()); } term.clear_line()?; -- 2.51.2 From 0bd461dab0a7d88591a6f19f6f9c4ac832c0c167 Mon Sep 17 00:00:00 2001 From: tobinio Date: Sun, 5 May 2024 09:13:55 +0200 Subject: [PATCH 2/2] add list of known false positives --- CHANGELOG.md | 2 ++ Cargo.lock | 86 -------------------------------------------- Cargo.toml | 12 +++---- Known-Features.toml | 4 +++ README.md | 13 +++++-- src/prune.rs | 87 +++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 105 insertions(+), 99 deletions(-) create mode 100644 Known-Features.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index c4534da..6173e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ * sort dependencies and packages alphabetically if no filter is set * when running `cargo features prune` correctly handle sub features * improved progress display while running `cargo features prune` +* `cargo features prune` now displays which features get disabled +* add list of known features to ignore when running `cargo features prune` ## 0.7.1 diff --git a/Cargo.lock b/Cargo.lock index 0c769b7..7745ece 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,7 +217,6 @@ dependencies = [ "once_cell", "owo-colors", "tracing-error", - "url", ] [[package]] @@ -288,15 +287,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "fuzzy-matcher" version = "0.3.7" @@ -324,16 +314,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "indenter" version = "0.3.3" @@ -371,15 +351,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "kstring" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" -dependencies = [ - "static_assertions", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -440,12 +411,6 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -540,12 +505,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.11.1" @@ -593,21 +552,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "toml" version = "0.8.12" @@ -617,7 +561,6 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", ] [[package]] @@ -636,9 +579,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", - "kstring", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] @@ -684,38 +624,12 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 720b4dd..8e2cefe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.64.0" include = ["src/**/*", "LICENSE", "README.md"] [dependencies] -color-eyre = { version = "0.6.3", features = ["issue-url"] } +color-eyre = "0.6.3" cargo-platform = "0.1.8" cargo_metadata = "0.18.1" clap = { version = "4.5.4", features = ["derive"] } @@ -22,15 +22,11 @@ clap_complete = "4.5.2" console = { version = "0.15.8", default-features = false } ctrlc = "3.4.4" fuzzy-matcher = "0.3.7" -itertools = "0.12.1" +itertools = { version = "0.12.1", default-features = false, features = ["use_alloc"] } semver = { version = "1.0.22", default-features = false } -toml = { version = "0.8.12", default-features = false, features = ["parse"] } -toml_edit = { version = "0.22.12", features = ["perf", "serde", "unbounded"] } +toml = { version = "0.8.12", default-features = false } +toml_edit = "0.22.12" [[bin]] name = "cargo-features" path = "src/main.rs" - -[cargo-features-manager.keep] -clap = ["default"] -color-eyre = ["default"] diff --git a/Known-Features.toml b/Known-Features.toml new file mode 100644 index 0000000..a87d727 --- /dev/null +++ b/Known-Features.toml @@ -0,0 +1,4 @@ +clap = ["default"] +color-eyre = ["default"] +regex = ["default"] +serde_json = ["preserve_order"] \ No newline at end of file diff --git a/README.md b/README.md index 5967482..d4c7603 100644 --- a/README.md +++ b/README.md @@ -83,10 +83,17 @@ You can run prune with `cargo features prune` this will disable all features which are not required to compile. -### always keep +### false positives -If your project requires features to be enabled which do not make the compile fail. You can add a section to -your `Cargo.toml` named `cargo-features-manager.keep` in there you can define which features will be kept. +Some features may not cause the compilation to fail but still remove functionality. To limit the extent of such cases we +keep a [file](Known-Features.toml) including all known false positives. These features will not be disabled +by `cargo features prune` and instead be display gray letting you know that you should consider if you really need the +feature. + +If you know of any other features that fall under this category fell free to open an Issue or PR! + +If your project requires additional features to be always kept. You can add a section to your `Cargo.toml` +named `cargo-features-manager.keep` in there you can define which features will be kept. ```toml # for individial packages diff --git a/src/prune.rs b/src/prune.rs index fb7151a..1da3db5 100644 --- a/src/prune.rs +++ b/src/prune.rs @@ -23,11 +23,42 @@ pub fn prune(mut document: Document, is_dry_run: bool) -> Result<()> { get_ignored_features("./", "workspace.cargo-features-manager.keep")?; remove_ignored_features(&document, &base_ignored_features, &mut enabled_features)?; - prune_features(&mut document, is_dry_run, &mut term, enabled_features)?; + prune_features( + &mut document, + is_dry_run, + &mut term, + enabled_features, + known_features()?, + )?; Ok(()) } +//give a map of known features that do not affect completion but remove functionality +pub fn known_features() -> Result>> { + let file = include_str!("../Known-Features.toml"); + + let document: toml_edit::DocumentMut = file.parse()?; + + let mut map = HashMap::new(); + + for (dependency, features) in document.as_table() { + let features = features + .as_array() + .context("could not parse Known-Features.toml")?; + + let features = features + .iter() + .filter_map(|item| item.as_str()) + .map(|name| name.to_string()) + .collect_vec(); + + map.insert(dependency.to_string(), features); + } + + Ok(map) +} + type FeaturesToTest = HashMap>>; fn get_enabled_features(document: &Document) -> FeaturesToTest { @@ -115,6 +146,7 @@ fn prune_features( is_dry_run: bool, term: &mut Term, features: FeaturesToTest, + known_features: HashMap>, ) -> Result<()> { let feature_count = features .values() @@ -122,6 +154,8 @@ fn prune_features( .flatten() .count(); + let mut has_known_features_enabled = false; + let mut checked_features_count = 0; writeln!( @@ -166,7 +200,21 @@ fn prune_features( continue; } + let mut known_features_list = vec![]; + let dependency = document + .get_package(&package_name)? + .get_dep(&dependency_name)?; + + for feature_name in known_features.get(&dependency_name).unwrap_or(&vec![]) { + set_features_to_be_keept( + dependency, + feature_name.to_string(), + &mut known_features_list, + ) + } + let mut to_be_disabled = vec![]; + to_be_disabled.append(&mut known_features_list.clone()); for (id, feature) in features.iter().enumerate() { term.clear_line()?; @@ -239,7 +287,14 @@ fn prune_features( features .iter() .filter(|feature| to_be_disabled.contains(feature)) - .map(|feature| style(format!("-{}", feature)).red().to_string()) + .map(|feature| { + if known_features_list.contains(feature) { + has_known_features_enabled = true; + style(feature).color256(7).to_string() + } else { + style(format!("-{}", feature)).red().to_string() + } + }) .join(","), ); @@ -263,6 +318,10 @@ fn prune_features( if to_be_disabled.is_empty().not() { for feature in to_be_disabled { + if known_features_list.contains(&feature) { + continue; + } + document .get_package_mut(&package_name)? .get_dep_mut(&dependency_name)? @@ -274,6 +333,12 @@ fn prune_features( } } + if has_known_features_enabled { + term.clear_line()?; + writeln!(term)?; + writeln!(term, "Some features that do not affect compilation but can limit functionally where found. For more information refer to https://github.com/ToBinio/cargo-features-manager?tab=readme-ov-file#prune")?; + } + Ok(()) } @@ -301,6 +366,24 @@ fn set_features_to_be_disabled( }); } +fn set_features_to_be_keept( + dependency: &Dependency, + feature: String, + to_be_disabled: &mut Vec, +) { + if to_be_disabled.contains(&feature) { + return; + } + + to_be_disabled.push(feature.clone()); + + if let Some(feature) = dependency.get_feature(&feature) { + for sub_feature in &feature.sub_features { + set_features_to_be_keept(dependency, sub_feature.name.clone(), to_be_disabled); + } + } +} + fn check() -> Result { if !build()? { return Ok(false); -- 2.51.2