weavatrix_worktree/report/
operation.rs1use core::fmt;
2
3use crate::hash::Sha256Hash;
4
5#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
7pub enum OperationKind {
8 Modify,
9 Create,
10 Delete,
11 Rename,
12}
13
14impl OperationKind {
15 #[must_use]
16 pub const fn as_str(self) -> &'static str {
17 match self {
18 Self::Modify => "MODIFY",
19 Self::Create => "CREATE",
20 Self::Delete => "DELETE",
21 Self::Rename => "RENAME",
22 }
23 }
24}
25
26impl fmt::Display for OperationKind {
27 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28 formatter.write_str(self.as_str())
29 }
30}
31
32#[derive(Clone, Debug, Eq, PartialEq)]
34pub struct OperationChange {
35 kind: OperationKind,
36 source_path: Option<String>,
37 destination_path: Option<String>,
38 old_sha256: Option<Sha256Hash>,
39 new_sha256: Option<Sha256Hash>,
40 bytes_before: u64,
41 bytes_after: u64,
42 edits_applied: usize,
43}
44
45impl OperationChange {
46 #[allow(clippy::too_many_arguments)]
47 pub(crate) fn new(
48 kind: OperationKind,
49 source_path: Option<String>,
50 destination_path: Option<String>,
51 old_sha256: Option<Sha256Hash>,
52 new_sha256: Option<Sha256Hash>,
53 bytes_before: u64,
54 bytes_after: u64,
55 edits_applied: usize,
56 ) -> Self {
57 Self {
58 kind,
59 source_path,
60 destination_path,
61 old_sha256,
62 new_sha256,
63 bytes_before,
64 bytes_after,
65 edits_applied,
66 }
67 }
68
69 #[must_use]
70 pub const fn kind(&self) -> OperationKind {
71 self.kind
72 }
73
74 #[must_use]
75 pub fn source_path(&self) -> Option<&str> {
76 self.source_path.as_deref()
77 }
78
79 #[must_use]
80 pub fn destination_path(&self) -> Option<&str> {
81 self.destination_path.as_deref()
82 }
83
84 #[must_use]
85 pub const fn old_sha256(&self) -> Option<Sha256Hash> {
86 self.old_sha256
87 }
88
89 #[must_use]
90 pub const fn new_sha256(&self) -> Option<Sha256Hash> {
91 self.new_sha256
92 }
93
94 #[must_use]
95 pub const fn bytes_before(&self) -> u64 {
96 self.bytes_before
97 }
98
99 #[must_use]
100 pub const fn bytes_after(&self) -> u64 {
101 self.bytes_after
102 }
103
104 #[must_use]
105 pub const fn edits_applied(&self) -> usize {
106 self.edits_applied
107 }
108}
109
110#[derive(Clone, Debug, Eq, PartialEq)]
112pub struct WorktreeDryRunReport {
113 operation: String,
114 files: Vec<OperationChange>,
115 touched_paths: usize,
116}
117
118impl WorktreeDryRunReport {
119 pub(crate) fn new(
120 operation: impl Into<String>,
121 files: Vec<OperationChange>,
122 touched_paths: usize,
123 ) -> Self {
124 Self {
125 operation: operation.into(),
126 files,
127 touched_paths,
128 }
129 }
130
131 #[must_use]
132 pub fn operation(&self) -> &str {
133 &self.operation
134 }
135
136 #[must_use]
137 pub fn files(&self) -> &[OperationChange] {
138 &self.files
139 }
140
141 #[must_use]
142 pub const fn touched_paths(&self) -> usize {
143 self.touched_paths
144 }
145
146 #[must_use]
147 pub fn total_edits(&self) -> usize {
148 self.files
149 .iter()
150 .fold(0, |total, file| total.saturating_add(file.edits_applied()))
151 }
152}
153
154#[derive(Clone, Debug, Eq, PartialEq)]
156pub struct WorktreeApplyReport {
157 transaction_id: String,
158 operation: String,
159 files: Vec<OperationChange>,
160 touched_paths: usize,
161}
162
163impl WorktreeApplyReport {
164 pub(crate) fn new(
165 transaction_id: impl Into<String>,
166 operation: impl Into<String>,
167 files: Vec<OperationChange>,
168 touched_paths: usize,
169 ) -> Self {
170 Self {
171 transaction_id: transaction_id.into(),
172 operation: operation.into(),
173 files,
174 touched_paths,
175 }
176 }
177
178 #[must_use]
179 pub fn transaction_id(&self) -> &str {
180 &self.transaction_id
181 }
182
183 #[must_use]
184 pub fn operation(&self) -> &str {
185 &self.operation
186 }
187
188 #[must_use]
189 pub fn files(&self) -> &[OperationChange] {
190 &self.files
191 }
192
193 #[must_use]
194 pub const fn touched_paths(&self) -> usize {
195 self.touched_paths
196 }
197}