Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Replace manual implementation of clap::ArgGroup
◌ CI pending Matthias Beyer committed 9 months ago
commit 3c581d9df5e24b183e0478f43e3e20f8928d5b14
parent d7f570ade46e19ca8c6abbddc442eae4ddf45554
1 pending (1 total) View logs
2 files changed +23 -22
modified crates/radicle-cli/src/commands/issue.rs
@@ -215,9 +215,8 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
                .context("No issue with the given ID exists")?;
            term::issue::show(&issue, &id, format, args.verbose, &profile)?;
        }
-
        Command::State(state_args) => {
-
            let id = state_args.id.clone();
-
            let to: StateArg = state_args.try_into()?;
+
        Command::State { id, target_state } => {
+
            let to: StateArg = target_state.into();
            let id = id.resolve(&repo.backend)?;
            let signer = term::signer(&profile)?;
            let mut issue = issues.get_mut(&id)?;
modified crates/radicle-cli/src/commands/issue/args.rs
@@ -13,7 +13,6 @@ use radicle::{
    issue::{cache::IssuesExt as _, CloseReason, Issues, State},
    storage::ReadStorage as _,
};
-
use thiserror::Error;

use crate::{git::Rev, terminal::patch::Message};

@@ -207,7 +206,15 @@ pub(crate) enum Command {
    },

    /// Set the state of an issue
-
    State(StateArgs),
+
    State {
+
        /// The issue to be transitioned
+
        #[arg(value_name = "ISSUE_ID", add = ArgValueCompleter::new(hints::issue_ids_completer))]
+
        id: Rev,
+

+
        /// The desired target state
+
        #[clap(flatten)]
+
        target_state: StateArgs,
+
    },
}

impl Default for Command {
@@ -276,37 +283,32 @@ impl From<ListArgs> for Option<State> {

/// Arguments for the [`Command::State`] subcommand.
#[derive(Parser, Debug)]
+
#[group(id = "state", required = true, multiple = false)]
pub(crate) struct StateArgs {
-
    /// The issue to be transitioned
-
    #[arg(value_name = "ISSUE_ID", add = ArgValueCompleter::new(hints::issue_ids_completer))]
-
    pub(crate) id: Rev,
-

    /// Change state to open
    #[arg(long)]
+
    #[arg(group = "state")]
    pub(crate) open: bool,

    /// Change state to closed
    #[arg(long)]
+
    #[arg(group = "state")]
    pub(crate) closed: bool,

    /// Change state to solved
    #[arg(long)]
+
    #[arg(group = "state")]
    pub(crate) solved: bool,
}

-
#[derive(Error, Debug)]
-
#[error("Exactly one of --open, --closed or --solved must be specified")]
-
pub(crate) struct StateArgError;
-

-
impl TryInto<StateArg> for StateArgs {
-
    type Error = StateArgError;
-

-
    fn try_into(self) -> Result<StateArg, Self::Error> {
-
        match (self.open, self.closed, self.solved) {
-
            (true, false, false) => Ok(StateArg::Open),
-
            (false, true, false) => Ok(StateArg::Closed),
-
            (false, false, true) => Ok(StateArg::Solved),
-
            _ => Err(StateArgError),
+
impl From<StateArgs> for StateArg {
+
    fn from(state: StateArgs) -> Self {
+
        // These are mutually exclusive, guaranteed by clap grouping
+
        match (state.open, state.closed, state.solved) {
+
            (true, _, _) => StateArg::Open,
+
            (_, true, _) => StateArg::Closed,
+
            (_, _, true) => StateArg::Solved,
+
            _ => unreachable!(),
        }
    }
}