From adfee954840aa84b1e1a5605f0b5cf727bed324e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:08:49 +0100 Subject: [PATCH] Support including other config files from a config file This will allow significantly reducing the amount of duplication between all the different configs used by Redox OS. --- src/config/general.rs | 8 ++++++++ src/config/mod.rs | 47 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/config/general.rs b/src/config/general.rs index 1ef4807..7ed6c33 100644 --- a/src/config/general.rs +++ b/src/config/general.rs @@ -5,3 +5,11 @@ pub struct GeneralConfig { pub repo_binary: Option<bool>, pub efi_partition_size: Option<u32>, //MiB } + +impl GeneralConfig { + pub(super) fn merge(&mut self, other: GeneralConfig) { + self.prompt = other.prompt; + self.repo_binary = other.repo_binary.or(self.repo_binary); + self.efi_partition_size = other.efi_partition_size.or(self.efi_partition_size); + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 712803b..e6ff206 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use std::fs; -use std::path::Path; +use std::mem; +use std::path::{Path, PathBuf}; pub mod file; pub mod general; @@ -9,6 +10,8 @@ pub mod user; #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Config { + #[serde(default)] + pub include: Vec<PathBuf>, pub general: general::GeneralConfig, #[serde(default)] pub packages: BTreeMap<String, package::PackageConfig>, @@ -20,7 +23,7 @@ pub struct Config { impl Config { pub fn from_file(path: &Path) -> Result<Self, failure::Error> { - let config = match fs::read_to_string(&path) { + let mut config: Config = match fs::read_to_string(&path) { Ok(config_data) => match toml::from_str(&config_data) { Ok(config) => config, Err(err) => { @@ -31,6 +34,46 @@ impl Config { return Err(format_err!("{}: failed to read: {}", path.display(), err)); } }; + + let config_dir = path.parent().unwrap(); + + let mut configs = mem::take(&mut config.include) + .into_iter() + .map(|path| Config::from_file(&config_dir.join(path))) + .collect::<Result<Vec<Config>, failure::Error>>()?; + configs.push(config); // Put ourself last to ensure that it overwrites anything else. + + config = configs.remove(0); + + for other_config in configs { + config.merge(other_config); + } + Ok(config) } + + pub fn merge(&mut self, other: Config) { + assert!(self.include.is_empty()); + assert!(other.include.is_empty()); + + let Config { + include: _, + general: other_general, + packages: other_packages, + files: other_files, + users: other_users, + } = other; + + self.general.merge(other_general); + + for (package, package_config) in other_packages { + self.packages.insert(package, package_config); + } + + self.files.extend(other_files); + + for (user, user_config) in other_users { + self.users.insert(user, user_config); + } + } } -- GitLab