aboutsummaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2023-07-20 22:04:45 +0100
committerLeonardo Bishop <me@leonardobishop.com>2023-07-20 22:15:25 +0100
commitc3a55debe9e4194f83164d412293f27b797627af (patch)
tree027ca943a051bf51c809eec0f590d598df2db9a3 /src/config.rs
Initial commit
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs93
1 files changed, 93 insertions, 0 deletions
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<String>,
+ pub steps: Option<Vec<Step>>,
+ pub from_file: Option<String>,
+
+ #[serde(skip_deserializing)]
+ pub base_path: PathBuf,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct Config {
+ pub stages: Vec<Stage>,
+
+ #[serde(skip_deserializing)]
+ pub base_path: PathBuf,
+}
+
+#[derive(Debug)]
+struct StageFileError {
+ stage_file: String,
+ cause: Box<dyn std::error::Error>,
+}
+
+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<Stage, Box<dyn std::error::Error>> {
+ 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<Self, Box<dyn std::error::Error>> {
+ 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<Stage> = 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