1use crate::error::{MyError, MyResult};
2use git2::Status;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq)]
5pub struct GitFlags {
6 pub everything: bool,
7 pub cached: bool,
8 pub added: bool,
9 pub modified: bool,
10 pub renamed: bool,
11 pub untracked: bool,
12 pub ignored: bool,
13}
14
15impl GitFlags {
16 pub fn from_str(value: &str) -> MyResult<Self> {
17 let mut flags = Self::default();
18 for ch in value.chars() {
19 match ch {
20 'x' => flags.everything = true,
21 'c' => flags.cached = true,
22 'a' => flags.added = true,
23 'm' => flags.modified = true,
24 'r' => flags.renamed = true,
25 'u' => flags.untracked = true,
26 'i' => flags.ignored = true,
27 _ => return Err(MyError::create_clap("git", ch)),
28 }
29 }
30 Ok(flags)
31 }
32
33 pub fn with_everything(mut self, everything: bool) -> Self {
34 self.everything = everything;
35 self
36 }
37
38 pub fn with_cached(mut self, cached: bool) -> Self {
39 self.cached = cached;
40 self
41 }
42
43 pub fn with_added(mut self, added: bool) -> Self {
44 self.added = added;
45 self
46 }
47
48 pub fn with_modified(mut self, modified: bool) -> Self {
49 self.modified = modified;
50 self
51 }
52
53 pub fn with_renamed(mut self, renamed: bool) -> Self {
54 self.renamed = renamed;
55 self
56 }
57
58 pub fn with_untracked(mut self, untracked: bool) -> Self {
59 self.untracked = untracked;
60 self
61 }
62
63 pub fn with_ignored(mut self, ignored: bool) -> Self {
64 self.ignored = ignored;
65 self
66 }
67
68 pub fn test_allowed(&self, status: Status) -> Option<Self> {
69 if self.is_allowed(status) {
70 let flags = Self::default()
71 .with_added(status.is_index_new())
72 .with_modified(status.is_index_modified() || status.is_wt_modified())
73 .with_renamed(status.is_index_renamed() || status.is_wt_renamed())
74 .with_untracked(status.is_wt_new())
75 .with_ignored(status.is_ignored());
76 Some(flags)
77 } else {
78 None
79 }
80 }
81
82 fn is_allowed(&self, status: Status) -> bool {
83 if self.everything {
84 return true;
85 }
86 if self.cached && !status.is_ignored() && !status.is_wt_new() {
87 return true;
88 }
89 if self.added && status.is_index_new() {
90 return true;
91 }
92 if self.modified && (status.is_index_modified() || status.is_wt_modified()) {
93 return true;
94 }
95 if self.renamed && (status.is_index_renamed() || status.is_wt_renamed()) {
96 return true;
97 }
98 if self.untracked && status.is_wt_new() {
99 return true;
100 }
101 if self.ignored && status.is_ignored() {
102 return true;
103 }
104 false
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use crate::git::flags::GitFlags;
111 use git2::Status;
112 use googletest::prelude::*;
113
114 #[gtest]
115 fn test_files_are_included_with_cached_flag() {
116 let flags = GitFlags::default().with_cached(true);
117 expect_true!(flags.is_allowed(Status::INDEX_NEW));
118 expect_true!(flags.is_allowed(Status::INDEX_MODIFIED));
119 expect_true!(flags.is_allowed(Status::INDEX_RENAMED));
120 expect_true!(flags.is_allowed(Status::INDEX_DELETED));
121 expect_true!(flags.is_allowed(Status::INDEX_TYPECHANGE));
122 expect_false!(flags.is_allowed(Status::WT_NEW));
123 expect_true!(flags.is_allowed(Status::WT_MODIFIED));
124 expect_true!(flags.is_allowed(Status::WT_RENAMED));
125 expect_true!(flags.is_allowed(Status::WT_DELETED));
126 expect_true!(flags.is_allowed(Status::WT_TYPECHANGE));
127 expect_true!(flags.is_allowed(Status::WT_UNREADABLE));
128 expect_false!(flags.is_allowed(Status::IGNORED));
129 expect_true!(flags.is_allowed(Status::CONFLICTED));
130 }
131
132 #[gtest]
133 fn test_files_are_included_with_added_flag() {
134 let flags = GitFlags::default().with_added(true);
135 expect_true!(flags.is_allowed(Status::INDEX_NEW));
136 expect_false!(flags.is_allowed(Status::INDEX_MODIFIED));
137 expect_false!(flags.is_allowed(Status::INDEX_RENAMED));
138 expect_false!(flags.is_allowed(Status::INDEX_DELETED));
139 expect_false!(flags.is_allowed(Status::INDEX_TYPECHANGE));
140 expect_false!(flags.is_allowed(Status::WT_NEW));
141 expect_false!(flags.is_allowed(Status::WT_MODIFIED));
142 expect_false!(flags.is_allowed(Status::WT_RENAMED));
143 expect_false!(flags.is_allowed(Status::WT_DELETED));
144 expect_false!(flags.is_allowed(Status::WT_TYPECHANGE));
145 expect_false!(flags.is_allowed(Status::WT_UNREADABLE));
146 expect_false!(flags.is_allowed(Status::IGNORED));
147 expect_false!(flags.is_allowed(Status::CONFLICTED));
148 }
149
150 #[gtest]
151 fn test_files_are_included_with_modified_flag() {
152 let flags = GitFlags::default().with_modified(true);
153 expect_false!(flags.is_allowed(Status::INDEX_NEW));
154 expect_true!(flags.is_allowed(Status::INDEX_MODIFIED));
155 expect_false!(flags.is_allowed(Status::INDEX_RENAMED));
156 expect_false!(flags.is_allowed(Status::INDEX_DELETED));
157 expect_false!(flags.is_allowed(Status::INDEX_TYPECHANGE));
158 expect_false!(flags.is_allowed(Status::WT_NEW));
159 expect_true!(flags.is_allowed(Status::WT_MODIFIED));
160 expect_false!(flags.is_allowed(Status::WT_RENAMED));
161 expect_false!(flags.is_allowed(Status::WT_DELETED));
162 expect_false!(flags.is_allowed(Status::WT_TYPECHANGE));
163 expect_false!(flags.is_allowed(Status::WT_UNREADABLE));
164 expect_false!(flags.is_allowed(Status::IGNORED));
165 expect_false!(flags.is_allowed(Status::CONFLICTED));
166 }
167
168 #[gtest]
169 fn test_files_are_included_with_renamed_flag() {
170 let flags = GitFlags::default().with_renamed(true);
171 expect_false!(flags.is_allowed(Status::INDEX_NEW));
172 expect_false!(flags.is_allowed(Status::INDEX_MODIFIED));
173 expect_true!(flags.is_allowed(Status::INDEX_RENAMED));
174 expect_false!(flags.is_allowed(Status::INDEX_DELETED));
175 expect_false!(flags.is_allowed(Status::INDEX_TYPECHANGE));
176 expect_false!(flags.is_allowed(Status::WT_NEW));
177 expect_false!(flags.is_allowed(Status::WT_MODIFIED));
178 expect_true!(flags.is_allowed(Status::WT_RENAMED));
179 expect_false!(flags.is_allowed(Status::WT_DELETED));
180 expect_false!(flags.is_allowed(Status::WT_TYPECHANGE));
181 expect_false!(flags.is_allowed(Status::WT_UNREADABLE));
182 expect_false!(flags.is_allowed(Status::IGNORED));
183 expect_false!(flags.is_allowed(Status::CONFLICTED));
184 }
185
186 #[gtest]
187 fn test_files_are_included_with_untracked_flag() {
188 let flags = GitFlags::default().with_untracked(true);
189 expect_false!(flags.is_allowed(Status::INDEX_NEW));
190 expect_false!(flags.is_allowed(Status::INDEX_MODIFIED));
191 expect_false!(flags.is_allowed(Status::INDEX_RENAMED));
192 expect_false!(flags.is_allowed(Status::INDEX_DELETED));
193 expect_false!(flags.is_allowed(Status::INDEX_TYPECHANGE));
194 expect_true!(flags.is_allowed(Status::WT_NEW));
195 expect_false!(flags.is_allowed(Status::WT_MODIFIED));
196 expect_false!(flags.is_allowed(Status::WT_RENAMED));
197 expect_false!(flags.is_allowed(Status::WT_DELETED));
198 expect_false!(flags.is_allowed(Status::WT_TYPECHANGE));
199 expect_false!(flags.is_allowed(Status::WT_UNREADABLE));
200 expect_false!(flags.is_allowed(Status::IGNORED));
201 expect_false!(flags.is_allowed(Status::CONFLICTED));
202 }
203
204 #[gtest]
205 fn test_files_are_included_with_ignored_flag() {
206 let flags = GitFlags::default().with_ignored(true);
207 expect_false!(flags.is_allowed(Status::INDEX_NEW));
208 expect_false!(flags.is_allowed(Status::INDEX_MODIFIED));
209 expect_false!(flags.is_allowed(Status::INDEX_RENAMED));
210 expect_false!(flags.is_allowed(Status::INDEX_DELETED));
211 expect_false!(flags.is_allowed(Status::INDEX_TYPECHANGE));
212 expect_false!(flags.is_allowed(Status::WT_NEW));
213 expect_false!(flags.is_allowed(Status::WT_MODIFIED));
214 expect_false!(flags.is_allowed(Status::WT_RENAMED));
215 expect_false!(flags.is_allowed(Status::WT_DELETED));
216 expect_false!(flags.is_allowed(Status::WT_TYPECHANGE));
217 expect_false!(flags.is_allowed(Status::WT_UNREADABLE));
218 expect_true!(flags.is_allowed(Status::IGNORED));
219 expect_false!(flags.is_allowed(Status::CONFLICTED));
220 }
221
222 #[gtest]
223 fn test_files_are_included_with_multiple_flags() {
224 let flags = GitFlags::default().with_added(true).with_modified(true).with_renamed(true);
225 expect_true!(flags.is_allowed(Status::INDEX_NEW));
226 expect_true!(flags.is_allowed(Status::INDEX_MODIFIED));
227 expect_true!(flags.is_allowed(Status::INDEX_RENAMED));
228 expect_false!(flags.is_allowed(Status::INDEX_DELETED));
229 expect_false!(flags.is_allowed(Status::INDEX_TYPECHANGE));
230 expect_false!(flags.is_allowed(Status::WT_NEW));
231 expect_true!(flags.is_allowed(Status::WT_MODIFIED));
232 expect_true!(flags.is_allowed(Status::WT_RENAMED));
233 expect_false!(flags.is_allowed(Status::WT_DELETED));
234 expect_false!(flags.is_allowed(Status::WT_TYPECHANGE));
235 expect_false!(flags.is_allowed(Status::WT_UNREADABLE));
236 expect_false!(flags.is_allowed(Status::IGNORED));
237 expect_false!(flags.is_allowed(Status::CONFLICTED));
238 }
239}