blue_build_recipe/
module_ext.rs1use std::{
2 collections::HashSet,
3 fs,
4 path::{Path, PathBuf},
5};
6
7use bon::Builder;
8use log::trace;
9use miette::{Context, IntoDiagnostic, Report, Result};
10use serde::{Deserialize, Serialize};
11
12use crate::{AkmodsInfo, FromFileList, Module, base_recipe_path};
13
14#[derive(Default, Serialize, Clone, Deserialize, Debug, Builder)]
15pub struct ModuleExt {
16 #[builder(default)]
17 pub modules: Vec<Module>,
18}
19
20impl FromFileList for ModuleExt {
21 const LIST_KEY: &'static str = "modules";
22
23 fn get_from_file_paths(&self) -> Vec<PathBuf> {
24 self.modules
25 .iter()
26 .filter_map(Module::get_from_file_path)
27 .collect()
28 }
29}
30
31impl TryFrom<&PathBuf> for ModuleExt {
32 type Error = Report;
33
34 fn try_from(value: &PathBuf) -> std::result::Result<Self, Self::Error> {
35 Self::try_from(value.as_path())
36 }
37}
38
39impl TryFrom<&Path> for ModuleExt {
40 type Error = Report;
41
42 fn try_from(file_name: &Path) -> Result<Self> {
43 let file_path = base_recipe_path().join(file_name);
44
45 let file = fs::read_to_string(&file_path)
46 .into_diagnostic()
47 .with_context(|| format!("Failed to open {}", file_path.display()))?;
48
49 serde_yaml::from_str::<Self>(&file).map_or_else(
50 |_| -> Result<Self> {
51 let module = serde_yaml::from_str::<Module>(&file)
52 .into_diagnostic()
53 .wrap_err_with(|| {
54 format!("Failed to parse module file {}", file_path.display())
55 })?;
56 Ok(Self::builder().modules(vec![module]).build())
57 },
58 Ok,
59 )
60 }
61}
62
63impl ModuleExt {
64 #[must_use]
65 pub fn get_akmods_info_list(&self, os_version: &u64) -> Vec<AkmodsInfo> {
66 trace!("get_akmods_image_list({self:#?}, {os_version})");
67
68 let mut seen = HashSet::new();
69
70 self.modules
71 .iter()
72 .filter(|module| {
73 module
74 .required_fields
75 .as_ref()
76 .is_some_and(|rf| rf.module_type.typ() == "akmods")
77 })
78 .filter_map(|module| {
79 Some(
80 module
81 .required_fields
82 .as_ref()?
83 .generate_akmods_info(os_version),
84 )
85 })
86 .filter(|image| seen.insert(image.clone()))
87 .collect()
88 }
89}