use std::path::{Path, PathBuf};
use std::sync::Once;
static INIT_DISABLE_DB: Once = Once::new();
fn ensure_db_disabled_by_default() {
INIT_DISABLE_DB.call_once(|| {
if std::env::var("MOLD_DB_DISABLE").is_err() {
std::env::set_var("MOLD_DB_DISABLE", "1");
}
});
}
pub(crate) static ENV_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
pub(crate) fn enter_test_scope() -> std::sync::MutexGuard<'static, ()> {
ENV_MUTEX.lock().unwrap_or_else(|p| p.into_inner())
}
pub(crate) fn disable_db_for_non_isolated_tests() {
ensure_db_disabled_by_default();
}
pub(crate) fn with_isolated_env<F: FnOnce(&Path)>(f: F) {
ensure_db_disabled_by_default();
let guard = ENV_MUTEX.lock().unwrap_or_else(|p| p.into_inner());
let tmp = unique_tmp_dir();
std::fs::create_dir_all(&tmp).unwrap();
let prev_home = std::env::var("MOLD_HOME").ok();
let prev_dbpath = std::env::var("MOLD_DB_PATH").ok();
let prev_disabled = std::env::var("MOLD_DB_DISABLE").ok();
std::env::set_var("MOLD_HOME", &tmp);
std::env::set_var("MOLD_DB_PATH", tmp.join("mold.db"));
std::env::remove_var("MOLD_DB_DISABLE");
let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&tmp)));
match prev_home {
Some(v) => std::env::set_var("MOLD_HOME", v),
None => std::env::remove_var("MOLD_HOME"),
}
match prev_dbpath {
Some(v) => std::env::set_var("MOLD_DB_PATH", v),
None => std::env::remove_var("MOLD_DB_PATH"),
}
match prev_disabled {
Some(v) => std::env::set_var("MOLD_DB_DISABLE", v),
None => std::env::remove_var("MOLD_DB_DISABLE"),
}
let _ = std::fs::remove_dir_all(&tmp);
drop(guard);
if let Err(payload) = res {
std::panic::resume_unwind(payload);
}
}
fn unique_tmp_dir() -> PathBuf {
std::env::temp_dir().join(format!(
"mold-tui-test-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0)
))
}