diff --git a/src/db/add_package.rs b/src/db/add_package.rs index bf54ba83c..57856511c 100644 --- a/src/db/add_package.rs +++ b/src/db/add_package.rs @@ -221,13 +221,13 @@ fn convert_dependencies(pkg: &MetadataPackage) -> Vec<(String, String, String)> fn get_features(pkg: &MetadataPackage) -> Vec { let mut features = Vec::with_capacity(pkg.features.len()); if let Some(subfeatures) = pkg.features.get("default") { - features.push(Feature::new("default".into(), subfeatures.clone())); + features.push(Feature::new("default".into(), subfeatures.clone(), false)); }; features.extend( pkg.features .iter() .filter(|(name, _)| *name != "default") - .map(|(name, subfeatures)| Feature::new(name.clone(), subfeatures.clone())), + .map(|(name, subfeatures)| Feature::new(name.clone(), subfeatures.clone(), false)), ); features.extend(get_optional_dependencies(pkg)); features @@ -237,7 +237,14 @@ fn get_optional_dependencies(pkg: &MetadataPackage) -> Vec { pkg.dependencies .iter() .filter(|dep| dep.optional) - .map(|dep| Feature::new(dep.name.clone(), Vec::new())) + .map(|dep| { + let name = if let Some(rename) = &dep.rename { + rename.clone() + } else { + dep.name.clone() + }; + Feature::new(name, Vec::new(), true) + }) .collect() } diff --git a/src/db/migrate.rs b/src/db/migrate.rs index 36d4feb7d..154f6c831 100644 --- a/src/db/migrate.rs +++ b/src/db/migrate.rs @@ -488,6 +488,20 @@ pub fn migrate(version: Option, conn: &mut Client) -> CratesfyiResult<( " ALTER TABLE queue DROP COLUMN registry; " + ), + migration!( + context, + 21, + // description + "Add mark for features that are derived from optional dependencies", + // upgrade query + " + ALTER TYPE feature ADD ATTRIBUTE optional_dependency BOOL; + ", + // downgrade query + " + ALTER TYPE feature DROP ATTRIBUTE optional_dependency; + " ) ]; diff --git a/src/db/types.rs b/src/db/types.rs index 74d5f1e12..1ecc09776 100644 --- a/src/db/types.rs +++ b/src/db/types.rs @@ -6,11 +6,17 @@ use serde::Serialize; pub struct Feature { pub(crate) name: String, pub(crate) subfeatures: Vec, + /// [`None`] when this crate was built before optional dependencies were tracked + pub(crate) optional_dependency: Option, } impl Feature { - pub fn new(name: String, subfeatures: Vec) -> Self { - Feature { name, subfeatures } + pub fn new(name: String, subfeatures: Vec, optional_dependency: bool) -> Self { + Feature { + name, + subfeatures, + optional_dependency: Some(optional_dependency), + } } pub fn is_private(&self) -> bool { diff --git a/src/test/fakes.rs b/src/test/fakes.rs index 14d6350e4..054cc43a0 100644 --- a/src/test/fakes.rs +++ b/src/test/fakes.rs @@ -49,6 +49,7 @@ impl<'a> FakeRelease<'a> { name: "fake-dependency".into(), req: "^1.0.0".into(), kind: None, + rename: None, optional: false, }], targets: vec![Target::dummy_lib("fake_package".into(), None)], diff --git a/src/utils/cargo_metadata.rs b/src/utils/cargo_metadata.rs index 19c274c47..c35337ac3 100644 --- a/src/utils/cargo_metadata.rs +++ b/src/utils/cargo_metadata.rs @@ -132,6 +132,7 @@ pub(crate) struct Dependency { pub(crate) name: String, pub(crate) req: String, pub(crate) kind: Option, + pub(crate) rename: Option, pub(crate) optional: bool, } diff --git a/src/web/features.rs b/src/web/features.rs index ea13cf5bc..ee2f3fade 100644 --- a/src/web/features.rs +++ b/src/web/features.rs @@ -107,8 +107,8 @@ mod tests { #[test] fn test_feature_map_filters_private() { - let private1 = Feature::new("_private1".into(), vec!["feature1".into()]); - let feature2 = Feature::new("feature2".into(), Vec::new()); + let private1 = Feature::new("_private1".into(), vec!["feature1".into()], false); + let feature2 = Feature::new("feature2".into(), Vec::new(), false); let raw = vec![private1.clone(), feature2.clone()]; let feature_map = get_feature_map(raw); @@ -120,14 +120,15 @@ mod tests { #[test] fn test_default_tree_structure_with_nested_default() { - let default = Feature::new(DEFAULT_NAME.into(), vec!["feature1".into()]); - let non_default = Feature::new("non-default".into(), Vec::new()); + let default = Feature::new(DEFAULT_NAME.into(), vec!["feature1".into()], false); + let non_default = Feature::new("non-default".into(), Vec::new(), false); let feature1 = Feature::new( "feature1".into(), vec!["feature2".into(), "feature3".into()], + false, ); - let feature2 = Feature::new("feature2".into(), Vec::new()); - let feature3 = Feature::new("feature3".into(), Vec::new()); + let feature2 = Feature::new("feature2".into(), Vec::new(), false); + let feature3 = Feature::new("feature3".into(), Vec::new(), false); let raw = vec![ default.clone(), @@ -154,9 +155,10 @@ mod tests { let feature1 = Feature::new( "feature1".into(), vec!["feature2".into(), "feature3".into()], + false, ); - let feature2 = Feature::new("feature2".into(), Vec::new()); - let feature3 = Feature::new("feature3".into(), Vec::new()); + let feature2 = Feature::new("feature2".into(), Vec::new(), false); + let feature3 = Feature::new("feature3".into(), Vec::new(), false); let raw = vec![feature3.clone(), feature2.clone(), feature1.clone()]; let mut feature_map = get_feature_map(raw); @@ -171,8 +173,8 @@ mod tests { #[test] fn test_default_tree_structure_single_default() { - let default = Feature::new(DEFAULT_NAME.into(), Vec::new()); - let non_default = Feature::new("non-default".into(), Vec::new()); + let default = Feature::new(DEFAULT_NAME.into(), Vec::new(), false); + let non_default = Feature::new("non-default".into(), Vec::new(), false); let raw = vec![default.clone(), non_default.clone()]; let mut feature_map = get_feature_map(raw); @@ -190,9 +192,10 @@ mod tests { let feature1 = Feature::new( "feature1".into(), vec!["feature10".into(), "feature11".into()], + false, ); - let feature2 = Feature::new("feature2".into(), vec!["feature20".into()]); - let feature3 = Feature::new("feature3".into(), Vec::new()); + let feature2 = Feature::new("feature2".into(), vec!["feature20".into()], false); + let feature3 = Feature::new("feature3".into(), Vec::new(), false); let raw = vec![feature3.clone(), feature2.clone(), feature1.clone()]; let (features, default_len) = order_features_and_count_default_len(raw); @@ -206,8 +209,8 @@ mod tests { #[test] fn test_order_features_and_get_len_single_default() { - let default = Feature::new(DEFAULT_NAME.into(), Vec::new()); - let non_default = Feature::new("non-default".into(), Vec::new()); + let default = Feature::new(DEFAULT_NAME.into(), Vec::new(), false); + let non_default = Feature::new("non-default".into(), Vec::new(), false); let raw = vec![default.clone(), non_default.clone()]; let (features, default_len) = order_features_and_count_default_len(raw);