comtrya_lib/atoms/directory/
remove.rs

1use std::path::PathBuf;
2
3use tracing::error;
4
5use crate::atoms::{Atom, Outcome};
6
7pub struct Remove {
8    pub target: PathBuf,
9}
10
11impl std::fmt::Display for Remove {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        write!(
14            f,
15            "The directory {} needs to be removed",
16            self.target.display(),
17        )
18    }
19}
20
21impl Atom for Remove {
22    fn plan(&self) -> anyhow::Result<Outcome> {
23        let path_to_dir = PathBuf::from(&self.target);
24
25        if !path_to_dir.is_dir() {
26            error!(
27                "Cannot plan: target isn`t a directory: {}",
28                self.target.display()
29            );
30            return Ok(Outcome {
31                side_effects: vec![],
32                should_run: false,
33            });
34        }
35
36        let is_empty = path_to_dir.read_dir()?.next().is_none();
37
38        if !is_empty {
39            error!(
40                "Cannot plan: directory {} is not empty",
41                self.target.display()
42            );
43
44            return Ok(Outcome {
45                side_effects: vec![],
46                should_run: false,
47            });
48        }
49
50        Ok(Outcome {
51            side_effects: vec![],
52            should_run: self.target.exists(),
53        })
54    }
55
56    fn execute(&mut self) -> anyhow::Result<()> {
57        std::fs::remove_dir(&self.target)?;
58        Ok(())
59    }
60}
61
62#[cfg(test)]
63mod tests {
64
65    use std::{fs::File, io::Write};
66
67    use super::*;
68    use pretty_assertions::assert_eq;
69    use tempfile::tempdir;
70
71    #[test]
72    fn it_can_plan() {
73        let temp = tempdir().unwrap().into_path();
74        let atom = Remove {
75            target: temp.clone(),
76        };
77        assert_eq!(true, atom.plan().unwrap().should_run);
78
79        let file_path = temp.join("my-temporary-note.txt");
80        let mut file = File::create(&file_path).unwrap();
81        writeln!(file, "Brian was here. Briefly.").unwrap();
82
83        // Should not run when dir is not empty
84        assert_eq!(false, atom.plan().unwrap().should_run);
85
86        // Should not run if path is not a dir
87        let atom = Remove {
88            target: file_path.clone(),
89        };
90
91        assert_eq!(false, atom.plan().unwrap().should_run)
92    }
93
94    #[test]
95    fn it_can_execute() {
96        let temp_dir = match tempfile::tempdir() {
97            std::result::Result::Ok(dir) => dir,
98            std::result::Result::Err(_) => {
99                assert_eq!(false, true);
100                return;
101            }
102        };
103
104        let path = temp_dir.path();
105
106        assert_eq!(true, path.exists());
107
108        let mut atom = Remove {
109            target: temp_dir.path().to_path_buf(),
110        };
111
112        // Deletes dir
113        assert_eq!(true, atom.execute().is_ok());
114        // Dir is deleted and dont exists
115        assert_eq!(false, temp_dir.path().exists())
116    }
117}