Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
cli/unfollow: Use clap
Merged lorenz opened 7 months ago

See issue/7fb03f234030b91c38cc4f5b48bd30cf5fd6a1de.

4 files changed +52 -75 6fb1ebec ee49e287
modified crates/radicle-cli/src/commands/help.rs
@@ -61,7 +61,10 @@ const COMMANDS: &[CommandItem] = &[
    CommandItem::Lexopt(crate::commands::seed::HELP),
    CommandItem::Lexopt(crate::commands::follow::HELP),
    CommandItem::Lexopt(crate::commands::unblock::HELP),
-
    CommandItem::Lexopt(crate::commands::unfollow::HELP),
+
    CommandItem::Clap {
+
        name: "unfollow",
+
        about: crate::commands::unfollow::ABOUT,
+
    },
    CommandItem::Lexopt(crate::commands::unseed::HELP),
    CommandItem::Lexopt(crate::commands::remote::HELP),
    CommandItem::Lexopt(crate::commands::stats::HELP),
modified crates/radicle-cli/src/commands/unfollow.rs
@@ -1,77 +1,13 @@
-
use std::ffi::OsString;
+
mod args;

-
use anyhow::anyhow;
-

-
use radicle::node::{Handle, NodeId};
+
use radicle::node::Handle;

use crate::terminal as term;
-
use crate::terminal::args::{Args, Error, Help};
-

-
pub const HELP: Help = Help {
-
    name: "unfollow",
-
    description: "Unfollow a peer",
-
    version: env!("RADICLE_VERSION"),
-
    usage: r#"
-
Usage
-

-
    rad unfollow <nid> [<option>...]
-

-
    The `unfollow` command takes a Node ID (<nid>), optionally in DID format,
-
    and removes the follow policy for that peer.
-

-
Options
-

-
    --verbose, -v          Verbose output
-
    --help                 Print help
-
"#,
-
};
-

-
#[derive(Debug)]
-
pub struct Options {
-
    pub nid: NodeId,
-
    pub verbose: bool,
-
}
-

-
impl Args for Options {
-
    fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
-
        use lexopt::prelude::*;

-
        let mut parser = lexopt::Parser::from_args(args);
-
        let mut nid: Option<NodeId> = None;
-
        let mut verbose = false;
-

-
        while let Some(arg) = parser.next()? {
-
            match &arg {
-
                Value(val) if nid.is_none() => {
-
                    if let Ok(did) = term::args::did(val) {
-
                        nid = Some(did.into());
-
                    } else if let Ok(val) = term::args::nid(val) {
-
                        nid = Some(val);
-
                    } else {
-
                        anyhow::bail!("invalid Node ID `{}` specified", val.to_string_lossy());
-
                    }
-
                }
-
                Long("verbose") | Short('v') => verbose = true,
-
                Long("help") | Short('h') => {
-
                    return Err(Error::Help.into());
-
                }
-
                _ => {
-
                    return Err(anyhow!(arg.unexpected()));
-
                }
-
            }
-
        }
-

-
        Ok((
-
            Options {
-
                nid: nid.ok_or_else(|| anyhow!("a Node ID must be specified"))?,
-
                verbose,
-
            },
-
            vec![],
-
        ))
-
    }
-
}
+
pub use args::Args;
+
pub(crate) use args::ABOUT;

-
pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
+
pub fn run(options: Args, ctx: impl term::Context) -> anyhow::Result<()> {
    let profile = ctx.profile()?;
    let mut node = radicle::Node::new(profile.socket());
    let nid = options.nid;
added crates/radicle-cli/src/commands/unfollow/args.rs
@@ -0,0 +1,39 @@
+
use clap::Parser;
+

+
use thiserror::Error;
+

+
use radicle::node::NodeId;
+
use radicle::prelude::Did;
+

+
pub(crate) const ABOUT: &str = "Unfollow a peer";
+

+
const LONG_ABOUT: &str = r#"
+
The `unfollow` command takes a Node ID, optionally in DID format,
+
and removes the follow policy for that peer."#;
+

+
#[derive(Debug, Error)]
+
#[error("invalid Node ID specified (Node ID parsing failed with: '{nid}', DID parsing failed with: '{did}'))")]
+
struct NodeIdParseError {
+
    did: radicle::identity::did::DidError,
+
    nid: radicle::crypto::PublicKeyError,
+
}
+

+
fn parse_nid(value: &str) -> Result<NodeId, NodeIdParseError> {
+
    value.parse::<Did>().map(NodeId::from).or_else(|did| {
+
        value
+
            .parse::<NodeId>()
+
            .map_err(|nid| NodeIdParseError { nid, did })
+
    })
+
}
+

+
#[derive(Debug, Parser)]
+
#[command(about = ABOUT, long_about = LONG_ABOUT, disable_version_flag = true)]
+
pub struct Args {
+
    /// Node ID (optionally in DID format) of the peer to unfollow
+
    #[arg(value_name = "NID", value_parser = parse_nid)]
+
    pub nid: NodeId,
+

+
    /// Verbose output
+
    #[arg(short, long)]
+
    pub verbose: bool,
+
}
modified crates/radicle-cli/src/main.rs
@@ -46,6 +46,7 @@ struct CliArgs {
#[derive(Subcommand, Debug)]
enum Commands {
    Issue(issue::Args),
+
    Unfollow(unfollow::Args),
}

#[derive(Debug)]
@@ -270,11 +271,9 @@ fn run_other(exe: &str, args: &[OsString]) -> Result<(), Option<anyhow::Error>>
            );
        }
        "unfollow" => {
-
            term::run_command_args::<unfollow::Options, _>(
-
                unfollow::HELP,
-
                unfollow::run,
-
                args.to_vec(),
-
            );
+
            if let Some(Commands::Unfollow(args)) = CliArgs::parse().command {
+
                term::run_command_fn(unfollow::run, args);
+
            }
        }
        "unseed" => {
            term::run_command_args::<unseed::Options, _>(unseed::HELP, unseed::run, args.to_vec());