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