projtool/src/dirs.rs

68 lines
1.8 KiB
Rust

#![allow(dead_code)]
use std::fs;
use std::path::PathBuf;
use std::sync::OnceLock;
use anyhow::Result;
const APP_NAME: &str = env!("CARGO_PKG_NAME");
const APP_ORG: &str = "valeth";
static CONFIG: OnceLock<PathBuf> = OnceLock::new();
static DATA: OnceLock<PathBuf> = OnceLock::new();
static CACHE: OnceLock<PathBuf> = OnceLock::new();
static STATE: OnceLock<PathBuf> = OnceLock::new();
static SELECTED_PROJECT_FILE: OnceLock<PathBuf> = OnceLock::new();
pub fn config_path() -> &'static PathBuf {
CONFIG.get_or_init(|| init("XDG_CONFIG_HOME", ".config").unwrap())
}
pub fn data_path() -> &'static PathBuf {
DATA.get_or_init(|| init("XDG_DATA_HOME", ".local/share").unwrap())
}
pub fn cache_path() -> &'static PathBuf {
CACHE.get_or_init(|| init("XDG_CACHE_HOME", ".cache").unwrap())
}
pub fn state_path() -> &'static PathBuf {
STATE.get_or_init(|| init("XDG_STATE_HOME", ".local/state").unwrap())
}
pub fn selected_project_file() -> &'static PathBuf {
SELECTED_PROJECT_FILE.get_or_init(|| state_path().join("selected-project"))
}
fn init(xdg_var: &str, fallback_home_path: &str) -> Result<PathBuf> {
let path = xdg_path_with_fallback(xdg_var, fallback_home_path)?;
if !path.exists() {
fs::create_dir_all(&path)?;
}
Ok(path)
}
fn xdg_path_with_fallback(xdg_var: &str, fallback_home_path: &str) -> Result<PathBuf> {
use std::env;
let user_home = env::var("HOME").expect("HOME variable is not set");
let user_home = PathBuf::from(user_home);
let apply_fallback = |e| match e {
env::VarError::NotPresent => Ok(user_home.join(fallback_home_path)),
_ => Err(e.into()),
};
env::var(xdg_var)
.map(PathBuf::from)
.or_else(apply_fallback)
.map(|path| path.join(APP_ORG).join(APP_NAME))
}