use std::{fmt::{Display, Formatter},
ops::Deref,
path::Path};
use miette::IntoDiagnostic;
use crate::friendly_random_id::generate_friendly_random_id;
#[derive(Debug)]
pub struct TempDir {
pub inner: std::path::PathBuf,
}
impl TempDir {
pub fn join<P: AsRef<Path>>(&self, path: P) -> std::path::PathBuf {
self.inner.join(path)
}
}
pub fn try_create_temp_dir() -> miette::Result<TempDir> {
let root = std::env::temp_dir();
let new_temp_dir = root.join(generate_friendly_random_id().as_str());
std::fs::create_dir(&new_temp_dir).into_diagnostic()?;
Ok(TempDir {
inner: new_temp_dir,
})
}
#[macro_export]
macro_rules! try_create_temp_dir_and_cd {
($sub_dir:expr) => {{
let temp_dir_root = $crate::try_create_temp_dir()?;
let sub_dir_path = temp_dir_root.join($sub_dir);
$crate::try_mkdir(
&sub_dir_path,
$crate::MkdirOptions::CreateIntermediateDirectories,
)?;
$crate::try_cd(&sub_dir_path)?;
(temp_dir_root, sub_dir_path)
}};
() => {{
let temp_dir_root = $crate::try_create_temp_dir()?;
$crate::try_cd(&temp_dir_root)?;
temp_dir_root
}};
}
impl Drop for TempDir {
fn drop(&mut self) {
std::fs::remove_dir_all(&self.inner).ok();
}
}
impl Deref for TempDir {
type Target = std::path::PathBuf;
fn deref(&self) -> &Self::Target { &self.inner }
}
impl Display for TempDir {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.inner.display())
}
}
impl AsRef<Path> for TempDir {
fn as_ref(&self) -> &Path { &self.inner }
}
#[cfg(test)]
mod tests_temp_dir {
use super::*;
use crate::{fg_lizard_green, ok};
#[test]
#[allow(clippy::missing_errors_doc)]
fn test_macro_try_create_temp_dir_and_cd() -> miette::Result<()> {
{
let (temp_dir_root, sub_dir) = try_create_temp_dir_and_cd!("test_sub_dir");
println!(
"Temp dir root: {}",
fg_lizard_green(temp_dir_root.inner.display().to_string())
);
println!(
"Subfolder: {}",
fg_lizard_green(sub_dir.display().to_string())
);
assert!(temp_dir_root.inner.exists());
assert!(sub_dir.exists());
let copy_of_path = temp_dir_root.inner.clone();
drop(temp_dir_root);
assert!(!copy_of_path.exists());
assert!(!sub_dir.exists());
}
{
let temp_dir_root = try_create_temp_dir_and_cd!();
println!(
"Temp dir root: {}",
fg_lizard_green(temp_dir_root.inner.display().to_string())
);
assert!(temp_dir_root.inner.exists());
let copy_of_path = temp_dir_root.inner.clone();
drop(temp_dir_root);
assert!(!copy_of_path.exists());
}
ok!()
}
#[test]
fn test_temp_dir() {
let temp_dir = try_create_temp_dir().unwrap();
println!(
"Temp dir: {}",
fg_lizard_green(temp_dir.inner.display().to_string())
);
assert!(temp_dir.inner.exists());
}
#[test]
fn test_temp_dir_join() {
let temp_dir = try_create_temp_dir().unwrap();
let expected_prefix = temp_dir.inner.display().to_string();
let new_sub_dir = temp_dir.join("test_set_file_executable");
let expected_postfix = new_sub_dir.display().to_string();
let expected_full_path = new_sub_dir.display().to_string();
assert!(temp_dir.exists());
assert!(!new_sub_dir.exists());
assert!(expected_full_path.starts_with(&expected_prefix));
assert!(expected_full_path.ends_with(&expected_postfix));
}
#[test]
fn test_temp_dir_drop() {
let temp_dir = try_create_temp_dir().unwrap();
let copy_of_path = temp_dir.inner.clone();
println!(
"Temp dir: {}",
fg_lizard_green(copy_of_path.display().to_string())
);
drop(temp_dir);
assert!(!copy_of_path.exists());
}
}