pub fn lock_env_tests() -> std::sync::MutexGuard<'static, ()> {
crate::diff_tool::TEST_MUTEX
.get_or_init(|| std::sync::Mutex::new(()))
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner())
}
pub struct RedirectedConfigDir {
_dir: tempfile::TempDir,
old_xdg: Option<String>,
old_home: Option<String>,
old_userprofile: Option<String>,
}
impl RedirectedConfigDir {
pub fn new() -> Self {
let dir = tempfile::tempdir().unwrap();
let old_xdg = std::env::var("XDG_CONFIG_HOME").ok();
let old_home = std::env::var("HOME").ok();
let old_userprofile = std::env::var("USERPROFILE").ok();
unsafe {
std::env::set_var("XDG_CONFIG_HOME", dir.path());
std::env::set_var("HOME", dir.path());
std::env::set_var("USERPROFILE", dir.path());
}
let seed = crate::settings::AppSettings {
external_diff_tool: crate::settings::DiffToolSetting::Pinned(
crate::diff_tool::ExternalDiffTool::Vim,
),
check_updates: false,
mouse: false,
theme: crate::theme::ThemeChoice::Light,
diff_context: 7,
scan_mode: crate::settings::ScanMode::Precise,
global_exclusions: crate::settings::AppSettings::default().global_exclusions,
respect_gitignore: true,
};
let config_dir = dir.path().join("duodiff");
std::fs::create_dir_all(&config_dir).unwrap();
std::fs::write(
config_dir.join("config.toml"),
toml::to_string(&seed).unwrap(),
)
.unwrap();
Self {
_dir: dir,
old_xdg,
old_home,
old_userprofile,
}
}
}
impl Default for RedirectedConfigDir {
fn default() -> Self {
Self::new()
}
}
impl Drop for RedirectedConfigDir {
fn drop(&mut self) {
unsafe {
match &self.old_xdg {
Some(v) => std::env::set_var("XDG_CONFIG_HOME", v),
None => std::env::remove_var("XDG_CONFIG_HOME"),
}
match &self.old_home {
Some(v) => std::env::set_var("HOME", v),
None => std::env::remove_var("HOME"),
}
match &self.old_userprofile {
Some(v) => std::env::set_var("USERPROFILE", v),
None => std::env::remove_var("USERPROFILE"),
}
}
}
}
pub struct ConfigEnvGuard {
_redirect: RedirectedConfigDir,
_lock: std::sync::MutexGuard<'static, ()>,
}
impl ConfigEnvGuard {
pub fn new() -> Self {
let lock = lock_env_tests();
let redirect = RedirectedConfigDir::new();
Self {
_redirect: redirect,
_lock: lock,
}
}
}
impl Default for ConfigEnvGuard {
fn default() -> Self {
Self::new()
}
}
pub struct RecordingTerminalHandoff {
log: std::rc::Rc<std::cell::RefCell<Vec<&'static str>>>,
}
impl RecordingTerminalHandoff {
pub fn new(log: std::rc::Rc<std::cell::RefCell<Vec<&'static str>>>) -> Self {
log.borrow_mut().push("suspend");
Self { log }
}
}
impl Drop for RecordingTerminalHandoff {
fn drop(&mut self) {
self.log.borrow_mut().push("resume");
}
}
pub struct PathEnvGuard {
old_path: Option<String>,
_lock: std::sync::MutexGuard<'static, ()>,
}
impl PathEnvGuard {
pub fn set(new_path: impl AsRef<std::path::Path>) -> Self {
let lock = lock_env_tests();
let old_path = std::env::var("PATH").ok();
unsafe {
std::env::set_var("PATH", new_path.as_ref());
}
Self {
old_path,
_lock: lock,
}
}
}
impl Drop for PathEnvGuard {
fn drop(&mut self) {
unsafe {
match &self.old_path {
Some(p) => std::env::set_var("PATH", p),
None => std::env::remove_var("PATH"),
}
}
}
}