radicle_cli/commands/
unblock.rs

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