Skip to main content

git_stk/
cli.rs

1use clap::{ArgAction, Parser, Subcommand};
2use clap_complete::engine::ArgValueCompleter;
3
4use crate::completions;
5
6#[derive(Debug, Parser)]
7#[command(name = "git-stk")]
8#[command(version)]
9#[command(about = "Git-native stacked branch workflow helper, with GitHub and GitLab integration")]
10pub struct Cli {
11    #[command(subcommand)]
12    pub command: Command,
13}
14
15#[derive(Debug, Subcommand)]
16pub enum Command {
17    /// Create a new child branch from the current branch.
18    New { branch: String },
19    /// Print a branch's stack parent.
20    Parent {
21        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
22        branch: Option<String>,
23    },
24    /// Print a branch's stack children.
25    Children {
26        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
27        branch: Option<String>,
28    },
29    /// Move up the stack: check out a child of the current branch.
30    Up {
31        #[arg(add = ArgValueCompleter::new(completions::child_branch_candidates))]
32        branch: Option<String>,
33    },
34    /// Move down the stack: check out the current branch's parent.
35    Down,
36    /// Print the current stack.
37    List,
38    /// Print local and remote stack status for a branch.
39    Status {
40        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
41        branch: Option<String>,
42    },
43    /// Attach an existing branch to a parent.
44    Adopt {
45        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
46        branch: String,
47        #[arg(long, add = ArgValueCompleter::new(completions::branch_candidates))]
48        parent: String,
49    },
50    /// Remove stack parent metadata from a branch.
51    Detach {
52        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
53        branch: Option<String>,
54    },
55    /// Rebase the current branch and descendants onto their stack parents.
56    Restack {
57        /// Pass --update-refs to git rebase.
58        #[arg(long, action = ArgAction::SetTrue, conflicts_with = "no_update_refs")]
59        update_refs: bool,
60        /// Do not pass --update-refs to git rebase.
61        #[arg(long, action = ArgAction::SetTrue)]
62        no_update_refs: bool,
63        /// Force-push (with lease) every rebased branch afterwards.
64        #[arg(long, action = ArgAction::SetTrue, conflicts_with = "no_push")]
65        push: bool,
66        /// Do not push rebased branches, overriding stk.pushOnRestack.
67        #[arg(long, action = ArgAction::SetTrue)]
68        no_push: bool,
69    },
70    /// Continue an interrupted restack after resolving conflicts.
71    Continue,
72    /// Abort an interrupted restack.
73    Abort,
74    /// Print detected review provider.
75    Provider,
76    /// Print the review request for a branch.
77    Review {
78        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
79        branch: Option<String>,
80    },
81    /// Sync local stack metadata from remote review requests.
82    Sync {
83        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
84        branch: Option<String>,
85        /// Print what would change without updating local metadata.
86        #[arg(long, action = ArgAction::SetTrue)]
87        dry_run: bool,
88    },
89    /// Rebuild or verify local stack metadata from reviews and ancestry.
90    Repair {
91        /// Print what would change without updating local metadata.
92        #[arg(long, action = ArgAction::SetTrue)]
93        dry_run: bool,
94    },
95    /// Create or update a remote review request for a branch.
96    Submit {
97        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
98        branch: Option<String>,
99        /// Print what would change without creating or updating reviews.
100        #[arg(long, action = ArgAction::SetTrue)]
101        dry_run: bool,
102        /// Submit the branch and its descendants parent-first.
103        #[arg(long, conflicts_with = "branch")]
104        stack: bool,
105        /// Push branches (-u --force-with-lease) before submitting.
106        #[arg(long, action = ArgAction::SetTrue, conflicts_with = "no_push")]
107        push: bool,
108        /// Do not push branches, overriding stk.pushOnSubmit.
109        #[arg(long, action = ArgAction::SetTrue)]
110        no_push: bool,
111    },
112    /// Print all stk git config settings and branch metadata.
113    Config,
114    /// Print shell completions.
115    Completions {
116        /// Shell to print completions for.
117        #[arg(value_enum)]
118        shell: clap_complete::Shell,
119    },
120    /// Install the man page and wire up shell completions.
121    Setup {
122        /// Skip confirmation prompts.
123        #[arg(long, short = 'y', action = ArgAction::SetTrue)]
124        yes: bool,
125        /// Only re-render generated assets (man page); never touch shell rc files.
126        #[arg(long, action = ArgAction::SetTrue, conflicts_with = "yes")]
127        refresh: bool,
128    },
129    /// Upgrade git-stk to the latest release.
130    Upgrade {
131        /// Build and install the latest unreleased commit instead.
132        #[arg(long, action = ArgAction::SetTrue, conflicts_with = "force")]
133        head: bool,
134        /// Reinstall the latest release even when already up to date.
135        #[arg(long, action = ArgAction::SetTrue)]
136        force: bool,
137        /// Skip the --head confirmation prompt.
138        #[arg(long, short = 'y', action = ArgAction::SetTrue, requires = "head")]
139        yes: bool,
140    },
141    /// Clean up local metadata for merged review requests.
142    Cleanup {
143        #[arg(add = ArgValueCompleter::new(completions::branch_candidates))]
144        branch: Option<String>,
145        /// Print what would change without updating local metadata.
146        #[arg(long, action = ArgAction::SetTrue)]
147        dry_run: bool,
148        /// Delete cleaned merged branches after updating stack metadata.
149        #[arg(long, action = ArgAction::SetTrue)]
150        delete_branch: bool,
151    },
152}
153
154#[derive(Debug, Clone, Copy, Eq, PartialEq)]
155pub enum UpdateRefsMode {
156    Config,
157    Enabled,
158    Disabled,
159}
160
161impl UpdateRefsMode {
162    pub fn from_flags(update_refs: bool, no_update_refs: bool) -> Self {
163        match (update_refs, no_update_refs) {
164            (true, false) => Self::Enabled,
165            (false, true) => Self::Disabled,
166            _ => Self::Config,
167        }
168    }
169}
170
171#[derive(Debug, Clone, Copy, Eq, PartialEq)]
172pub enum PushMode {
173    Config,
174    Enabled,
175    Disabled,
176}
177
178impl PushMode {
179    pub fn from_flags(push: bool, no_push: bool) -> Self {
180        match (push, no_push) {
181            (true, false) => Self::Enabled,
182            (false, true) => Self::Disabled,
183            _ => Self::Config,
184        }
185    }
186}