use std::collections::HashSet;
use std::path::Path;
use std::{env, fs, path::PathBuf};
use crate::{config::CONFIG_FILE_NAME, files::File};
use super::{Config, Error, Result, DIR_NAME};
pub struct ConfigHandler {
config_path: PathBuf,
config: Config,
}
impl ConfigHandler {
pub fn load() -> Result<Self> {
let config_path = Self::get_config_dir()?;
if !config_path.exists() {
fs::create_dir_all(&config_path)?;
}
let config = ConfigHandler::load_config(&config_path)?;
Ok(Self {
config_path,
config,
})
}
#[must_use]
pub fn config(&self) -> &Config {
&self.config
}
#[must_use]
pub fn files(&self) -> &HashSet<PathBuf> {
&self.config.files_to_load
}
#[must_use]
pub fn dirs(&self) -> &HashSet<PathBuf> {
&self.config.directories_to_load
}
pub fn save_config(&self) -> Result<()> {
let config_file = self.config_path.join(CONFIG_FILE_NAME);
Ok(self.config.write_file(&config_file)?)
}
pub fn add_saved_file(&mut self, file: &Path) {
self.config.files_to_load.insert(file.to_path_buf());
}
pub fn remove_saved_file(&mut self, file: &Path) -> bool {
self.config.files_to_load.remove(&file.to_path_buf())
}
pub fn add_saved_directory(&mut self, dir: &Path) {
self.config.directories_to_load.insert(dir.to_path_buf());
}
pub fn remove_saved_directory(&mut self, dir: &Path) -> bool {
self.config.directories_to_load.remove(&dir.to_path_buf())
}
fn load_config(config_path: &Path) -> Result<Config> {
let config_file = config_path.join(CONFIG_FILE_NAME);
let config = if config_file.exists() {
Config::from_file(&config_file)?
} else {
let config = Config::try_default()?;
config.write_file(&config_file)?;
config
};
Ok(config)
}
fn get_config_dir() -> Result<PathBuf> {
#[cfg(unix)]
{
env::var("XDG_CONFIG_DIR")
.map(PathBuf::from)
.map(|p| p.join(DIR_NAME))
.or_else(|_| {
env::var("HOME")
.map(PathBuf::from)
.map(|p| p.join(".config").join(DIR_NAME))
})
.map_err(|_| Error::Directory)
}
#[cfg(windows)]
{
env::var("APPDATA")
.map(PathBuf::from)
.map(|p| p.join(DIR_NAME))
.map_err(|_| Error::Directory)
}
#[cfg(not(any(unix, windows)))]
{
Err(Error::UnknownOs(env::consts::OS.to_string()))
}
}
#[doc(hidden)]
#[must_use]
pub fn in_place() -> Self {
let config_path = PathBuf::from(".");
let config = Self::load_config(&config_path).expect("load config for test");
Self {
config_path,
config,
}
}
}