#![allow(dead_code)]
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
const XDG_VARS: &[&str] = &[
"HOME",
"XDG_CONFIG_HOME",
"XDG_DATA_HOME",
"XDG_STATE_HOME",
"XDG_CACHE_HOME",
];
pub struct XdgSandbox {
tmp: TempDir,
saved: Vec<(&'static str, Option<OsString>)>,
}
impl XdgSandbox {
pub fn new() -> Self {
let tmp = tempfile::tempdir().expect("create xdg sandbox tempdir");
let mut sandbox = Self {
tmp,
saved: Vec::with_capacity(XDG_VARS.len()),
};
for &var in XDG_VARS {
sandbox.saved.push((var, std::env::var_os(var)));
let dir = sandbox.tmp.path().join(subdir_for(var));
std::fs::create_dir_all(&dir).expect("create xdg subdir");
std::env::set_var(var, &dir);
}
sandbox
}
pub fn path(&self) -> &Path {
self.tmp.path()
}
pub fn data_dir(&self) -> PathBuf {
self.tmp.path().join("data").join("qli")
}
pub fn extensions_dir(&self) -> PathBuf {
self.data_dir().join("extensions")
}
pub fn state_dir(&self) -> PathBuf {
self.tmp.path().join("state").join("qli")
}
}
impl Drop for XdgSandbox {
fn drop(&mut self) {
for (var, prev) in self.saved.drain(..) {
match prev {
Some(v) => std::env::set_var(var, v),
None => std::env::remove_var(var),
}
}
}
}
fn subdir_for(var: &str) -> &'static str {
match var {
"HOME" => "home",
"XDG_CONFIG_HOME" => "config",
"XDG_DATA_HOME" => "data",
"XDG_STATE_HOME" => "state",
"XDG_CACHE_HOME" => "cache",
_ => unreachable!("unknown xdg var: {var}"),
}
}