comtrya_lib/atoms/file/
contents.rs

1use crate::atoms::Outcome;
2
3use super::super::Atom;
4use super::FileAtom;
5use std::path::PathBuf;
6use tracing::error;
7
8pub struct SetContents {
9    pub path: PathBuf,
10    pub contents: Vec<u8>,
11}
12
13impl FileAtom for SetContents {
14    fn get_path(&self) -> &PathBuf {
15        &self.path
16    }
17}
18
19impl std::fmt::Display for SetContents {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        write!(
22            f,
23            "The file {} contents need to be set",
24            self.path.display(),
25        )
26    }
27}
28
29impl Atom for SetContents {
30    fn plan(&self) -> anyhow::Result<Outcome> {
31        // If the file doesn't exist, assume it's because
32        // another atom is going to provide it.
33        if !self.path.exists() {
34            return Ok(Outcome {
35                side_effects: vec![],
36                should_run: true,
37            });
38        }
39
40        let contents = match std::fs::read(&self.path) {
41            Ok(contents) => contents,
42            Err(error) => {
43                error!(
44                    "Failed to read contents of {} for diff because {:?}. Skipping",
45                    error, self.path
46                );
47
48                return Ok(Outcome {
49                    side_effects: vec![],
50                    should_run: false,
51                });
52            }
53        };
54
55        Ok(Outcome {
56            side_effects: vec![],
57            should_run: !contents.eq(&self.contents),
58        })
59    }
60
61    fn execute(&mut self) -> anyhow::Result<()> {
62        std::fs::write(&self.path, &self.contents)?;
63
64        Ok(())
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use pretty_assertions::assert_eq;
72
73    #[test]
74    fn it_can() {
75        let file = match tempfile::NamedTempFile::new() {
76            std::result::Result::Ok(file) => file,
77            std::result::Result::Err(_) => {
78                assert_eq!(false, true);
79                return;
80            }
81        };
82
83        let file_contents = SetContents {
84            path: file.path().to_path_buf(),
85            contents: String::from("").into_bytes(),
86        };
87
88        assert_eq!(false, file_contents.plan().unwrap().should_run);
89
90        let mut file_contents = SetContents {
91            path: file.path().to_path_buf(),
92            contents: String::from("Hello, world!").into_bytes(),
93        };
94
95        assert_eq!(true, file_contents.plan().unwrap().should_run);
96        assert_eq!(true, file_contents.execute().is_ok());
97        assert_eq!(false, file_contents.plan().unwrap().should_run);
98    }
99}