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 for (path, hash) in &new.files {
29 if let Some(old_hash) = old.files.get(path) {
31 if old_hash != hash {
33 event!(Level::INFO, path = path.display().to_string(), "change");
34 diff.change.push(path.clone());
35 }
36 } else {
37 event!(Level::INFO, path = path.display().to_string(), "new");
39 diff.add.push(path.clone());
40 }
41 }
42
43 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}