1use clap::{ArgAction, Parser};
2
3#[derive(Copy, Clone, Debug, Eq, PartialEq)]
4pub enum CommitsToConsider {
5 All,
6 WithTrailer,
7}
8
9impl From<&str> for CommitsToConsider {
10 fn from(value: &str) -> Self {
11 match value {
12 "true" => Self::All,
13 "false" => Self::WithTrailer,
14 _ => unreachable!(),
15 }
16 }
17}
18
19#[derive(Copy, Clone, Debug, Eq, PartialEq)]
20pub enum PromptUserToChooseCommits {
21 Yes,
22 No,
23}
24
25impl From<&str> for PromptUserToChooseCommits {
26 fn from(value: &str) -> Self {
27 match value {
28 "true" => Self::Yes,
29 "false" => Self::No,
30 _ => unreachable!(),
31 }
32 }
33}
34
35#[derive(Copy, Clone, Debug, Eq, PartialEq)]
36pub enum OverlayCommitsIntoOnePullRequest {
37 Yes,
38 No,
39}
40
41impl From<&str> for OverlayCommitsIntoOnePullRequest {
42 fn from(value: &str) -> Self {
43 match value {
44 "true" => Self::Yes,
45 "false" => Self::No,
46 _ => unreachable!(),
47 }
48 }
49}
50
51#[derive(Copy, Clone, Debug, Eq, PartialEq)]
52pub enum CommitGrouping {
53 Individual,
54 ByIssue,
55}
56
57impl From<&str> for CommitGrouping {
58 fn from(value: &str) -> Self {
59 match value {
60 "true" => Self::Individual,
61 "false" => Self::ByIssue,
62 _ => unreachable!(),
63 }
64 }
65}
66
67#[derive(Clone, Debug, Parser)]
68#[command(author, version, about)]
69pub struct Cli {
70 #[arg(
79 short,
80 long,
81 help = "Consider every commit, even commits without an issue trailer",
82 action = ArgAction::SetTrue,
83 )]
84 pub all: CommitsToConsider,
85
86 #[arg(
90 short,
91 long,
92 help = "The starting point (exclusive) of commits to act on",
93 value_name = "REF"
94 )]
95 pub base: Option<String>,
96
97 #[arg(
102 short,
103 long,
104 help = "Prompt the user to select which issues to create PRs for",
105 action = ArgAction::SetTrue,
106 )]
107 pub choose: PromptUserToChooseCommits,
108
109 #[arg(
111 short,
112 long,
113 env = "GIT_DISJOINT_DRY_RUN",
114 help = "Show the work that would be performed without taking any action"
115 )]
116 pub dry_run: bool,
117
118 #[arg(
123 long,
124 env = "GITHUB_TOKEN",
125 help = "GitHub API token [default: resolved from gh auth token]",
126 value_name = "TOKEN"
127 )]
128 pub github_token: Option<String>,
129
130 #[arg(
137 short,
138 long,
139 help = "Combine multiple issue groups into one PR",
140 action = ArgAction::SetTrue,
141 )]
142 pub overlay: OverlayCommitsIntoOnePullRequest,
143
144 #[arg(
149 short,
150 long,
151 help = "Create pull requests as ready for review instead of draft"
152 )]
153 pub ready: bool,
154
155 #[arg(
166 short,
167 long,
168 help = "Treat every commit separately; do not group by issue",
169 action = ArgAction::SetTrue,
170 )]
171 pub separate: CommitGrouping,
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn parse_without_token_returns_none() {
180 let cli = Cli::try_parse_from(["git-disjoint"]).unwrap();
181 assert_eq!(cli.github_token, None);
182 }
183
184 #[test]
185 fn parse_with_token_flag_returns_some() {
186 let cli = Cli::try_parse_from(["git-disjoint", "--github-token", "ghp_abc123"]).unwrap();
187 assert_eq!(cli.github_token, Some("ghp_abc123".into()));
188 }
189}