1use clap::Parser;
2
3#[derive(Parser)]
4#[command(author, version, about)]
5pub struct Args {
6 #[arg(
7 short = 'r',
8 long = "repo-path",
9 help = "Path or URI to the repository"
10 )]
11 pub repo_path: Option<String>,
12
13 #[arg(long, help = "Email associated with the commits")]
14 pub email: Option<String>,
15
16 #[arg(short = 'n', long = "name", help = "Name associated with the commits")]
17 pub name: Option<String>,
18
19 #[arg(
20 short = 'b',
21 long = "begin",
22 help = "Start date for the commits in YYYY-MM-DD format"
23 )]
24 pub start: Option<String>,
25
26 #[arg(
27 short = 'e',
28 long = "end",
29 help = "End date for the commits in YYYY-MM-DD format"
30 )]
31 pub end: Option<String>,
32
33 #[arg(
34 short = 's',
35 long = "show-history",
36 help = "Show updated commit history after rewriting"
37 )]
38 pub show_history: bool,
39
40 #[arg(
41 short = 'p',
42 long = "pick-specific-commits",
43 help = "Pick specific commits to rewrite. Provide a comma-separated list of commit hashes."
44 )]
45 pub pic_specific_commits: bool,
46
47 #[arg(
48 short = 'x',
49 long = "range",
50 help = "Edit a range of commits (e.g., --range to interactively select range)"
51 )]
52 pub range: bool,
53}
54
55impl Args {
56 pub fn is_help_request(&self) -> bool {
57 !self.show_history
58 && !self.pic_specific_commits
59 && !self.range
60 && self.email.is_none()
61 && self.name.is_none()
62 && self.start.is_none()
63 && self.end.is_none()
64 }
65
66 pub fn ensure_all_args_present(&mut self) {
67 use crate::utils::prompt::prompt_for_missing_arg;
68
69 if self.repo_path.is_none() {
70 self.repo_path = Some(String::from("./"));
71 }
72
73 if self.show_history || self.pic_specific_commits {
75 return;
76 }
77
78 if self.range {
80 return;
81 }
82
83 if self.email.is_none() {
84 self.email = Some(prompt_for_missing_arg("email"));
85 }
86
87 if self.name.is_none() {
88 self.name = Some(prompt_for_missing_arg("name"));
89 }
90
91 if self.start.is_none() {
92 self.start = Some(prompt_for_missing_arg("start date (YYYY-MM-DD HH:MM:SS)"));
93 }
94
95 if self.end.is_none() {
96 self.end = Some(prompt_for_missing_arg("end date (YYYY-MM-DD HH:MM:SS)"));
97 }
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn test_args_default_values() {
107 let args = Args {
108 repo_path: None,
109 email: None,
110 name: None,
111 start: None,
112 end: None,
113 show_history: false,
114 pic_specific_commits: false,
115 range: false,
116 };
117
118 assert_eq!(args.repo_path, None);
119 assert_eq!(args.email, None);
120 assert_eq!(args.name, None);
121 assert_eq!(args.start, None);
122 assert_eq!(args.end, None);
123 assert!(!args.show_history);
124 assert!(!args.pic_specific_commits);
125 assert!(!args.range);
126 }
127
128 #[test]
129 fn test_args_with_show_history() {
130 let args = Args {
131 repo_path: Some("/test/repo".to_string()),
132 email: None,
133 name: None,
134 start: None,
135 end: None,
136 show_history: true,
137 pic_specific_commits: false,
138 range: false,
139 };
140
141 assert_eq!(args.repo_path, Some("/test/repo".to_string()));
142 assert!(args.show_history);
143 assert!(!args.pic_specific_commits);
144 }
145
146 #[test]
147 fn test_args_with_pick_specific_commits() {
148 let args = Args {
149 repo_path: Some("/test/repo".to_string()),
150 email: None,
151 name: None,
152 start: None,
153 end: None,
154 show_history: false,
155 pic_specific_commits: true,
156 range: false,
157 };
158
159 assert_eq!(args.repo_path, Some("/test/repo".to_string()));
160 assert!(!args.show_history);
161 assert!(args.pic_specific_commits);
162 }
163
164 #[test]
165 fn test_args_full_rewrite() {
166 let args = Args {
167 repo_path: Some("/test/repo".to_string()),
168 email: Some("test@example.com".to_string()),
169 name: Some("Test User".to_string()),
170 start: Some("2023-01-01 00:00:00".to_string()),
171 end: Some("2023-01-02 00:00:00".to_string()),
172 show_history: false,
173 pic_specific_commits: false,
174 range: false,
175 };
176
177 assert_eq!(args.repo_path, Some("/test/repo".to_string()));
178 assert_eq!(args.email, Some("test@example.com".to_string()));
179 assert_eq!(args.name, Some("Test User".to_string()));
180 assert_eq!(args.start, Some("2023-01-01 00:00:00".to_string()));
181 assert_eq!(args.end, Some("2023-01-02 00:00:00".to_string()));
182 }
183
184 #[test]
185 fn test_args_with_range() {
186 let args = Args {
187 repo_path: Some("/test/repo".to_string()),
188 email: None,
189 name: None,
190 start: None,
191 end: None,
192 show_history: false,
193 pic_specific_commits: false,
194 range: true,
195 };
196
197 assert_eq!(args.repo_path, Some("/test/repo".to_string()));
198 assert!(!args.show_history);
199 assert!(!args.pic_specific_commits);
200 assert!(args.range);
201 }
202
203 #[test]
204 fn test_is_help_request() {
205 let args = Args {
207 repo_path: None,
208 email: None,
209 name: None,
210 start: None,
211 end: None,
212 show_history: false,
213 pic_specific_commits: false,
214 range: false,
215 };
216 assert!(args.is_help_request());
217
218 let args = Args {
220 repo_path: Some("/test/repo".to_string()),
221 email: None,
222 name: None,
223 start: None,
224 end: None,
225 show_history: false,
226 pic_specific_commits: false,
227 range: false,
228 };
229 assert!(args.is_help_request());
230
231 let args = Args {
233 repo_path: None,
234 email: None,
235 name: None,
236 start: None,
237 end: None,
238 show_history: true,
239 pic_specific_commits: false,
240 range: false,
241 };
242 assert!(!args.is_help_request());
243
244 let args = Args {
246 repo_path: None,
247 email: Some("test@example.com".to_string()),
248 name: None,
249 start: None,
250 end: None,
251 show_history: false,
252 pic_specific_commits: false,
253 range: false,
254 };
255 assert!(!args.is_help_request());
256
257 let args = Args {
259 repo_path: None,
260 email: None,
261 name: None,
262 start: None,
263 end: None,
264 show_history: false,
265 pic_specific_commits: false,
266 range: true,
267 };
268 assert!(!args.is_help_request());
269
270 let args = Args {
272 repo_path: None,
273 email: None,
274 name: None,
275 start: None,
276 end: None,
277 show_history: false,
278 pic_specific_commits: true,
279 range: false,
280 };
281 assert!(!args.is_help_request());
282 }
283}