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<String>,
pub custom_directories: Map<String, String>,
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<PathBuf>) -> Result<Self> {
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<PathBuf> {
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)
}
}