radicle_cli/commands/
block.rs1use std::ffi::OsString;
2
3use radicle::node::policy::Policy;
4use radicle::prelude::{NodeId, RepoId};
5
6use crate::terminal as term;
7use crate::terminal::args;
8use crate::terminal::args::{Args, Error, Help};
9
10pub const HELP: Help = Help {
11 name: "block",
12 description: "Block repositories or nodes from being seeded or followed",
13 version: env!("RADICLE_VERSION"),
14 usage: r#"
15Usage
16
17 rad block <rid> [<option>...]
18 rad block <nid> [<option>...]
19
20 Blocks a repository from being seeded or a node from being followed.
21
22Options
23
24 --help Print help
25"#,
26};
27
28enum Target {
29 Node(NodeId),
30 Repo(RepoId),
31}
32
33impl std::fmt::Display for Target {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 Self::Node(nid) => nid.fmt(f),
37 Self::Repo(rid) => rid.fmt(f),
38 }
39 }
40}
41
42pub struct Options {
43 target: Target,
44}
45
46impl Args for Options {
47 fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
48 use lexopt::prelude::*;
49
50 let mut parser = lexopt::Parser::from_args(args);
51 let mut target = None;
52
53 while let Some(arg) = parser.next()? {
54 match arg {
55 Long("help") | Short('h') => {
56 return Err(Error::Help.into());
57 }
58 Value(val) if target.is_none() => {
59 if let Ok(rid) = args::rid(&val) {
60 target = Some(Target::Repo(rid));
61 } else if let Ok(nid) = args::nid(&val) {
62 target = Some(Target::Node(nid));
63 } else {
64 anyhow::bail!(
65 "invalid repository or node specified, see `rad block --help`"
66 )
67 }
68 }
69 _ => anyhow::bail!(arg.unexpected()),
70 }
71 }
72
73 Ok((
74 Options {
75 target: target.ok_or(anyhow::anyhow!(
76 "a repository or node to block must be specified, see `rad block --help`"
77 ))?,
78 },
79 vec![],
80 ))
81 }
82}
83
84pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
85 let profile = ctx.profile()?;
86 let mut policies = profile.policies_mut()?;
87
88 let updated = match options.target {
89 Target::Node(nid) => policies.set_follow_policy(&nid, Policy::Block)?,
90 Target::Repo(rid) => policies.set_seed_policy(&rid, Policy::Block)?,
91 };
92 if updated {
93 term::success!("Policy for {} set to 'block'", options.target);
94 }
95 Ok(())
96}