use std::sync::Mutex;
use tempfile::TempDir;
static XDG_ENV_MUTEX: Mutex<()> = Mutex::new(());
struct EnvState {
home: Option<String>,
xdg_config_home: Option<String>,
xdg_data_home: Option<String>,
}
impl EnvState {
fn capture() -> Self {
Self {
home: std::env::var("HOME").ok(),
xdg_config_home: std::env::var("XDG_CONFIG_HOME").ok(),
xdg_data_home: std::env::var("XDG_DATA_HOME").ok(),
}
}
fn restore(self) {
if let Some(orig) = self.home {
std::env::set_var("HOME", orig);
} else {
std::env::remove_var("HOME");
}
if let Some(orig) = self.xdg_config_home {
std::env::set_var("XDG_CONFIG_HOME", orig);
} else {
std::env::remove_var("XDG_CONFIG_HOME");
}
if let Some(orig) = self.xdg_data_home {
std::env::set_var("XDG_DATA_HOME", orig);
} else {
std::env::remove_var("XDG_DATA_HOME");
}
}
}
pub fn with_xdg_env<F, R>(test_dir: &TempDir, f: F) -> R
where
F: FnOnce() -> R,
{
let _guard = XDG_ENV_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
let env_state = EnvState::capture();
let test_config_home = test_dir.path().to_path_buf();
let test_data_home = test_dir.path().join("data");
let test_home = test_dir.path().join("home");
std::fs::create_dir_all(&test_data_home).unwrap();
std::fs::create_dir_all(&test_home).unwrap();
std::env::set_var("HOME", test_home.to_str().unwrap());
std::env::set_var("XDG_CONFIG_HOME", test_config_home.to_str().unwrap());
std::env::set_var("XDG_DATA_HOME", test_data_home.to_str().unwrap());
let result = f();
env_state.restore();
result
}
pub fn with_xdg_data_home<F, R>(test_dir: &TempDir, f: F) -> R
where
F: FnOnce() -> R,
{
let _guard = XDG_ENV_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
let env_state = EnvState::capture();
let test_data_home = test_dir.path().join("data");
let test_home = test_dir.path().join("home");
std::fs::create_dir_all(&test_data_home).unwrap();
std::fs::create_dir_all(&test_home).unwrap();
std::env::set_var("HOME", test_home.to_str().unwrap());
std::env::set_var("XDG_DATA_HOME", test_data_home.to_str().unwrap());
let result = f();
env_state.restore();
result
}