Skip to main content

radicle_cli/commands/remote/
args.rs

1use clap::{Parser, Subcommand};
2
3use radicle::git;
4use radicle::git::fmt::RefString;
5use radicle::node::NodeId;
6
7use crate::terminal as term;
8
9const ABOUT: &str = "Manage a repository's remotes";
10
11#[derive(Parser, Debug)]
12#[command(about = ABOUT, disable_version_flag = true)]
13pub struct Args {
14    #[command(subcommand)]
15    pub(super) command: Option<Command>,
16
17    /// Arguments for the empty subcommand.
18    /// Will fall back to [`Command::List`].
19    #[clap(flatten)]
20    pub(super) empty: EmptyArgs,
21}
22
23#[derive(Subcommand, Debug)]
24pub(super) enum Command {
25    /// Add a Git remote for the provided NID
26    #[clap(alias = "a")]
27    Add {
28        /// The DID or NID of the remote to add
29        #[arg(value_parser = term::args::parse_nid)]
30        nid: NodeId,
31
32        /// Override the name of the Git remote
33        ///
34        /// [default: <ALIAS>@<NID>]
35        #[arg(long, short, value_name = "REMOTE", value_parser = parse_refstr)]
36        name: Option<RefString>,
37
38        #[clap(flatten)]
39        fetch: FetchArgs,
40
41        #[clap(flatten)]
42        sync: SyncArgs,
43    },
44    /// Remove the Git remote identified by REMOTE
45    #[clap(alias = "r")]
46    Rm {
47        /// The name of the remote to delete
48        #[arg(value_name = "REMOTE", value_parser = parse_refstr)]
49        name: RefString,
50    },
51    /// List the stored remotes
52    ///
53    /// Filter the listed remotes using the provided options
54    #[clap(alias = "l")]
55    List(ListArgs),
56}
57
58#[derive(Parser, Debug)]
59pub(super) struct FetchArgs {
60    /// Fetch the remote from local storage (default)
61    #[arg(long, conflicts_with = "no_fetch")]
62    fetch: bool,
63
64    /// Do not fetch the remote from local storage
65    #[arg(long)]
66    no_fetch: bool,
67}
68
69impl FetchArgs {
70    pub(super) fn should_fetch(&self) -> bool {
71        let Self { fetch, no_fetch } = self;
72        *fetch || !no_fetch
73    }
74}
75
76#[derive(Parser, Debug)]
77pub(super) struct SyncArgs {
78    /// Sync the remote refs from the network (default)
79    #[arg(long, conflicts_with = "no_sync")]
80    sync: bool,
81
82    /// Do not sync the remote refs from the network
83    #[arg(long)]
84    no_sync: bool,
85}
86
87impl SyncArgs {
88    pub(super) fn should_sync(&self) -> bool {
89        let Self { sync, no_sync } = self;
90        *sync || !no_sync
91    }
92}
93
94#[derive(Parser, Clone, Copy, Debug)]
95#[group(multiple = false)]
96pub struct ListArgs {
97    /// Show all remotes in both the Radicle storage and the working copy
98    #[arg(long)]
99    all: bool,
100
101    /// Show all remotes that are listed in the working copy
102    #[arg(long)]
103    tracked: bool,
104
105    /// Show all remotes that are listed in the Radicle storage
106    #[arg(long)]
107    untracked: bool,
108}
109
110impl From<ListArgs> for ListOption {
111    fn from(
112        ListArgs {
113            all,
114            tracked,
115            untracked,
116        }: ListArgs,
117    ) -> Self {
118        match (all, tracked, untracked) {
119            (true, false, false) => Self::All,
120            (false, true, false) | (false, false, false) => Self::Tracked,
121            (false, false, true) => Self::Untracked,
122            _ => unreachable!(),
123        }
124    }
125}
126
127pub(super) enum ListOption {
128    /// Show all remotes in both the Radicle storage and the working copy
129    All,
130    /// Show all remotes that are listed in the working copy
131    Tracked,
132    /// Show all remotes that are listed in the Radicle storage
133    Untracked,
134}
135
136#[derive(Parser, Clone, Copy, Debug)]
137#[group(multiple = false)]
138pub(super) struct EmptyArgs {
139    #[arg(long, hide = true)]
140    all: bool,
141
142    #[arg(long, hide = true)]
143    tracked: bool,
144
145    #[arg(long, hide = true)]
146    untracked: bool,
147}
148
149impl From<EmptyArgs> for ListArgs {
150    fn from(args: EmptyArgs) -> Self {
151        Self {
152            all: args.all,
153            tracked: args.tracked,
154            untracked: args.untracked,
155        }
156    }
157}
158
159fn parse_refstr(refstr: &str) -> Result<RefString, git::fmt::Error> {
160    RefString::try_from(refstr)
161}