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    #[arg(long, short, value_name = "SECS", default_value_t = 9)]
47    timeout: u64,
48
49    /// Peer follow scope for this repository
50    #[arg(
51        long,
52        default_value_t = Scope::Followed,
53        value_parser = terminal::args::ScopeParser
54    )]
55    pub(super) scope: Scope,
56
57    /// Verbose output
58    #[arg(long, short)]
59    pub(super) verbose: bool,
60}
61
62pub(super) enum Operation {
63    List,
64    Seed {
65        rids: NonEmpty<RepoId>,
66        should_fetch: bool,
67        settings: SyncSettings,
68        scope: Scope,
69    },
70}
71
72impl From<Args> for Operation {
73    fn from(args: Args) -> Self {
74        let should_fetch = args.should_fetch();
75        let timeout = args.timeout();
76        let Args {
77            rids, from, scope, ..
78        } = args;
79        match rids.and_then(NonEmpty::from_vec) {
80            Some(rids) => Operation::Seed {
81                rids,
82                should_fetch,
83                settings: SyncSettings::default().seeds(from).timeout(timeout),
84                scope,
85            },
86            None => Self::List,
87        }
88    }
89}
90
91impl Args {
92    fn timeout(&self) -> time::Duration {
93        time::Duration::from_secs(self.timeout)
94    }
95
96    fn should_fetch(&self) -> bool {
97        match (self.fetch, self.no_fetch) {
98            (true, false) => true,
99            (false, true) => false,
100            // Default it to fetch
101            (_, _) => true,
102        }
103    }
104}