1use clap::Parser;
2
3use crate::model::{Options, SortBy};
4
5#[derive(Parser)]
6#[command(author, version, about, long_about = None)]
7pub struct Cli {
8 #[arg(name = "revision-range", default_value = "HEAD")]
9 rev_range: String,
16 #[arg(short, long)]
17 email: bool,
19 #[arg(short, long)]
20 reviews: bool,
23 #[arg(short, long, value_enum, default_value_t = SortBy::Commits)]
25 sort: SortBy,
26 #[arg(long)]
28 reverse: bool,
29 #[arg(short, long)]
33 author: Option<Vec<String>>,
34 #[arg(long)]
36 since: Option<String>,
37 #[arg(long)]
39 until: Option<String>,
40}
41
42impl Cli {
43 #[must_use]
45 pub fn into_options(self) -> Options {
46 Options {
47 range: self.rev_range,
48 email: self.email,
49 reviews: self.reviews,
50 sort: self.sort,
51 reverse: self.reverse,
52 authors: self.author.unwrap_or_default(),
53 since: self.since,
54 until: self.until,
55 }
56 }
57}
58
59#[cfg(test)]
60mod test {
61 use super::Cli;
62 use crate::model::{Options, SortBy};
63 use clap::Parser;
64
65 #[test]
66 fn verify_app() {
67 use clap::CommandFactory;
68 Cli::command().debug_assert();
69 }
70
71 #[test]
72 fn into_options_maps_parsed_flags() {
73 let cli = Cli::try_parse_from([
74 "git-stats",
75 "--email",
76 "--reviews",
77 "--reverse",
78 "--sort",
79 "net",
80 "--author",
81 "alice",
82 "--since",
83 "2020-01-01",
84 "--until",
85 "2021-01-01",
86 "origin..HEAD",
87 ])
88 .unwrap();
89
90 let expected = Options {
91 range: "origin..HEAD".to_string(),
92 email: true,
93 reviews: true,
94 sort: SortBy::Net,
95 reverse: true,
96 authors: vec!["alice".to_string()],
97 since: Some("2020-01-01".to_string()),
98 until: Some("2021-01-01".to_string()),
99 };
100 assert_eq!(cli.into_options(), expected);
101 }
102
103 #[test]
104 fn into_options_uses_defaults_without_flags() {
105 let opts = Cli::try_parse_from(["git-stats"]).unwrap().into_options();
106
107 let expected = Options {
108 range: "HEAD".to_string(),
109 email: false,
110 reviews: false,
111 sort: SortBy::Commits,
112 reverse: false,
113 authors: Vec::new(),
114 since: None,
115 until: None,
116 };
117 assert_eq!(opts, expected);
118 }
119}