use anyhow::Result;
use std::collections::BTreeMap;
use std::path::Path;
use crate::settings::config_file::ConfigFile;
use crate::settings::package_config::PackageConfig;
use crate::settings::scanned_package::ScannedPackage;
pub struct PackageSections {
sections: BTreeMap<String, PackageConfig>,
}
impl PackageSections {
pub fn new(sections: BTreeMap<String, PackageConfig>) -> Self {
Self { sections }
}
pub fn load(directory: &Path) -> Result<Self> {
Ok(Self::new(
ConfigFile::load(directory)?
.map(|file| file.packages)
.unwrap_or_default(),
))
}
pub fn of(&self, name: &str) -> Option<&PackageConfig> {
self.sections.get(name)
}
pub fn skipped_anywhere(&self) -> Vec<String> {
let mut skipped: Vec<String> = self
.sections
.values()
.flat_map(|section| section.skip.iter().cloned())
.collect();
skipped.sort();
skipped.dedup();
skipped
}
pub fn is_empty(&self) -> bool {
self.sections.is_empty()
}
pub fn validate(&self, packages: &[ScannedPackage]) -> Result<()> {
let scanned: Vec<&str> = packages
.iter()
.map(|package| package.name.as_str())
.collect();
let unknown: Vec<&str> = self
.sections
.keys()
.map(String::as_str)
.filter(|name| !scanned.contains(name))
.collect();
if unknown.is_empty() {
return Ok(());
}
Err(anyhow::anyhow!(
"{} configures package(s) this run does not scan: {} -- it scans: {}",
ConfigFile::NAME,
unknown.join(", "),
scanned.join(", ")
))
}
}