use std::env;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use directories::ProjectDirs;
#[derive(Debug, Clone)]
pub struct AppPaths {
pub root: Option<PathBuf>,
pub config_dir: PathBuf,
pub data_dir: PathBuf,
pub log_dir: PathBuf,
pub config_file: PathBuf,
pub database_path: PathBuf,
}
impl AppPaths {
pub fn discover(database_override: Option<PathBuf>) -> Result<Self> {
if let Ok(root) = env::var("CARGOWATCH_HOME") {
let root = PathBuf::from(root);
let config_dir = root.join("config");
let data_dir = root.join("data");
let log_dir = root.join("logs");
let config_file = config_dir.join("config.toml");
let database_path = database_override.unwrap_or_else(|| data_dir.join("cargowatch.db"));
return Ok(Self {
root: Some(root),
config_dir,
data_dir,
log_dir,
config_file,
database_path,
});
}
let project_dirs = ProjectDirs::from("dev", "cargowatch", "CargoWatch")
.context("failed to resolve application directories")?;
let config_dir = project_dirs.config_dir().to_path_buf();
let data_dir = project_dirs.data_local_dir().to_path_buf();
let log_dir = data_dir.join("logs");
let config_file = config_dir.join("config.toml");
let database_path = database_override.unwrap_or_else(|| data_dir.join("cargowatch.db"));
Ok(Self {
root: None,
config_dir,
data_dir,
log_dir,
config_file,
database_path,
})
}
pub fn ensure_exists(&self) -> Result<()> {
std::fs::create_dir_all(&self.config_dir)
.with_context(|| format!("failed to create {}", self.config_dir.display()))?;
std::fs::create_dir_all(&self.data_dir)
.with_context(|| format!("failed to create {}", self.data_dir.display()))?;
std::fs::create_dir_all(&self.log_dir)
.with_context(|| format!("failed to create {}", self.log_dir.display()))?;
Ok(())
}
pub fn config_file(&self) -> &Path {
&self.config_file
}
}