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
12#[derive(Debug)]
13pub struct EphemeralDir {
14 path: PathBuf,
16}
17
18impl EphemeralDir {
19 pub fn new(path: impl AsRef<Path>) -> eyre::Result<Self> {
20 let path = path.as_ref();
21 assert!(!path.exists());
22
23 fs::create_dir_all(path)?;
24
25 Ok(Self {
26 path: PathBuf::from(path),
27 })
28 }
29
30 pub fn new_forced(path: impl AsRef<Path>) -> eyre::Result<Self> {
31 let path = path.as_ref();
32 if path.exists() {
33 fs::remove_dir_all(path)?;
34 }
35
36 Self::new(path)
37 }
38
39 pub fn path(&self) -> &Path {
40 self.path.as_ref()
41 }
42}
43
44impl Drop for EphemeralDir {
45 fn drop(&mut self) {
46 let _ = fs::remove_dir_all(self.path());
47 }
48}
49
50impl AsRef<Path> for EphemeralDir {
51 fn as_ref(&self) -> &Path {
52 self.path()
53 }
54}
55
56#[test]
57fn test_dir_exists_after_creation() {
58 let path = "/tmp/ephemeral_dir_test";
59 let res_dir = EphemeralDir::new_forced(path);
60 assert!(res_dir.is_ok());
61 let Ok(dir) = res_dir else { unreachable!() };
62 assert!(dir.path().exists());
63 let dir_path_str = format!("{}", dir.path().display());
64 assert_eq!(dir_path_str, path);
65}
66
67#[test]
68fn test_dir_does_not_exist_after_going_out_of_scope() {
69 let path = "/tmp/ephemeral_dir_test";
70 let res_dir = EphemeralDir::new_forced(path);
71 assert!(res_dir.is_ok());
72 {
73 let Ok(dir) = res_dir else { unreachable!() };
74 assert!(dir.path().exists());
75 let dir_path_str = format!("{}", dir.path().display());
76 assert_eq!(dir_path_str, path);
77 let dir_path = Path::new(&dir_path_str);
78 assert!(dir_path.exists());
79 }
80 let path_path = Path::new(path);
81 assert!(!path_path.exists());
82}
83
84#[test]
85fn test_wrapper_functions() {
86 let path = "/tmp/ephemeral_dir_test";
88 let res_dir = ephemeral_dir(path);
89 assert!(res_dir.is_ok());
90 let Ok(dir) = res_dir else { unreachable!() };
91 assert!(dir.path().exists());
92 let dir_path_str = format!("{}", dir.path().display());
93 assert_eq!(dir_path_str, path);
94
95 let path = "/tmp/ephemeral_dir_test";
97 let res_dir = ephemeral_dir_forced(path);
98 assert!(res_dir.is_ok());
99 {
100 let Ok(dir) = res_dir else { unreachable!() };
101 assert!(dir.path().exists());
102 let dir_path_str = format!("{}", dir.path().display());
103 assert_eq!(dir_path_str, path);
104 let dir_path = Path::new(&dir_path_str);
105 assert!(dir_path.exists());
106 }
107 let path_path = Path::new(path);
108 assert!(!path_path.exists());
109}
110
111#[test]
112fn test_asref_path() {
113 let path = "/tmp/ephemeral_test_dir";
114 let res_dir = ephemeral_dir(path).unwrap();
115
116 fn foo(p: impl AsRef<Path>) -> bool {
117 let p = p.as_ref();
118 p.exists()
119 }
120
121 assert!(foo(&res_dir));
122}