Skip to main content

ex_cli/git/
flags.rs

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}