1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::report::{
IgnoreSourceEvidence, ScanCacheStats, ScanTermination, ScanWarning, SkippedEntry,
};
use std::path::{Path, PathBuf};
/// Controls whether a content visit retains selected-file evidence internally.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContentVisitMode {
/// Retain compact selected-file evidence and compute a deterministic
/// revision.
Revision,
/// Emit bytes and counters without retaining selected-file evidence or
/// computing a revision.
Streaming,
}
/// Controls delivery from [`crate::Scanner::visit_content`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContentVisitControl {
/// Continue delivering the current file.
Continue,
/// Stop delivering chunks for this file while allowing required scanner
/// evidence work to finish.
SkipFile,
/// Cooperatively stop every content worker.
Quit,
}
/// Stable identity and discovery evidence for one selected file.
#[derive(Debug, Clone, Copy)]
pub struct ContentFile<'a> {
/// Root insertion index. A single-root [`crate::Scanner`] always uses zero.
pub root_index: usize,
/// Monotonic work sequence within this visit. Sort by `root_index` and
/// `relative` when results must be deterministic across runs.
pub sequence: u64,
pub root: &'a Path,
pub absolute: &'a Path,
pub relative: &'a str,
pub bytes: u64,
}
/// Result of verifying the file around its single content read.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContentFileStatus {
Selected,
Binary,
Changed,
}
/// Events emitted from one bounded content worker.
#[derive(Debug)]
pub enum ContentVisitEvent<'a> {
/// The selected file was opened and its discovery evidence was verified.
FileStart {
worker_index: usize,
file: ContentFile<'a>,
},
/// A borrowed chunk from the scanner's one content read.
Chunk {
worker_index: usize,
file: ContentFile<'a>,
offset: u64,
bytes: &'a [u8],
},
/// The file read and post-read verification finished.
FileEnd {
worker_index: usize,
file: ContentFile<'a>,
status: ContentFileStatus,
bytes_read: u64,
content_hash: Option<&'a str>,
consumer_skipped: bool,
},
}
/// Summary of a parallel, one-pass selected-content visit.
#[derive(Debug)]
pub struct ContentVisitReport {
pub mode: ContentVisitMode,
pub root: PathBuf,
/// Candidates selected by traversal and ignore rules before content checks.
pub discovered: u64,
/// Files that completed content checks and remain selected.
pub completed: u64,
pub opened: u64,
pub chunks: u64,
pub bytes_read: u64,
pub bytes_emitted: u64,
pub consumer_skipped: u64,
pub stopped: bool,
pub skipped: Vec<SkippedEntry>,
pub warnings: Vec<ScanWarning>,
pub ignore_sources: Vec<IgnoreSourceEvidence>,
pub revision: String,
pub complete: bool,
pub termination: Option<ScanTermination>,
pub portable: bool,
pub cache: ScanCacheStats,
}
/// Ordered summaries from a multi-root content visit.
#[derive(Debug)]
pub struct MultiContentVisitReport {
/// Reports remain in the same order as roots were added.
pub reports: Vec<ContentVisitReport>,
}
impl MultiContentVisitReport {
#[must_use]
pub const fn len(&self) -> usize {
self.reports.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.reports.is_empty()
}
}
/// Content and removals produced by a safe file-only watcher plan.
#[derive(Debug)]
pub struct ChangedContentVisitReport {
/// Evidence for the changed files that still exist and remain selected.
///
/// Its revision describes this changed-file subset, not the complete
/// repository manifest.
pub content: ContentVisitReport,
/// Stable normalized paths that disappeared from the repository.
pub removed: Vec<String>,
}
/// Result of attempting a traversal-free watcher content visit.
#[derive(Debug)]
pub enum ChangedContentVisitOutcome {
/// Only changed file paths were matched, opened, and visited.
Visited(Box<ChangedContentVisitReport>),
/// The plan can affect directory structure or selection and therefore
/// requires the caller to perform a complete scan.
FullRescanRequired,
}