Skip to main content

radicle_cli/commands/seed/
args.rs

1use std::time;
2
3use clap::Parser;
4
5use nonempty::NonEmpty;
6use radicle::node::policy::Scope;
7use radicle::prelude::*;
8
9use crate::node::SyncSettings;
10use crate::terminal;
11
12const ABOUT: &str = "Manage repository seeding policies";
13
14const LONG_ABOUT: &str = r#"
15The `seed` command, when no Repository ID is provided, will list the
16repositories being seeded.
17
18When a Repository ID is provided it updates or creates the seeding policy for
19that repository. To delete a seeding policy, use the `rad unseed` command.
20
21When seeding a repository, a scope can be specified: this can be either `all` or
22`followed`. When using `all`, all remote nodes will be followed for that repository.
23On the other hand, with `followed`, only the repository delegates will be followed,
24plus any remote that is explicitly followed via `rad follow <nid>`.
25"#;
26
27#[derive(Parser, Debug)]
28#[command(about = ABOUT, long_about = LONG_ABOUT, disable_version_flag = true)]
29pub struct Args {
30    #[arg(value_name = "RID", num_args = 1..)]
31    pub(super) rids: Option<Vec<RepoId>>,
32
33    /// Fetch repository after updating seeding policy
34    #[arg(long, overrides_with("no_fetch"), hide(true))]
35    fetch: bool,
36
37    /// Do not fetch repository after updating seeding policy
38    #[arg(long, overrides_with("fetch"))]
39    no_fetch: bool,
40
41    /// Fetch from the given node (may be specified multiple times)
42    #[arg(long, value_name = "NID", action = clap::ArgAction::Append)]
43    pub(super) from: Vec<NodeId>,
44
45    /// Fetch timeout in seconds
46    ///
47    /// Valid arguments are for example "10s", "5min" or "2h 37min"
48    #[arg(long, short, value_parser = humantime::parse_duration, default_value = "9s")]
49    timeout: std::time::Duration,
50
51    /// Peer follow scope for this repository
52    #[arg(long, value_parser = terminal::args::ScopeParser)]
53    pub(super) scope: Option<Scope>,
54
55    /// Verbose output
56    #[arg(long, short)]
57    pub(super) verbose: bool,
58}
59
60pub(super) enum Operation {
61    List,
62    Seed {
63        rids: NonEmpty<RepoId>,
64        should_fetch: bool,
65        settings: SyncSettings,
66        scope: Option<Scope>,
67    },
68}
69
70impl From<Args> for Operation {
71    fn from(args: Args) -> Self {
72        let should_fetch = args.should_fetch();
73        let timeout = args.timeout();
74        let Args {
75            rids, from, scope, ..
76        } = args;
77        match rids.and_then(NonEmpty::from_vec) {
78            Some(rids) => Operation::Seed {
79                rids,
80                should_fetch,
81                settings: SyncSettings::default().seeds(from).timeout(timeout),
82                scope,
83            },
84            None => Self::List,
85        }
86    }
87}
88
89impl Args {
90    fn timeout(&self) -> time::Duration {
91        self.timeout
92    }
93
94    fn should_fetch(&self) -> bool {
95        match (self.fetch, self.no_fetch) {
96            (true, false) => true,
97            (false, true) => false,
98            // Default it to fetch
99            (_, _) => true,
100        }
101    }
102}