Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Share common argument types used in `(un)block`
Erik Kundt committed 6 months ago
commit faf19af9de8aea4a24cda72f6f73ab82b3e2db00
parent cef0ff571d1530a2b5a1fafc37cf776b29751b57
3 files changed +69 -41
modified crates/radicle-cli/src/commands/block.rs
@@ -4,7 +4,7 @@ use radicle::node::policy::Policy;

use crate::terminal as term;

-
use args::Target;
+
use term::args::BlockTarget;

pub use args::Args;
pub(crate) use args::ABOUT;
@@ -14,8 +14,8 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
    let mut policies = profile.policies_mut()?;

    let updated = match args.target {
-
        Target::Node(nid) => policies.set_follow_policy(&nid, Policy::Block)?,
-
        Target::Repo(rid) => policies.set_seed_policy(&rid, Policy::Block)?,
+
        BlockTarget::Node(nid) => policies.set_follow_policy(&nid, Policy::Block)?,
+
        BlockTarget::Repo(rid) => policies.set_seed_policy(&rid, Policy::Block)?,
    };
    if updated {
        term::success!("Policy for {} set to 'block'", args.target);
modified crates/radicle-cli/src/commands/block/args.rs
@@ -1,44 +1,9 @@
use clap::Parser;
-
use thiserror::Error;

-
use radicle::prelude::{NodeId, RepoId};
+
use crate::terminal::args::BlockTarget;

pub(crate) const ABOUT: &str = "Block repositories or nodes from being seeded or followed";

-
#[derive(Clone, Debug)]
-
pub(super) enum Target {
-
    Node(NodeId),
-
    Repo(RepoId),
-
}
-

-
#[derive(Debug, Error)]
-
#[error("invalid repository or node specified (RID parsing failed with: '{repo}', NID parsing failed with: '{node}'))")]
-
pub(super) struct ParseTargetError {
-
    repo: radicle::identity::IdError,
-
    node: radicle::crypto::PublicKeyError,
-
}
-

-
impl std::str::FromStr for Target {
-
    type Err = ParseTargetError;
-

-
    fn from_str(val: &str) -> Result<Self, Self::Err> {
-
        val.parse::<RepoId>().map(Target::Repo).or_else(|repo| {
-
            val.parse::<NodeId>()
-
                .map(Target::Node)
-
                .map_err(|node| ParseTargetError { repo, node })
-
        })
-
    }
-
}
-

-
impl std::fmt::Display for Target {
-
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-
        match self {
-
            Self::Node(nid) => nid.fmt(f),
-
            Self::Repo(rid) => rid.fmt(f),
-
        }
-
    }
-
}
-

#[derive(Parser, Debug)]
#[command(about = ABOUT, disable_version_flag = true)]
pub struct Args {
@@ -46,7 +11,7 @@ pub struct Args {
    ///
    /// [example values: rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH, z6MkiswaKJ85vafhffCGBu2gdBsYoDAyHVBWRxL3j297fwS9]
    #[arg(value_name = "RID|NID")]
-
    pub(super) target: Target,
+
    pub(super) target: BlockTarget,
}

#[cfg(test)]
modified crates/radicle-cli/src/terminal/args.rs
@@ -4,8 +4,8 @@ use std::str::FromStr;
use std::time;

use anyhow::anyhow;
-

use clap::builder::TypedValueParser;
+
use thiserror::Error;

use radicle::cob::{self, issue, patch};
use radicle::crypto;
@@ -207,6 +207,43 @@ pub fn cob(val: &OsString) -> anyhow::Result<cob::ObjectId> {
    cob::ObjectId::from_str(&val).map_err(|_| anyhow!("invalid Object ID '{}'", val))
}

+
/// Targets used in the `block` and `unblock` commands
+
#[derive(Clone, Debug)]
+
pub(crate) enum BlockTarget {
+
    Node(NodeId),
+
    Repo(RepoId),
+
}
+

+
#[derive(Debug, Error)]
+
#[error("invalid repository or node specified (RID parsing failed with: '{repo}', NID parsing failed with: '{node}'))")]
+
pub(crate) struct BlockTargetParseError {
+
    repo: radicle::identity::IdError,
+
    node: radicle::crypto::PublicKeyError,
+
}
+

+
impl std::str::FromStr for BlockTarget {
+
    type Err = BlockTargetParseError;
+

+
    fn from_str(val: &str) -> Result<Self, Self::Err> {
+
        val.parse::<RepoId>()
+
            .map(BlockTarget::Repo)
+
            .or_else(|repo| {
+
                val.parse::<NodeId>()
+
                    .map(BlockTarget::Node)
+
                    .map_err(|node| BlockTargetParseError { repo, node })
+
            })
+
    }
+
}
+

+
impl std::fmt::Display for BlockTarget {
+
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+
        match self {
+
            Self::Node(nid) => nid.fmt(f),
+
            Self::Repo(rid) => rid.fmt(f),
+
        }
+
    }
+
}
+

#[derive(Clone, Debug)]
pub(crate) struct ScopeParser;

@@ -231,3 +268,29 @@ impl TypedValueParser for ScopeParser {
        ))
    }
}
+

+
#[cfg(test)]
+
mod test {
+
    use std::str::FromStr;
+

+
    use super::BlockTarget;
+
    use super::BlockTargetParseError;
+

+
    #[test]
+
    fn should_parse_nid() {
+
        let target = BlockTarget::from_str("z6MkiswaKJ85vafhffCGBu2gdBsYoDAyHVBWRxL3j297fwS9");
+
        assert!(target.is_ok())
+
    }
+

+
    #[test]
+
    fn should_parse_rid() {
+
        let target = BlockTarget::from_str("rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH");
+
        assert!(target.is_ok())
+
    }
+

+
    #[test]
+
    fn should_not_parse() {
+
        let err = BlockTarget::from_str("bee").unwrap_err();
+
        assert!(matches!(err, BlockTargetParseError { .. }));
+
    }
+
}