eto/
diff.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4use tracing::{event, Level};
5
6use crate::state::State;
7
8#[derive(Serialize, Deserialize, Default, Debug, Clone)]
9pub struct Diff {
10    pub old_version: String,
11    pub new_version: String,
12    pub add: Vec<PathBuf>,
13    pub change: Vec<PathBuf>,
14    pub delete: Vec<PathBuf>,
15}
16
17impl Diff {
18    pub fn from_states(old: &State, new: &State) -> Self {
19        event!(Level::INFO, "diffing states");
20
21        let mut diff = Self {
22            old_version: old.version.clone(),
23            new_version: new.version.clone(),
24            ..Self::default()
25        };
26
27        // Go through all files in new to check them against the old state
28        for (path, hash) in &new.files {
29            // Check if they exist in the old state
30            if let Some(old_hash) = old.files.get(path) {
31                // It does exist, check if it changed
32                if old_hash != hash {
33                    event!(Level::INFO, path = path.display().to_string(), "change");
34                    diff.change.push(path.clone());
35                }
36            } else {
37                // It doesn't exist, so it's new
38                event!(Level::INFO, path = path.display().to_string(), "new");
39                diff.add.push(path.clone());
40            }
41        }
42
43        // Go through all old files, and check if any were deleted in the new state
44        for path in old.files.keys() {
45            if !new.files.contains_key(path) {
46                event!(Level::INFO, path = path.display().to_string(), "delete");
47                diff.delete.push(path.clone());
48            }
49        }
50
51        diff
52    }
53}