Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Allow unseed to use name
◌ CI pending Pavan Kumar Sunkara committed 1 year ago
commit f88df71c776f6938913b45328a047d0f17738faa
parent e130b4dc06ca02a035519e1ea86ffeafc788866f
1 pending (1 total) View logs
1 file changed +43 -7
modified radicle-cli/src/commands/unseed.rs
@@ -1,3 +1,4 @@
+
use std::collections::HashMap;
use std::ffi::OsString;

use anyhow::anyhow;
@@ -14,7 +15,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad unseed <rid> [<option>...]
+
    rad unseed <name|rid> [<option>...]

    The `unseed` command removes the seeding policy, if found,
    for the given repository.
@@ -27,7 +28,7 @@ Options

#[derive(Debug)]
pub struct Options {
-
    rid: RepoId,
+
    id: OsString,
}

impl Args for Options {
@@ -35,12 +36,12 @@ impl Args for Options {
        use lexopt::prelude::*;

        let mut parser = lexopt::Parser::from_args(args);
-
        let mut rid: Option<RepoId> = None;
+
        let mut id: Option<OsString> = None;

        while let Some(arg) = parser.next()? {
            match &arg {
                Value(val) => {
-
                    rid = Some(term::args::rid(val)?);
+
                    id = Some(val.into());
                }
                Long("help") | Short('h') => {
                    return Err(Error::Help.into());
@@ -53,8 +54,8 @@ impl Args for Options {

        Ok((
            Options {
-
                rid: rid.ok_or(anyhow!(
-
                    "A Repository ID must be provided; see `rad unseed --help`"
+
                id: id.ok_or(anyhow!(
+
                    "A Repository ID or name must be provided; see `rad unseed --help`"
                ))?,
            },
            vec![],
@@ -66,7 +67,42 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let profile = ctx.profile()?;
    let mut node = radicle::Node::new(profile.socket());

-
    delete(options.rid, &mut node, &profile)?;
+
    // If given a radicle ID, use it directly
+
    let rid = term::args::rid(&options.id).or_else(|err| {
+
        let name = options.id.to_string_lossy();
+
        let storage = &profile.storage;
+
        let repos = storage.repositories()?;
+

+
        // Collect the names of the repositories
+
        let names = repos
+
            .iter()
+
            .filter_map(|repo| match repo.doc.project() {
+
                Ok(p) => Some((p.name().to_owned(), repo.rid)),
+
                Err(_) => None,
+
            })
+
            .collect::<HashMap<_, _>>();
+

+
        if names.contains_key(name.as_ref()) {
+
            let rids = names
+
                .iter()
+
                .filter_map(|(key, rid)| (name == *key).then_some(rid))
+
                .collect::<Vec<_>>();
+

+
            // If there are multiple repositories with the same name, it's ambiguous
+
            if rids.len() > 1 {
+
                return Err(anyhow!(
+
                    "name '{}' matches more than one Repository; use Repository ID instead",
+
                    name
+
                ));
+
            }
+

+
            return Ok(rids[0].clone());
+
        }
+

+
        return Err(err);
+
    })?;
+

+
    delete(rid, &mut node, &profile)?;

    Ok(())
}