ikki_config/
parse.rs

1use crate::{deps::parse_deps, parse_image_config, Image, ImageConfig};
2use kdl::{KdlDocument, KdlError};
3use toposort::Toposort;
4
5use thiserror::Error;
6
7pub type BuildOrder = Vec<Vec<String>>;
8
9#[derive(Error, Debug)]
10pub enum IkkiConfigError {
11    #[error("Invalid Ikki configuration: {0}")]
12    InvalidConfiguration(String),
13    #[error("Configuration deserialization failed: {0}")]
14    Knuffel(#[from] knuffel::Error),
15}
16
17#[derive(Debug)]
18pub struct IkkiConfig {
19    image_config: ImageConfig,
20    build_order: Vec<Vec<String>>,
21}
22
23impl IkkiConfig {
24    pub fn images(&self) -> &Vec<Image> {
25        &self.image_config.images.images
26    }
27
28    pub fn find_image(&self, name: &str) -> Option<&Image> {
29        self.image_config
30            .images
31            .images
32            .iter()
33            .find(|img| img.name == name)
34    }
35
36    pub fn build_order(&self) -> BuildOrder {
37        self.build_order.clone()
38    }
39}
40
41pub fn parse(filename: &str, input: &str) -> Result<IkkiConfig, IkkiConfigError> {
42    let doc: KdlDocument = input
43        .parse()
44        .map_err(|e: KdlError| IkkiConfigError::InvalidConfiguration(e.to_string()))?;
45
46    let images = doc
47        .get("images")
48        .ok_or(IkkiConfigError::InvalidConfiguration(
49            "missing `images` configuration".to_string(),
50        ))?;
51
52    let dependencies = doc.get("dependencies");
53    let image_config = parse_image_config(filename, &images.to_string())?;
54    let build_order = dependencies
55        .map(|deps| {
56            let dag = parse_deps(deps);
57            dag.toposort().unwrap_or_default()
58        })
59        .unwrap_or_else(|| {
60            let image_names = image_config.image_names();
61            vec![image_names]
62        });
63
64    Ok(IkkiConfig {
65        image_config,
66        build_order,
67    })
68}