use std::{fs::create_dir_all, io::Write, path::PathBuf}; use config::{File, Map}; use serde::{Deserialize, Serialize}; use tracing::{debug, trace}; use crate::{error::{Error, Result}, packages::Manager}; #[derive(Debug, Serialize, Deserialize)] #[serde(default)] pub struct Config { pub root: String, pub directories: Vec, pub custom_directories: Map, pub device: String, pub package_manager: Manager, } impl Default for Config { fn default() -> Self { Self { root: "/mnt/backup".to_string(), directories: vec![], custom_directories: Map::new(), device: gethostname::gethostname() .into_string() .expect("invalid hostname string"), package_manager: Manager::from_sys().expect("couldn't get package manager"), } } } impl Config { pub fn load(path: Option) -> Result { debug!("load config"); let source = if let Some(source) = path { source } else { Self::get_location()? }; let config = config::Config::builder() .add_source(File::with_name(&source.to_string_lossy()).required(false)) .add_source(config::Environment::with_prefix("FXBAUP").separator("_")) .build()?; let cfg = config.try_deserialize()?; trace!(?cfg, "loaded config"); Ok(cfg) } pub fn generate() -> Result<()> { let loc = Self::get_location()?; create_dir_all(loc.parent().unwrap())?; let mut f = std::fs::File::create(loc)?; f.write_all(toml::to_string(&Self::default())?.as_bytes())?; Ok(()) } fn get_location() -> Result { let Some(mut config_dir) = dirs::config_dir() else { return Err(Error::NoSysDir); }; config_dir.push(env!("CARGO_PKG_NAME")); config_dir.push("config.toml"); Ok(config_dir) } }