Skip to content

Commit 4544888

Browse files
endosamajfrolich
authored andcommitted
allowed-dependents
1 parent 1683ae2 commit 4544888

File tree

3 files changed

+261
-0
lines changed

3 files changed

+261
-0
lines changed

src/bsconfig.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ pub struct T {
179179
// this is a new feature of rewatch, and it's not part of the bsconfig.json spec
180180
#[serde(rename = "namespace-entry")]
181181
pub namespace_entry: Option<String>,
182+
// this is a new feature of rewatch, and it's not part of the bsconfig.json spec
183+
#[serde(rename = "allowed-dependents")]
184+
pub allowed_dependents: Option<Vec<String>>,
182185
}
183186

184187
/// This flattens string flags

src/build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,12 @@ pub fn build(filter: &Option<regex::Regex>, path: &str, no_timing: bool) -> Resu
7575
.as_secs_f64()
7676
);
7777

78+
if !packages::validate_packages_dependencies(&packages) {
79+
return Err(());
80+
}
81+
7882
let timing_source_files = Instant::now();
83+
7984
print!(
8085
"{} {} Finding source files...",
8186
style("[2/7]").bold().dim(),

src/build/packages.rs

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,3 +706,256 @@ impl Package {
706706
}
707707
}
708708
}
709+
710+
fn get_unallowed_dependents(
711+
packages: &AHashMap<String, Package>,
712+
package_name: &String,
713+
dependencies: &Vec<String>,
714+
) -> Option<String> {
715+
for deps_package_name in dependencies {
716+
if let Some(deps_package) = packages.get(deps_package_name) {
717+
let deps_allowed_dependents = deps_package.bsconfig.allowed_dependents.to_owned();
718+
if let Some(allowed_dependents) = deps_allowed_dependents {
719+
if !allowed_dependents.contains(package_name) {
720+
return Some(deps_package_name.to_string());
721+
}
722+
}
723+
}
724+
}
725+
return None;
726+
}
727+
#[derive(Debug, Clone)]
728+
struct UnallowedDependency {
729+
bs_deps: Vec<String>,
730+
pinned_deps: Vec<String>,
731+
bs_dev_deps: Vec<String>,
732+
}
733+
734+
pub fn validate_packages_dependencies(packages: &AHashMap<String, Package>) -> bool {
735+
let mut detected_unallowed_dependencies: AHashMap<String, UnallowedDependency> = AHashMap::new();
736+
737+
for (package_name, package) in packages {
738+
let bs_dependencies = &package.bsconfig.bs_dependencies.to_owned().unwrap_or(vec![]);
739+
let pinned_dependencies = &package.bsconfig.pinned_dependencies.to_owned().unwrap_or(vec![]);
740+
let dev_dependencies = &package.bsconfig.bs_dev_dependencies.to_owned().unwrap_or(vec![]);
741+
742+
vec![
743+
("bs-dependencies", bs_dependencies),
744+
("pinned-dependencies", pinned_dependencies),
745+
("bs-dev-dependencies", dev_dependencies),
746+
]
747+
.iter()
748+
.for_each(|(dependency_type, dependencies)| {
749+
if let Some(unallowed_dependency_name) = get_unallowed_dependents(packages, package_name, dependencies) {
750+
let empty_unallowed_deps = UnallowedDependency{
751+
bs_deps: vec![],
752+
pinned_deps: vec![],
753+
bs_dev_deps: vec![],
754+
};
755+
756+
let unallowed_dependency = detected_unallowed_dependencies.entry(String::from(package_name));
757+
let value = unallowed_dependency
758+
.or_insert_with(||empty_unallowed_deps);
759+
match dependency_type {
760+
&"bs-dependencies" => value.bs_deps.push(String::from(unallowed_dependency_name)),
761+
&"pinned-dependencies" => value.pinned_deps.push(String::from(unallowed_dependency_name)),
762+
&"bs-dev-dependencies" => value.bs_dev_deps.push(String::from(unallowed_dependency_name)),
763+
_ => (),
764+
}
765+
766+
}
767+
});
768+
}
769+
for (package_name, unallowed_deps) in detected_unallowed_dependencies.iter() {
770+
println!(
771+
"\n{}: {} has the following unallowed dependencies:",
772+
console::style("Error").red(),
773+
console::style(package_name).bold()
774+
);
775+
776+
vec![
777+
("bs-dependencies", unallowed_deps.bs_deps.to_owned()),
778+
("pinned-dependencies", unallowed_deps.pinned_deps.to_owned()),
779+
("bs-dev-dependencies", unallowed_deps.bs_dev_deps.to_owned()),
780+
]
781+
.iter()
782+
.for_each(|(deps_type, map)| {
783+
if map.len() > 0 {
784+
println!(
785+
"{} dependencies: {}",
786+
console::style(deps_type).bold().dim(),
787+
console::style(map.join(" \n -")).bold().dim()
788+
);
789+
}
790+
});
791+
}
792+
let has_any_unallowed_dependent = detected_unallowed_dependencies.len() > 0;
793+
794+
if has_any_unallowed_dependent {
795+
println!("\nUpdate the {} value in the {} of the unallowed dependencies to solve the issue!",
796+
console::style("unallowed_dependents").bold().dim(),
797+
console::style("bsconfig.json").bold().dim()
798+
)
799+
}
800+
return !has_any_unallowed_dependent;
801+
}
802+
803+
#[cfg(test)]
804+
mod test {
805+
use crate::bsconfig::Source;
806+
use ahash::{AHashMap, AHashSet};
807+
808+
use super::{Package, Namespace};
809+
810+
fn create_package(
811+
name: String,
812+
bs_deps: Vec<String>,
813+
pinned_deps: Vec<String>,
814+
dev_deps: Vec<String>,
815+
allowed_dependents: Option<Vec<String>>,
816+
) -> Package {
817+
return Package {
818+
name: name.clone(),
819+
bsconfig: crate::bsconfig::T {
820+
name: name.clone(),
821+
sources: crate::bsconfig::OneOrMore::Single(Source::Shorthand(String::from("Source"))),
822+
package_specs: None,
823+
warnings: None,
824+
suffix: None,
825+
pinned_dependencies: Some(pinned_deps),
826+
bs_dependencies: Some(bs_deps),
827+
bs_dev_dependencies: Some(dev_deps),
828+
ppx_flags: None,
829+
bsc_flags: None,
830+
reason: None,
831+
namespace: None,
832+
jsx: None,
833+
uncurried: None,
834+
namespace_entry: None,
835+
allowed_dependents,
836+
},
837+
source_folders: AHashSet::new(),
838+
source_files: None,
839+
namespace: Namespace::Namespace(String::from("Package1")),
840+
modules: None,
841+
package_dir: String::from("./something"),
842+
dirs: None,
843+
is_pinned_dep: false,
844+
is_root: false,
845+
};
846+
}
847+
#[test]
848+
fn test_validate_packages_dependencies_unallowed_dependents_should_return_false_with_invalid_parents_as_bs_dependencies(
849+
) {
850+
let mut packages: AHashMap<String, Package> = AHashMap::new();
851+
packages.insert(
852+
String::from("Package1"),
853+
create_package(
854+
String::from("Package1"),
855+
vec![String::from("Package2")],
856+
vec![],
857+
vec![],
858+
None,
859+
),
860+
);
861+
packages.insert(
862+
String::from("Package2"),
863+
create_package(
864+
String::from("Package2"),
865+
vec![],
866+
vec![],
867+
vec![],
868+
Some(vec![String::from("Package3")]),
869+
),
870+
);
871+
872+
let is_valid = super::validate_packages_dependencies(&packages);
873+
assert_eq!(is_valid, false)
874+
}
875+
876+
#[test]
877+
fn test_validate_packages_dependencies_unallowed_dependents_should_return_false_with_invalid_parents_as_pinned_dependencies(
878+
) {
879+
let mut packages: AHashMap<String, Package> = AHashMap::new();
880+
packages.insert(
881+
String::from("Package1"),
882+
create_package(
883+
String::from("Package1"),
884+
vec![],
885+
vec![String::from("Package2")],
886+
vec![],
887+
None,
888+
),
889+
);
890+
packages.insert(
891+
String::from("Package2"),
892+
create_package(
893+
String::from("Package2"),
894+
vec![],
895+
vec![],
896+
vec![],
897+
Some(vec![String::from("Package3")]),
898+
),
899+
);
900+
901+
let is_valid = super::validate_packages_dependencies(&packages);
902+
assert_eq!(is_valid, false)
903+
}
904+
905+
#[test]
906+
fn test_validate_packages_dependencies_unallowed_dependents_should_return_false_with_invalid_parents_as_dev_dependencies(
907+
) {
908+
let mut packages: AHashMap<String, Package> = AHashMap::new();
909+
packages.insert(
910+
String::from("Package1"),
911+
create_package(
912+
String::from("Package1"),
913+
vec![],
914+
vec![],
915+
vec![String::from("Package2")],
916+
None,
917+
),
918+
);
919+
packages.insert(
920+
String::from("Package2"),
921+
create_package(
922+
String::from("Package2"),
923+
vec![],
924+
vec![],
925+
vec![],
926+
Some(vec![String::from("Package3")]),
927+
),
928+
);
929+
930+
let is_valid = super::validate_packages_dependencies(&packages);
931+
assert_eq!(is_valid, false)
932+
}
933+
934+
#[test]
935+
fn test_validate_packages_dependencies_unallowed_dependents_should_return_true_with_no_invalid_parent() {
936+
let mut packages: AHashMap<String, Package> = AHashMap::new();
937+
packages.insert(
938+
String::from("Package1"),
939+
create_package(
940+
String::from("Package1"),
941+
vec![String::from("Package2")],
942+
vec![],
943+
vec![],
944+
None,
945+
),
946+
);
947+
packages.insert(
948+
String::from("Package2"),
949+
create_package(
950+
String::from("Package2"),
951+
vec![],
952+
vec![],
953+
vec![],
954+
Some(vec![String::from("Package1")]),
955+
),
956+
);
957+
958+
let is_valid = super::validate_packages_dependencies(&packages);
959+
assert_eq!(is_valid, true)
960+
}
961+
}

0 commit comments

Comments
 (0)