use std::path::{Path, PathBuf};
use etcetera::{AppStrategy, AppStrategyArgs, choose_app_strategy};
#[derive(Debug, Clone)]
pub struct AppPaths {
config_dir: PathBuf,
data_dir: PathBuf,
}
impl AppPaths {
pub fn new(qualifier: &str, organization: &str, application: &str) -> Option<Self> {
let strategy = choose_app_strategy(AppStrategyArgs {
top_level_domain: qualifier.to_string(),
author: organization.to_string(),
app_name: application.to_string(),
})
.ok()?;
Some(Self {
config_dir: strategy.config_dir(),
data_dir: strategy.data_dir(),
})
}
pub fn for_testing(root: &Path) -> Self {
Self {
config_dir: root.to_path_buf(),
data_dir: root.to_path_buf(),
}
}
pub fn from_dirs(config_dir: PathBuf, data_dir: PathBuf) -> Self {
Self {
config_dir,
data_dir,
}
}
pub fn config_dir(&self) -> &Path {
&self.config_dir
}
pub fn data_dir(&self) -> &Path {
&self.data_dir
}
pub fn config_file(&self, name: &str) -> PathBuf {
self.config_dir.join(format!("{name}.toml"))
}
pub fn data_file(&self, name: &str) -> PathBuf {
self.data_dir.join(format!("{name}.toml"))
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn for_testing_routes_everything_to_root() {
let dir = tempdir().unwrap();
let paths = AppPaths::for_testing(dir.path());
assert_eq!(paths.config_dir(), dir.path());
assert_eq!(paths.data_dir(), dir.path());
assert_eq!(
paths.config_file("recents"),
dir.path().join("recents.toml")
);
assert_eq!(paths.data_file("cache"), dir.path().join("cache.toml"));
}
#[test]
fn from_dirs_keeps_separate_paths() {
let cfg = tempdir().unwrap();
let data = tempdir().unwrap();
let paths = AppPaths::from_dirs(cfg.path().to_path_buf(), data.path().to_path_buf());
assert_eq!(paths.config_dir(), cfg.path());
assert_eq!(paths.data_dir(), data.path());
}
}