use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
pub(crate) struct TempTree {
root: PathBuf,
}
impl TempTree {
pub(crate) fn new(name: &str) -> Self {
let unique = COUNTER.fetch_add(1, Ordering::Relaxed);
let root =
std::env::temp_dir().join(format!("paths-le-{name}-{}-{unique}", std::process::id()));
let _ = std::fs::remove_dir_all(&root);
std::fs::create_dir_all(&root).expect("a temporary directory");
let root = std::fs::canonicalize(&root).expect("a canonical temporary directory");
Self { root }
}
pub(crate) fn path(&self) -> &Path {
&self.root
}
pub(crate) fn mkdir(&self, relative: &str) -> PathBuf {
let target = self.root.join(relative);
std::fs::create_dir_all(&target).expect("a directory");
target
}
pub(crate) fn write(&self, relative: &str, contents: &str) -> PathBuf {
let target = self.root.join(relative);
if let Some(parent) = target.parent() {
std::fs::create_dir_all(parent).expect("a parent directory");
}
std::fs::write(&target, contents).expect("a file");
target
}
#[cfg(unix)]
pub(crate) fn symlink(&self, target: &str, link: &str) {
let link_path = self.root.join(link);
if let Some(parent) = link_path.parent() {
std::fs::create_dir_all(parent).expect("a parent directory");
}
std::os::unix::fs::symlink(target, link_path).expect("a symlink");
}
}
impl Drop for TempTree {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.root);
}
}