Skip to main content

git_stk/
cli.rs

1use clap::{Parser, Subcommand};
2
3use crate::commands;
4
5#[derive(Debug, Parser)]
6#[command(name = "git-stk")]
7#[command(version)]
8#[command(about = "Git-native stacked branch workflow helper, with GitHub and GitLab integration")]
9#[command(after_help = "New to stacking? Run `git stk guide` for short interactive tours.")]
10pub struct Cli {
11    /// Pass raw git output through instead of showing it only on failure, with
12    /// the occasional detail git-stk holds back because it would repeat every
13    /// run - such as a host that cannot answer for GitHub's stacked pull
14    /// requests.
15    #[arg(long, short = 'v', global = true)]
16    pub verbose: bool,
17    #[command(subcommand)]
18    pub command: Command,
19}
20
21// Ordered by workflow stage - create/edit, navigate, restack/resolve,
22// review/land, setup - rather than alphabetically: clap lists subcommands in
23// declaration order, so `git stk --help` reads as the workflow. clap has no way
24// to print headings or blank lines between subcommands, so the grouping is
25// conveyed by order alone; the blank lines below are for source readability.
26#[derive(Debug, Subcommand)]
27pub enum Command {
28    New(commands::new::New),
29    Adopt(commands::adopt::Adopt),
30    Split(commands::split::Split),
31    Rename(commands::rename::Rename),
32    Detach(commands::detach::Detach),
33    Unstack(commands::unstack::Unstack),
34    Absorb(commands::absorb::Absorb),
35
36    Up(commands::up::Up),
37    Down(commands::down::Down),
38    Top(commands::top::Top),
39    Bottom(commands::bottom::Bottom),
40    Parent(commands::parent::Parent),
41    Children(commands::children::Children),
42    List(commands::list::List),
43    Status(commands::status::Status),
44
45    Restack(commands::restack::Restack),
46    Run(commands::run::Run),
47    Continue(commands::restack::Continue),
48    Abort(commands::restack::Abort),
49    Undo(commands::undo::Undo),
50    Repair(commands::repair::Repair),
51
52    Submit(commands::submit::Submit),
53    Review(commands::review::Review),
54    View(commands::view::View),
55    Sync(commands::sync::Sync),
56    Merge(commands::merge::Merge),
57    Provider(commands::provider::Provider),
58
59    Config(commands::config::Config),
60    Setup(commands::setup::Setup),
61    Completions(commands::completions::Completions),
62    Guide(commands::guide::Guide),
63    Upgrade(commands::upgrade::Upgrade),
64    Downgrade(commands::downgrade::Downgrade),
65    Uninstall(commands::uninstall::Uninstall),
66    Cleanup(commands::cleanup::Cleanup),
67    Credits(commands::credits::Credits),
68}
69
70/// How many branches an `up`/`down` should move. Zero lands where you already
71/// are and the other direction is the other command's job, so neither is a
72/// distance.
73pub fn parse_distance(value: &str) -> Result<usize, String> {
74    match value.parse::<i64>() {
75        Ok(distance) if distance >= 1 => Ok(usize::try_from(distance).unwrap_or(usize::MAX)),
76        Ok(_) => {
77            Err("a distance is 1 or more branches - the other way is the other command".into())
78        }
79        Err(_) => Err("expected a number of branches".into()),
80    }
81}
82
83#[derive(Debug, Clone, Copy, Eq, PartialEq)]
84pub enum UpdateRefsMode {
85    Config,
86    Enabled,
87    Disabled,
88}
89
90impl UpdateRefsMode {
91    pub fn from_flags(update_refs: bool, no_update_refs: bool) -> Self {
92        match (update_refs, no_update_refs) {
93            (true, false) => Self::Enabled,
94            (false, true) => Self::Disabled,
95            _ => Self::Config,
96        }
97    }
98}
99
100#[derive(Debug, Clone, Copy, Eq, PartialEq)]
101pub enum PushMode {
102    Config,
103    Enabled,
104    Disabled,
105}
106
107impl PushMode {
108    pub fn from_flags(push: bool, no_push: bool) -> Self {
109        match (push, no_push) {
110            (true, false) => Self::Enabled,
111            (false, true) => Self::Disabled,
112            _ => Self::Config,
113        }
114    }
115}
116
117#[derive(Debug, Clone, Copy, Eq, PartialEq)]
118pub enum FetchMode {
119    Config,
120    Enabled,
121    Disabled,
122}
123
124impl FetchMode {
125    pub fn from_flags(fetch: bool, no_fetch: bool) -> Self {
126        match (fetch, no_fetch) {
127            (true, false) => Self::Enabled,
128            (false, true) => Self::Disabled,
129            _ => Self::Config,
130        }
131    }
132}