From c3a55debe9e4194f83164d412293f27b797627af Mon Sep 17 00:00:00 2001 From: Leonardo Bishop Date: Thu, 20 Jul 2023 22:04:45 +0100 Subject: Initial commit --- src/config.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/config.rs (limited to 'src/config.rs') diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..2a0e38b --- /dev/null +++ b/src/config.rs @@ -0,0 +1,93 @@ +use std::{fs::File, path::PathBuf}; +use std::fmt; +use std::error::Error; + +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CopyPath { + pub from: String, + pub to: String, + pub recursive: bool, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum Step { + Link(CopyPath), + Copy(CopyPath), + Shell(String), +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Stage { + pub name: Option, + pub steps: Option>, + pub from_file: Option, + + #[serde(skip_deserializing)] + pub base_path: PathBuf, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Config { + pub stages: Vec, + + #[serde(skip_deserializing)] + pub base_path: PathBuf, +} + +#[derive(Debug)] +struct StageFileError { + stage_file: String, + cause: Box, +} + +impl Error for StageFileError {} + +impl fmt::Display for StageFileError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let stage_file = &self.stage_file; + let cause = &self.cause.to_string(); + + write!(f, "Failed to load stage from file '{stage_file}': {cause}") + } +} + +impl Config { + fn resolve_stage_file(base_path: PathBuf, file_name: &str) -> Result> { + let mut file_path = base_path.clone(); + file_path.push(file_name); + let file = File::open(&file_path)?; + let stage: Stage = serde_yaml::from_reader(file)?; + let parent_path = file_path.parent().unwrap(); + + Ok(Stage { base_path: parent_path.to_path_buf(), ..stage }) + } + + pub fn from_file(file_name: &str) -> Result> { + let base_path = std::env::current_dir()?; + let mut file_path = base_path.clone(); + file_path.push(file_name); + + let file = File::open(&file_path)?; + let loaded_config: Config = serde_yaml::from_reader(file)?; + + let mut stages: Vec = Vec::new(); + + for stage in loaded_config.stages { + if let Some(file_name) = stage.from_file { + match Self::resolve_stage_file(base_path.clone(), &file_name) { + Ok(loaded_stage) => stages.push(loaded_stage), + Err(err) => return Err(Box::new(StageFileError { + stage_file: file_name, + cause: err + })) + } + } else { + stages.push(Stage { base_path: base_path.clone(), ..stage }); + } + } + + Ok(Config { stages, base_path: base_path }) + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2