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
113 #[test]
114 fn test_files_are_included_with_cached_flag() {
115 let flags = GitFlags::default().with_cached(true);
116 assert_eq!(true, flags.is_allowed(&Status::INDEX_NEW));
117 assert_eq!(true, flags.is_allowed(&Status::INDEX_MODIFIED));
118 assert_eq!(true, flags.is_allowed(&Status::INDEX_RENAMED));
119 assert_eq!(true, flags.is_allowed(&Status::INDEX_DELETED));
120 assert_eq!(true, flags.is_allowed(&Status::INDEX_TYPECHANGE));
121 assert_eq!(false, flags.is_allowed(&Status::WT_NEW));
122 assert_eq!(true, flags.is_allowed(&Status::WT_MODIFIED));
123 assert_eq!(true, flags.is_allowed(&Status::WT_RENAMED));
124 assert_eq!(true, flags.is_allowed(&Status::WT_DELETED));
125 assert_eq!(true, flags.is_allowed(&Status::WT_TYPECHANGE));
126 assert_eq!(true, flags.is_allowed(&Status::WT_UNREADABLE));
127 assert_eq!(false, flags.is_allowed(&Status::IGNORED));
128 assert_eq!(true, flags.is_allowed(&Status::CONFLICTED));
129 }
130
131 #[test]
132 fn test_files_are_included_with_added_flag() {
133 let flags = GitFlags::default().with_added(true);
134 assert_eq!(true, flags.is_allowed(&Status::INDEX_NEW));
135 assert_eq!(false, flags.is_allowed(&Status::INDEX_MODIFIED));
136 assert_eq!(false, flags.is_allowed(&Status::INDEX_RENAMED));
137 assert_eq!(false, flags.is_allowed(&Status::INDEX_DELETED));
138 assert_eq!(false, flags.is_allowed(&Status::INDEX_TYPECHANGE));
139 assert_eq!(false, flags.is_allowed(&Status::WT_NEW));
140 assert_eq!(false, flags.is_allowed(&Status::WT_MODIFIED));
141 assert_eq!(false, flags.is_allowed(&Status::WT_RENAMED));
142 assert_eq!(false, flags.is_allowed(&Status::WT_DELETED));
143 assert_eq!(false, flags.is_allowed(&Status::WT_TYPECHANGE));
144 assert_eq!(false, flags.is_allowed(&Status::WT_UNREADABLE));
145 assert_eq!(false, flags.is_allowed(&Status::IGNORED));
146 assert_eq!(false, flags.is_allowed(&Status::CONFLICTED));
147 }
148
149 #[test]
150 fn test_files_are_included_with_modified_flag() {
151 let flags = GitFlags::default().with_modified(true);
152 assert_eq!(false, flags.is_allowed(&Status::INDEX_NEW));
153 assert_eq!(true, flags.is_allowed(&Status::INDEX_MODIFIED));
154 assert_eq!(false, flags.is_allowed(&Status::INDEX_RENAMED));
155 assert_eq!(false, flags.is_allowed(&Status::INDEX_DELETED));
156 assert_eq!(false, flags.is_allowed(&Status::INDEX_TYPECHANGE));
157 assert_eq!(false, flags.is_allowed(&Status::WT_NEW));
158 assert_eq!(true, flags.is_allowed(&Status::WT_MODIFIED));
159 assert_eq!(false, flags.is_allowed(&Status::WT_RENAMED));
160 assert_eq!(false, flags.is_allowed(&Status::WT_DELETED));
161 assert_eq!(false, flags.is_allowed(&Status::WT_TYPECHANGE));
162 assert_eq!(false, flags.is_allowed(&Status::WT_UNREADABLE));
163 assert_eq!(false, flags.is_allowed(&Status::IGNORED));
164 assert_eq!(false, flags.is_allowed(&Status::CONFLICTED));
165 }
166
167 #[test]
168 fn test_files_are_included_with_renamed_flag() {
169 let flags = GitFlags::default().with_renamed(true);
170 assert_eq!(false, flags.is_allowed(&Status::INDEX_NEW));
171 assert_eq!(false, flags.is_allowed(&Status::INDEX_MODIFIED));
172 assert_eq!(true, flags.is_allowed(&Status::INDEX_RENAMED));
173 assert_eq!(false, flags.is_allowed(&Status::INDEX_DELETED));
174 assert_eq!(false, flags.is_allowed(&Status::INDEX_TYPECHANGE));
175 assert_eq!(false, flags.is_allowed(&Status::WT_NEW));
176 assert_eq!(false, flags.is_allowed(&Status::WT_MODIFIED));
177 assert_eq!(true, flags.is_allowed(&Status::WT_RENAMED));
178 assert_eq!(false, flags.is_allowed(&Status::WT_DELETED));
179 assert_eq!(false, flags.is_allowed(&Status::WT_TYPECHANGE));
180 assert_eq!(false, flags.is_allowed(&Status::WT_UNREADABLE));
181 assert_eq!(false, flags.is_allowed(&Status::IGNORED));
182 assert_eq!(false, flags.is_allowed(&Status::CONFLICTED));
183 }
184
185 #[test]
186 fn test_files_are_included_with_untracked_flag() {
187 let flags = GitFlags::default().with_untracked(true);
188 assert_eq!(false, flags.is_allowed(&Status::INDEX_NEW));
189 assert_eq!(false, flags.is_allowed(&Status::INDEX_MODIFIED));
190 assert_eq!(false, flags.is_allowed(&Status::INDEX_RENAMED));
191 assert_eq!(false, flags.is_allowed(&Status::INDEX_DELETED));
192 assert_eq!(false, flags.is_allowed(&Status::INDEX_TYPECHANGE));
193 assert_eq!(true, flags.is_allowed(&Status::WT_NEW));
194 assert_eq!(false, flags.is_allowed(&Status::WT_MODIFIED));
195 assert_eq!(false, flags.is_allowed(&Status::WT_RENAMED));
196 assert_eq!(false, flags.is_allowed(&Status::WT_DELETED));
197 assert_eq!(false, flags.is_allowed(&Status::WT_TYPECHANGE));
198 assert_eq!(false, flags.is_allowed(&Status::WT_UNREADABLE));
199 assert_eq!(false, flags.is_allowed(&Status::IGNORED));
200 assert_eq!(false, flags.is_allowed(&Status::CONFLICTED));
201 }
202
203 #[test]
204 fn test_files_are_included_with_ignored_flag() {
205 let flags = GitFlags::default().with_ignored(true);
206 assert_eq!(false, flags.is_allowed(&Status::INDEX_NEW));
207 assert_eq!(false, flags.is_allowed(&Status::INDEX_MODIFIED));
208 assert_eq!(false, flags.is_allowed(&Status::INDEX_RENAMED));
209 assert_eq!(false, flags.is_allowed(&Status::INDEX_DELETED));
210 assert_eq!(false, flags.is_allowed(&Status::INDEX_TYPECHANGE));
211 assert_eq!(false, flags.is_allowed(&Status::WT_NEW));
212 assert_eq!(false, flags.is_allowed(&Status::WT_MODIFIED));
213 assert_eq!(false, flags.is_allowed(&Status::WT_RENAMED));
214 assert_eq!(false, flags.is_allowed(&Status::WT_DELETED));
215 assert_eq!(false, flags.is_allowed(&Status::WT_TYPECHANGE));
216 assert_eq!(false, flags.is_allowed(&Status::WT_UNREADABLE));
217 assert_eq!(true, flags.is_allowed(&Status::IGNORED));
218 assert_eq!(false, flags.is_allowed(&Status::CONFLICTED));
219 }
220
221 #[test]
222 fn test_files_are_included_with_multiple_flags() {
223 let flags = GitFlags::default().with_added(true).with_modified(true).with_renamed(true);
224 assert_eq!(true, flags.is_allowed(&Status::INDEX_NEW));
225 assert_eq!(true, flags.is_allowed(&Status::INDEX_MODIFIED));
226 assert_eq!(true, flags.is_allowed(&Status::INDEX_RENAMED));
227 assert_eq!(false, flags.is_allowed(&Status::INDEX_DELETED));
228 assert_eq!(false, flags.is_allowed(&Status::INDEX_TYPECHANGE));
229 assert_eq!(false, flags.is_allowed(&Status::WT_NEW));
230 assert_eq!(true, flags.is_allowed(&Status::WT_MODIFIED));
231 assert_eq!(true, flags.is_allowed(&Status::WT_RENAMED));
232 assert_eq!(false, flags.is_allowed(&Status::WT_DELETED));
233 assert_eq!(false, flags.is_allowed(&Status::WT_TYPECHANGE));
234 assert_eq!(false, flags.is_allowed(&Status::WT_UNREADABLE));
235 assert_eq!(false, flags.is_allowed(&Status::IGNORED));
236 assert_eq!(false, flags.is_allowed(&Status::CONFLICTED));
237 }
238}