Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: accept from the cli the remote subcommand
Vincenzo Palazzo committed 3 years ago
commit d55861572d21d6a055efebe535152244ce238fd3
parent fb44af965324634cb741c40118abb80db004b2a0
2 files changed +123 -0
modified radicle-cli/src/commands/help.rs
@@ -39,6 +39,7 @@ const COMMANDS: &[Help] = &[
    rad_unassign::HELP,
    rad_untag::HELP,
    rad_untrack::HELP,
+
    rad_remote::HELP,
];

#[derive(Default)]
added radicle-cli/src/commands/remote.rs
@@ -0,0 +1,122 @@
+
//! Remote Command implementation
+
#[path = "remote/add.rs"]
+
pub mod add;
+
#[path = "remote/list.rs"]
+
pub mod list;
+
#[path = "remote/rm.rs"]
+
pub mod rm;
+

+
use std::ffi::OsString;
+

+
use anyhow::anyhow;
+

+
use radicle::prelude::NodeId;
+

+
use crate::terminal::args::{self, string, Error};
+
use crate::terminal::{Args, Context, Help};
+

+
pub const HELP: Help = Help {
+
    name: "remote",
+
    description: "Manage a project's remotes",
+
    version: env!("CARGO_PKG_VERSION"),
+
    usage: r#"
+
Usage
+

+
    rad remote
+
    rad remote list
+
    rad remote add (<did> | <nid>) [--name <string>]
+
    rad remote rm <name>
+

+
Options
+

+
    --name      Override the name of the remote that by default is set to the node alias
+
    --help      Print help
+
"#,
+
};
+

+
#[derive(Debug, Default, PartialEq, Eq)]
+
pub enum OperationName {
+
    Add,
+
    Rm,
+
    #[default]
+
    List,
+
}
+

+
#[derive(Debug)]
+
pub enum Operation {
+
    Add { id: NodeId, name: Option<String> },
+
    Rm { name: String },
+
    List,
+
}
+

+
#[derive(Debug)]
+
pub struct Options {
+
    pub op: Operation,
+
}
+

+
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 op: Option<OperationName> = None;
+
        let mut id: Option<NodeId> = None;
+
        let mut name: Option<String> = None;
+

+
        while let Some(arg) = parser.next()? {
+
            match arg {
+
                Long("help") => {
+
                    return Err(Error::Help.into());
+
                }
+
                Long("name") | Short('n') => {
+
                    let value = parser.value()?;
+
                    let value = string(&value);
+
                    name = Some(value);
+
                }
+
                Value(val) if op.is_none() => match val.to_string_lossy().as_ref() {
+
                    "a" | "add" => op = Some(OperationName::Add),
+
                    "l" | "list" => op = Some(OperationName::List),
+
                    "r" | "rm" => op = Some(OperationName::Rm),
+
                    unknown => anyhow::bail!("unknown operation '{}'", unknown),
+
                },
+
                Value(val) if op == Some(OperationName::Add) && id.is_none() => {
+
                    let nid = args::pubkey(&val)?;
+
                    id = Some(nid);
+
                }
+
                Value(val) if op == Some(OperationName::Rm) && name.is_none() => {
+
                    let val = string(&val);
+
                    name = Some(val);
+
                }
+
                _ => return Err(anyhow::anyhow!(arg.unexpected())),
+
            }
+
        }
+

+
        let op = match op.unwrap_or_default() {
+
            OperationName::Add => Operation::Add {
+
                id: id.ok_or(anyhow!(
+
                    "`DID` required, try running `rad remote add <did>`"
+
                ))?,
+
                name,
+
            },
+
            OperationName::List => Operation::List,
+
            OperationName::Rm => Operation::Rm {
+
                name: name.ok_or(anyhow!("name required, see `rad remote`"))?,
+
            },
+
        };
+

+
        Ok((Options { op }, vec![]))
+
    }
+
}
+

+
pub fn run(options: Options, ctx: impl Context) -> anyhow::Result<()> {
+
    let (working, rid) = radicle::rad::cwd()
+
        .map_err(|_| anyhow!("this command must be run in the context of a project"))?;
+
    let profile = ctx.profile()?;
+

+
    match options.op {
+
        Operation::Add { ref id, name } => self::add::run(&working, &profile, id, name, rid)?,
+
        Operation::Rm { ref name } => self::rm::run(&working, name)?,
+
        Operation::List => self::list::run(&working)?,
+
    };
+
    Ok(())
+
}