use std::sync::{Mutex, OnceLock};
static ENV_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
pub(crate) fn with_env_vars<R>(vars: &[(&str, Option<&str>)], f: impl FnOnce() -> R) -> R {
let lock = ENV_LOCK.get_or_init(|| Mutex::new(()));
let _guard = lock.lock().unwrap_or_else(|e| e.into_inner());
struct EnvRestore {
saved: Vec<(String, Option<String>)>,
}
impl Drop for EnvRestore {
fn drop(&mut self) {
for (key, value) in self.saved.drain(..) {
match value {
Some(v) => std::env::set_var(key, v),
None => std::env::remove_var(key),
}
}
}
}
let saved = vars
.iter()
.map(|(key, _)| ((*key).to_string(), std::env::var(key).ok()))
.collect::<Vec<_>>();
for (key, value) in vars {
match value {
Some(v) => std::env::set_var(key, v),
None => std::env::remove_var(key),
}
}
let _restore = EnvRestore { saved };
f()
}