okc/scanner/changes.rs
1//! Change detection between file system scans.
2//!
3//! [`ChangeDetector`] compares current and previous file listings to identify
4//! added, modified, deleted, and unchanged files for incremental indexing.
5
6use std::collections::HashSet;
7
8use crate::model::document::FileRecord;
9
10/// Result of change detection between two scans.
11#[derive(Debug)]
12pub struct FileChanges {
13 /// New files not present in previous scan.
14 pub added: Vec<FileRecord>,
15 /// Files with changed size or modification time.
16 pub modified: Vec<FileRecord>,
17 /// Files present in previous scan but not current.
18 pub deleted: Vec<String>,
19 /// Files unchanged since previous scan (paths only).
20 pub unchanged: Vec<String>,
21}
22
23/// Detects file system changes between scans.
24///
25/// Compares current and previous file records by path, using size and
26/// modification time to detect modifications.
27pub struct ChangeDetector;
28
29impl ChangeDetector {
30 /// Detect changes between current and previous file listings.
31 ///
32 /// Files are matched by path. A file is considered modified if either
33 /// its size or modification timestamp differs from the previous scan.
34 pub fn detect(current: &[FileRecord], previous: &[FileRecord]) -> FileChanges {
35 let prev_map: std::collections::HashMap<&str, &FileRecord> =
36 previous.iter().map(|f| (f.path.as_str(), f)).collect();
37
38 let current_paths: HashSet<&str> = current.iter().map(|f| f.path.as_str()).collect();
39
40 let mut added = Vec::new();
41 let mut modified = Vec::new();
42 let mut unchanged = Vec::new();
43
44 for file in current {
45 match prev_map.get(file.path.as_str()) {
46 Some(prev) => {
47 if prev.modified_at == file.modified_at && prev.size == file.size {
48 unchanged.push(file.path.clone());
49 } else {
50 modified.push(file.clone());
51 }
52 }
53 None => {
54 added.push(file.clone());
55 }
56 }
57 }
58
59 let deleted: Vec<String> = previous
60 .iter()
61 .map(|f| f.path.clone())
62 .filter(|p| !current_paths.contains(p.as_str()))
63 .collect();
64
65 FileChanges {
66 added,
67 modified,
68 deleted,
69 unchanged,
70 }
71 }
72}