1use clap::Parser;
2
3use crate::cmds::{
4 gist::GistListCliArgs,
5 merge_request::{MergeRequestListCliArgs, MergeRequestUser},
6 project::ProjectListCliArgs,
7};
8
9use super::{common::ListArgs, merge_request::ListMergeRequest, project::ListProject};
10
11#[derive(Parser)]
12pub struct MyCommand {
13 #[clap(subcommand)]
14 subcommand: MySubcommand,
15}
16
17#[derive(Parser)]
18enum MySubcommand {
19 #[clap(
20 about = "Lists the merge requests where you are the author, assignee or the reviewer",
21 name = "mr"
22 )]
23 MergeRequest(ListMyMergeRequest),
24 #[clap(about = "Lists your projects", name = "pj")]
25 Project(ListProject),
26 #[clap(about = "Lists your starred projects", name = "st")]
27 Star(ListStar),
28 #[clap(about = "Lists your gists", name = "gs")]
29 Gist(ListGist),
30}
31
32#[derive(Parser)]
33struct ListMyMergeRequest {
34 #[clap(long, group = "merge_request")]
36 assignee: bool,
37 #[clap(long, group = "merge_request")]
40 author: bool,
41 #[clap(long, group = "merge_request")]
43 reviewer: bool,
44 #[clap(flatten)]
45 list_merge_request: ListMergeRequest,
46}
47
48pub enum MyOptions {
49 MergeRequest(MergeRequestListCliArgs),
50 Project(ProjectListCliArgs),
51 Gist(GistListCliArgs),
52}
53
54impl From<MyCommand> for MyOptions {
55 fn from(options: MyCommand) -> Self {
56 match options.subcommand {
57 MySubcommand::MergeRequest(options) => options.into(),
58 MySubcommand::Project(options) => options.into(),
59 MySubcommand::Star(options) => options.into(),
60 MySubcommand::Gist(options) => options.into(),
61 }
62 }
63}
64
65impl From<ListMyMergeRequest> for MyOptions {
66 fn from(options: ListMyMergeRequest) -> Self {
67 MyOptions::MergeRequest(
68 MergeRequestListCliArgs::builder()
69 .state(options.list_merge_request.state.into())
70 .list_args(options.list_merge_request.list_args.into())
71 .assignee(if options.assignee {
72 Some(MergeRequestUser::Me)
73 } else {
74 None
75 })
76 .author(
78 if options.author || (!options.assignee && !options.reviewer) {
79 Some(MergeRequestUser::Me)
80 } else {
81 None
82 },
83 )
84 .reviewer(if options.reviewer {
85 Some(MergeRequestUser::Me)
86 } else {
87 None
88 })
89 .build()
90 .unwrap(),
91 )
92 }
93}
94
95impl From<ListProject> for MyOptions {
96 fn from(options: ListProject) -> Self {
97 MyOptions::Project(
98 ProjectListCliArgs::builder()
99 .list_args(options.list_args.into())
100 .build()
101 .unwrap(),
102 )
103 }
104}
105
106#[derive(Parser)]
107pub struct ListStar {
108 #[clap(flatten)]
109 pub list_args: ListArgs,
110}
111
112impl From<ListStar> for MyOptions {
113 fn from(options: ListStar) -> Self {
114 MyOptions::Project(
115 ProjectListCliArgs::builder()
116 .list_args(options.list_args.into())
117 .stars(true)
118 .build()
119 .unwrap(),
120 )
121 }
122}
123
124#[derive(Parser)]
125pub struct ListGist {
126 #[clap(flatten)]
127 pub list_args: ListArgs,
128}
129
130impl From<ListGist> for MyOptions {
131 fn from(options: ListGist) -> Self {
132 MyOptions::Gist(
133 GistListCliArgs::builder()
134 .list_args(options.list_args.into())
135 .build()
136 .unwrap(),
137 )
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use crate::{
145 cli::{merge_request::MergeRequestStateStateCli, Args, Command},
146 cmds::merge_request::MergeRequestState,
147 };
148
149 #[test]
150 fn test_my_merge_request_cli_args() {
151 let args = Args::parse_from(vec!["gr", "my", "mr", "opened"]);
152 let my_command = match args.command {
153 Command::My(MyCommand {
154 subcommand: MySubcommand::MergeRequest(options),
155 }) => {
156 assert_eq!(
157 options.list_merge_request.state,
158 MergeRequestStateStateCli::Opened
159 );
160 options
161 }
162 _ => panic!("Expected MyCommand"),
163 };
164 let options: MyOptions = my_command.into();
165 match options {
166 MyOptions::MergeRequest(options) => {
167 assert_eq!(options.state, MergeRequestState::Opened);
168 assert_eq!(options.author, Some(MergeRequestUser::Me));
169 }
170 _ => panic!("Expected MyOptions::MergeRequest"),
171 }
172 }
173
174 #[test]
175 fn test_my_merge_request_cli_args_reviewer() {
176 let args = Args::parse_from(vec!["gr", "my", "mr", "opened", "--reviewer"]);
177 let my_command = match args.command {
178 Command::My(MyCommand {
179 subcommand: MySubcommand::MergeRequest(options),
180 }) => {
181 assert_eq!(
182 options.list_merge_request.state,
183 MergeRequestStateStateCli::Opened
184 );
185 assert!(options.reviewer);
186 options
187 }
188 _ => panic!("Expected MyCommand"),
189 };
190 let options: MyOptions = my_command.into();
191 match options {
192 MyOptions::MergeRequest(options) => {
193 assert_eq!(options.state, MergeRequestState::Opened);
194 assert_eq!(options.reviewer, Some(MergeRequestUser::Me));
195 }
196 _ => panic!("Expected MyOptions::MergeRequest"),
197 }
198 }
199
200 #[test]
201 fn test_my_merge_request_cli_args_author() {
202 let args = Args::parse_from(vec!["gr", "my", "mr", "opened", "--author"]);
203 let my_command = match args.command {
204 Command::My(MyCommand {
205 subcommand: MySubcommand::MergeRequest(options),
206 }) => {
207 assert_eq!(
208 options.list_merge_request.state,
209 MergeRequestStateStateCli::Opened
210 );
211 assert!(options.author);
212 options
213 }
214 _ => panic!("Expected MyCommand"),
215 };
216 let options: MyOptions = my_command.into();
217 match options {
218 MyOptions::MergeRequest(options) => {
219 assert_eq!(options.state, MergeRequestState::Opened);
220 assert_eq!(options.author, Some(MergeRequestUser::Me));
221 }
222 _ => panic!("Expected MyOptions::MergeRequest"),
223 }
224 }
225
226 #[test]
227 fn test_my_merge_request_cli_args_assignee() {
228 let args = Args::parse_from(vec!["gr", "my", "mr", "opened", "--assignee"]);
229 let my_command = match args.command {
230 Command::My(MyCommand {
231 subcommand: MySubcommand::MergeRequest(options),
232 }) => {
233 assert_eq!(
234 options.list_merge_request.state,
235 MergeRequestStateStateCli::Opened
236 );
237 assert!(options.assignee);
238 options
239 }
240 _ => panic!("Expected MyCommand"),
241 };
242 let options: MyOptions = my_command.into();
243 match options {
244 MyOptions::MergeRequest(options) => {
245 assert_eq!(options.state, MergeRequestState::Opened);
246 assert_eq!(options.assignee, Some(MergeRequestUser::Me));
247 }
248 _ => panic!("Expected MyOptions::MergeRequest"),
249 }
250 }
251
252 #[test]
253 fn test_my_projects_cli_args() {
254 let args = Args::parse_from(vec!["gr", "my", "pj"]);
255 let my_command = match args.command {
256 Command::My(MyCommand {
257 subcommand: MySubcommand::Project(options),
258 }) => options,
259 _ => panic!("Expected MyCommand"),
260 };
261 let options: MyOptions = my_command.into();
262 match options {
263 MyOptions::Project(_) => {}
264 _ => panic!("Expected MyOptions::Project"),
265 }
266 }
267
268 #[test]
269 fn test_my_stars_cli_args() {
270 let args = Args::parse_from(vec!["gr", "my", "st"]);
271 let my_command = match args.command {
272 Command::My(MyCommand {
273 subcommand: MySubcommand::Star(options),
274 }) => options,
275 _ => panic!("Expected MyCommand"),
276 };
277 let options: MyOptions = my_command.into();
278 match options {
279 MyOptions::Project(_) => {}
280 _ => panic!("Expected MyOptions::Star"),
281 }
282 }
283
284 #[test]
285 fn test_my_gists_cli_args() {
286 let args = Args::parse_from(vec!["gr", "my", "gs"]);
287 let my_command = match args.command {
288 Command::My(MyCommand {
289 subcommand: MySubcommand::Gist(options),
290 }) => options,
291 _ => panic!("Expected MyCommand"),
292 };
293 let options: MyOptions = my_command.into();
294 match options {
295 MyOptions::Gist(_) => {}
296 _ => panic!("Expected MyOptions::Gist"),
297 }
298 }
299}