1use std::path::PathBuf;
7
8use cadvm_store::ObjectId;
9use serde::Serialize;
10
11use crate::model::{FileEntry, Manifest};
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
15pub struct FileDiff {
16 pub path: PathBuf,
17 pub size_bytes: (u64, u64),
18 pub raw_hash: (ObjectId, ObjectId),
19 pub line_count: (Option<u64>, Option<u64>),
20 pub schema: (Option<String>, Option<String>),
21 pub entity_count: (Option<u64>, Option<u64>),
22 pub triangles: (Option<u64>, Option<u64>),
24 pub vertices: (Option<u64>, Option<u64>),
26}
27
28impl FileDiff {
29 fn between(a: &FileEntry, b: &FileEntry) -> Self {
30 let schema = (
31 a.step_metadata.as_ref().and_then(|m| m.file_schema.clone()),
32 b.step_metadata.as_ref().and_then(|m| m.file_schema.clone()),
33 );
34 let entity_count = (
35 a.step_metadata.as_ref().and_then(|m| m.entity_count),
36 b.step_metadata.as_ref().and_then(|m| m.entity_count),
37 );
38 let triangles = (
39 a.mesh_metadata.as_ref().and_then(|m| m.triangles),
40 b.mesh_metadata.as_ref().and_then(|m| m.triangles),
41 );
42 let vertices = (
43 a.mesh_metadata.as_ref().and_then(|m| m.vertices),
44 b.mesh_metadata.as_ref().and_then(|m| m.vertices),
45 );
46 FileDiff {
47 path: a.path.clone(),
48 size_bytes: (a.size_bytes, b.size_bytes),
49 raw_hash: (a.raw_hash.clone(), b.raw_hash.clone()),
50 line_count: (a.line_count, b.line_count),
51 schema,
52 entity_count,
53 triangles,
54 vertices,
55 }
56 }
57}
58
59#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
61pub struct ManifestDiff {
62 pub added: Vec<PathBuf>,
63 pub removed: Vec<PathBuf>,
64 pub modified: Vec<FileDiff>,
65}
66
67impl ManifestDiff {
68 pub fn is_empty(&self) -> bool {
70 self.added.is_empty() && self.removed.is_empty() && self.modified.is_empty()
71 }
72}
73
74pub fn diff_manifests(a: &Manifest, b: &Manifest) -> ManifestDiff {
76 let mut diff = ManifestDiff::default();
77
78 for (path, entry_b) in &b.files {
79 match a.files.get(path) {
80 None => diff.added.push(path.clone()),
81 Some(entry_a) if entry_a.raw_hash != entry_b.raw_hash => {
82 diff.modified.push(FileDiff::between(entry_a, entry_b));
83 }
84 Some(_) => {}
85 }
86 }
87
88 for path in a.files.keys() {
89 if !b.files.contains_key(path) {
90 diff.removed.push(path.clone());
91 }
92 }
93
94 diff.added.sort();
95 diff.removed.sort();
96 diff.modified.sort_by(|x, y| x.path.cmp(&y.path));
97 diff
98}