use std::time;
use clap::Parser;
use nonempty::NonEmpty;
use radicle::node::policy::Scope;
use radicle::prelude::*;
use crate::node::SyncSettings;
use crate::terminal;
const ABOUT: &str = "Manage repository seeding policies";
const LONG_ABOUT: &str = r#"
The `seed` command, when no Repository ID is provided, will list the
repositories being seeded.
When a Repository ID is provided it updates or creates the seeding policy for
that repository. To delete a seeding policy, use the `rad unseed` command.
When seeding a repository, a scope can be specified: this can be either `all` or
`followed`. When using `all`, all remote nodes will be followed for that repository.
On the other hand, with `followed`, only the repository delegates will be followed,
plus any remote that is explicitly followed via `rad follow <nid>`.
"#;
#[derive(Parser, Debug)]
#[command(about = ABOUT, long_about = LONG_ABOUT, disable_version_flag = true)]
pub struct Args {
#[arg(value_name = "RID", num_args = 1..)]
pub(super) rids: Option<Vec<RepoId>>,
#[arg(long, overrides_with("no_fetch"), hide(true))]
fetch: bool,
#[arg(long, overrides_with("fetch"))]
no_fetch: bool,
#[arg(long, value_name = "NID", action = clap::ArgAction::Append)]
pub(super) from: Vec<NodeId>,
#[arg(long, short, value_parser = humantime::parse_duration, default_value = "9s")]
timeout: std::time::Duration,
#[arg(long, value_parser = terminal::args::ScopeParser)]
pub(super) scope: Option<Scope>,
#[arg(long, short)]
pub(super) verbose: bool,
}
pub(super) enum Operation {
List,
Seed {
rids: NonEmpty<RepoId>,
should_fetch: bool,
settings: SyncSettings,
scope: Option<Scope>,
},
}
impl From<Args> for Operation {
fn from(args: Args) -> Self {
let should_fetch = args.should_fetch();
let timeout = args.timeout();
let Args {
rids, from, scope, ..
} = args;
match rids.and_then(NonEmpty::from_vec) {
Some(rids) => Operation::Seed {
rids,
should_fetch,
settings: SyncSettings::default().seeds(from).timeout(timeout),
scope,
},
None => Self::List,
}
}
}
impl Args {
fn timeout(&self) -> time::Duration {
self.timeout
}
fn should_fetch(&self) -> bool {
match (self.fetch, self.no_fetch) {
(true, false) => true,
(false, true) => false,
(_, _) => true,
}
}
}