use std::{
ffi::OsString,
sync::{
Mutex,
MutexGuard,
PoisonError,
},
};
static ENV_LOCK: Mutex<()> = Mutex::new(());
pub(crate) struct EnvGuard {
saved: Vec<(&'static str, Option<OsString>)>,
_lock: MutexGuard<'static, ()>,
}
impl EnvGuard {
pub(crate) fn set(vars: &[(&'static str, Option<&str>)]) -> Self {
let lock = ENV_LOCK.lock().unwrap_or_else(PoisonError::into_inner);
let saved = vars
.iter()
.map(|(name, value)| {
let previous = std::env::var_os(name);
match value {
Some(value) => std::env::set_var(name, value),
None => std::env::remove_var(name),
}
(*name, previous)
})
.collect();
Self { saved, _lock: lock }
}
}
impl Drop for EnvGuard {
fn drop(&mut self) {
for (name, previous) in self.saved.drain(..) {
match previous {
Some(value) => std::env::set_var(name, value),
None => std::env::remove_var(name),
}
}
}
}