1use crate::manifest::{Manifest, ManifestPackage};
2use crate::{PrayError, PrayResult};
3use std::collections::BTreeSet;
4
5pub fn package_matches_environment(groups: &[String], environment: Option<&str>) -> bool {
6 if groups.is_empty() {
7 return true;
8 }
9 let Some(selected) = environment else {
10 return false;
11 };
12 groups.iter().any(|group| group == selected)
13}
14
15pub fn collect_group_names(manifest: &Manifest) -> BTreeSet<String> {
16 manifest
17 .packages
18 .iter()
19 .flat_map(|package| package.groups.iter().cloned())
20 .collect()
21}
22
23pub fn validate_environment(manifest: &Manifest, environment: Option<&str>) -> PrayResult<()> {
24 let Some(selected) = environment else {
25 return Ok(());
26 };
27 if selected.is_empty() {
28 return Err(PrayError::Resolution(
29 "environment name cannot be empty".to_string(),
30 ));
31 }
32 let known_groups = collect_group_names(manifest);
33 if known_groups.is_empty() {
34 return Err(PrayError::Resolution(format!(
35 "unknown environment {selected}; Prayfile defines no groups"
36 )));
37 }
38 if !known_groups.contains(selected) {
39 let mut names: Vec<String> = known_groups.into_iter().collect();
40 names.sort();
41 return Err(PrayError::Resolution(format!(
42 "unknown environment {selected}; available groups are {}",
43 names.join(", ")
44 )));
45 }
46 Ok(())
47}
48
49pub fn packages_for_render<'a>(
50 packages: &'a [crate::resolve::ResolvedPackage],
51 environment: Option<&str>,
52) -> Vec<&'a crate::resolve::ResolvedPackage> {
53 packages
54 .iter()
55 .filter(|package| package_matches_environment(&package.declaration.groups, environment))
56 .collect()
57}
58
59pub fn should_render_package(declaration: &ManifestPackage, environment: Option<&str>) -> bool {
60 package_matches_environment(&declaration.groups, environment)
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use crate::manifest::ManifestPackage;
67
68 fn package_with_groups(groups: &[&str]) -> ManifestPackage {
69 ManifestPackage {
70 name: "sample/base".to_string(),
71 groups: groups.iter().map(|group| (*group).to_string()).collect(),
72 ..ManifestPackage::default()
73 }
74 }
75
76 #[test]
77 fn ungrouped_packages_always_render() {
78 let package = package_with_groups(&[]);
79 assert!(should_render_package(&package, None));
80 assert!(should_render_package(&package, Some("development")));
81 }
82
83 #[test]
84 fn grouped_packages_render_only_for_selected_environment() {
85 let package = package_with_groups(&["development", "test"]);
86 assert!(!should_render_package(&package, None));
87 assert!(should_render_package(&package, Some("development")));
88 assert!(should_render_package(&package, Some("test")));
89 assert!(!should_render_package(&package, Some("production")));
90 }
91}