Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
cli: Allow unseed to use repository name
Archived did:key:z6Mks2St...6Xqc opened 1 year ago
  • We try unseeding a repo by it’s name if the given arg is not a valid RID
  • We error out if the name is ambiguous
$ cargo run -- unseed rips
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
     Running `/home/pksunkara/Coding/open/heartwood/target/debug/rad unseed rips`
✓ Seeding policy for rad:z3trNYnLWS11cJWC6BbxDs5niGo82 removed
1 file changed +40 -7 e130b4dc 69e50e1a
modified radicle-cli/src/commands/unseed.rs
@@ -14,7 +14,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 +27,7 @@ Options

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

impl Args for Options {
@@ -35,12 +35,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 +53,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 +66,40 @@ 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 rids of the repositories that match the name
+
        let rids = repos
+
            .iter()
+
            .filter_map(|repo| {
+
                repo.doc
+
                    .project()
+
                    .is_ok_and(|p| p.name() == name)
+
                    .then_some(repo.rid)
+
            })
+
            .collect::<Vec<_>>();
+

+
        // If there are no repositories with the given name, forward the radicle ID parsing error
+
        if rids.is_empty() {
+
            return Err(err);
+
        }
+

+
        // 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]);
+
    })?;
+

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

    Ok(())
}