espforge 0.1.24

A scaffolding++ project generator for ESP32 projects
Documentation
use crate::cli::model::ExampleConfig;
use anyhow::{Context, Result, anyhow, bail};
use std::fs;
use std::path::{Path, PathBuf};

pub struct ConfigFile {
    path: PathBuf,
}

impl ConfigFile {
    const DEFAULT_NAME: &'static str = "example.yaml";

    pub fn locate(base_path: &Path) -> Result<Self> {
        let path = base_path.join(Self::DEFAULT_NAME);

        if !path.exists() {
            bail!("The example template is missing the required 'example.yaml' file");
        }

        Ok(Self { path })
    }

    pub fn update(&self, config: &ExampleConfig) -> Result<()> {
        let mut yaml_doc = self.read_yaml()?;

        Self::apply_project_name(&mut yaml_doc, &config.project_name);
        Self::apply_chip(&mut yaml_doc, &config.chip);

        self.write_yaml(&yaml_doc)
    }

    pub fn rename_to(&self, project_name: &str) -> Result<String> {
        let new_filename = format!("{}.yaml", project_name);
        let new_path = self
            .path
            .parent()
            .ok_or_else(|| anyhow!("Invalid config file path"))?
            .join(&new_filename);

        fs::rename(&self.path, &new_path).context("Failed to rename configuration file")?;

        Ok(project_name.to_string())
    }

    fn read_yaml(&self) -> Result<serde_yaml_ng::Value> {
        let content = fs::read_to_string(&self.path).context("Failed to read example.yaml")?;
        serde_yaml_ng::from_str(&content).context("Failed to parse example.yaml")
    }

    fn write_yaml(&self, doc: &serde_yaml_ng::Value) -> Result<()> {
        let content =
            serde_yaml_ng::to_string(doc).context("Failed to serialize updated config")?;
        fs::write(&self.path, content).context("Failed to write updated example.yaml")
    }

    fn apply_project_name(doc: &mut serde_yaml_ng::Value, name: &str) {
        if let Some(espforge) = doc.get_mut("espforge") {
            espforge["name"] = serde_yaml_ng::Value::String(name.to_string());
        }
    }

    fn apply_chip(doc: &mut serde_yaml_ng::Value, chip: &str) {
        if let Some(espforge) = doc.get_mut("espforge") {
            espforge["platform"] = serde_yaml_ng::Value::String(chip.to_string());
        }
    }
}