ephemeral_dir/
lib.rs

1use std::fs;
2use std::path::{Path, PathBuf};
3
4pub fn ephemeral_dir(path: impl AsRef<Path>) -> eyre::Result<EphemeralDir> {
5    EphemeralDir::new(path)
6}
7
8pub fn ephemeral_dir_forced(path: impl AsRef<Path>) -> eyre::Result<EphemeralDir> {
9    EphemeralDir::new_forced(path)
10}
11
12pub struct EphemeralDir {
13    // TODO: should we use a Box<Path> here instead of PathBuf?
14    path: PathBuf,
15}
16
17impl EphemeralDir {
18    pub fn new(path: impl AsRef<Path>) -> eyre::Result<Self> {
19        let path = path.as_ref();
20        assert!(!path.exists());
21
22        fs::create_dir_all(path)?;
23
24        Ok(Self {
25            path: PathBuf::from(path),
26        })
27    }
28
29    pub fn new_forced(path: impl AsRef<Path>) -> eyre::Result<Self> {
30        let path = path.as_ref();
31        if path.exists() {
32            fs::remove_dir_all(path)?;
33        }
34
35        Self::new(path)
36    }
37
38    pub fn path(&self) -> &Path {
39        self.path.as_ref()
40    }
41}
42
43impl Drop for EphemeralDir {
44    fn drop(&mut self) {
45        let _ = fs::remove_dir_all(self.path());
46    }
47}
48
49#[test]
50fn test_dir_exists_after_creation() {
51    let path = "/tmp/ephemeral_dir_test";
52    let res_dir = EphemeralDir::new_forced(path);
53    assert!(res_dir.is_ok());
54    let Ok(dir) = res_dir else { unreachable!() };
55    assert!(dir.path().exists());
56    let dir_path_str = format!("{}", dir.path().display());
57    assert_eq!(dir_path_str, path);
58}
59
60#[test]
61fn test_dir_does_not_exist_after_going_out_of_scope() {
62    let path = "/tmp/ephemeral_dir_test";
63    let res_dir = EphemeralDir::new_forced(path);
64    assert!(res_dir.is_ok());
65    {
66        let Ok(dir) = res_dir else { unreachable!() };
67        assert!(dir.path().exists());
68        let dir_path_str = format!("{}", dir.path().display());
69        assert_eq!(dir_path_str, path);
70        let dir_path = Path::new(&dir_path_str);
71        assert!(dir_path.exists());
72    }
73    let path_path = Path::new(path);
74    assert!(!path_path.exists());
75}
76
77#[test]
78fn test_wrapper_functions() {
79    // ephemeral_dir::ephemeral_dir()
80    let path = "/tmp/ephemeral_dir_test";
81    let res_dir = ephemeral_dir(path);
82    assert!(res_dir.is_ok());
83    let Ok(dir) = res_dir else { unreachable!() };
84    assert!(dir.path().exists());
85    let dir_path_str = format!("{}", dir.path().display());
86    assert_eq!(dir_path_str, path);
87
88    // ephemeral_dir::ephemeral_dir_forced()
89    let path = "/tmp/ephemeral_dir_test";
90    let res_dir = ephemeral_dir_forced(path);
91    assert!(res_dir.is_ok());
92    {
93        let Ok(dir) = res_dir else { unreachable!() };
94        assert!(dir.path().exists());
95        let dir_path_str = format!("{}", dir.path().display());
96        assert_eq!(dir_path_str, path);
97        let dir_path = Path::new(&dir_path_str);
98        assert!(dir_path.exists());
99    }
100    let path_path = Path::new(path);
101    assert!(!path_path.exists());
102}