Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Unify format of help messages
xphoniex committed 3 years ago
commit 414477a31676d5e75efa7f3e8dc6624bcf2b2e52
parent 992e94ebe4125513e4587ef4ecc00b8ef2247b1e
38 files changed +159 -177
modified radicle-cli/examples/rad-auth.md
@@ -18,7 +18,7 @@ You can get the above information at all times using the `self` command:
```
$ rad self
DID            did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Node ID        z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
Node ID (NID)  z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
Key (hash)     SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA
Key (full)     ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1
Storage (git)  [..]/storage
modified radicle-cli/examples/rad-self.md
@@ -4,7 +4,7 @@ device and node.
```
$ rad self
DID            did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Node ID        z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
Node ID (NID)  z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
Key (hash)     SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA
Key (full)     ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1
Storage (git)  [..]
modified radicle-cli/src/commands/assign.rs
@@ -2,14 +2,15 @@ use std::ffi::OsString;

use anyhow::anyhow;
use nonempty::NonEmpty;
+

+
use radicle::cob;
+
use radicle::cob::issue;
use radicle::prelude::Did;
+
use radicle::storage::WriteStorage;

use crate::git::Rev;
use crate::terminal as term;
use crate::terminal::args::{string, Args, Error, Help};
-
use radicle::cob;
-
use radicle::cob::issue;
-
use radicle::storage::WriteStorage;

pub const HELP: Help = Help {
    name: "assign",
@@ -18,14 +19,15 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad assign <issue> --to <did>
+
    rad assign <issue-id> --to <did> [<option>...]

    To assign multiple users to an issue, you may repeat
    the `--to` option.

+
    --to <did>    Assignee to add to the issue
+

Options

-
    --to <did>    Assignee to add to the issue
    --help        Print help
"#,
};
modified radicle-cli/src/commands/auth.rs
@@ -18,10 +18,10 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad auth [<options>...]
+
    rad auth [<option>...]

    A passphrase may be given via the environment variable `RAD_PASSPHRASE` or
-
    via the standard input stream if `--stdin` is used. Using one of these
+
    via the standard input stream if `--stdin` is used. Using either of these
    methods disables the passphrase prompt.

Options
modified radicle-cli/src/commands/checkout.rs
@@ -6,7 +6,6 @@ use anyhow::Context as _;

use radicle::prelude::*;
use radicle::storage::git::transport;
-
use radicle::storage::RemoteId;

use crate::project;
use crate::terminal as term;
@@ -19,11 +18,11 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad checkout <id> [<option>...]
+
    rad checkout <rid> [--remote <did>] [<option>...]

Options

-
    --remote <id>   Remote namespace to checkout
+
    --remote <did>  Remote peer to checkout
    --no-confirm    Don't ask for confirmation during checkout
    --help          Print help
"#,
@@ -31,13 +30,12 @@ Options

pub struct Options {
    pub id: Id,
-
    pub remote: Option<RemoteId>,
+
    pub remote: Option<Did>,
}

impl Args for Options {
    fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
        use lexopt::prelude::*;
-
        use std::str::FromStr;

        let mut parser = lexopt::Parser::from_args(args);
        let mut id = None;
@@ -51,13 +49,7 @@ impl Args for Options {
                Long("help") => return Err(Error::Help.into()),
                Long("remote") => {
                    let val = parser.value().unwrap();
-
                    let val = val.to_string_lossy();
-

-
                    if let Ok(val) = NodeId::from_str(&val) {
-
                        remote = Some(val);
-
                    } else {
-
                        return Err(anyhow!("invalid Node ID '{}'", val));
-
                    }
+
                    remote = Some(term::args::did(&val)?);
                }
                Value(val) if id.is_none() => {
                    id = Some(term::args::rid(&val)?);
@@ -68,7 +60,7 @@ impl Args for Options {

        Ok((
            Options {
-
                id: id.ok_or_else(|| anyhow!("a project id to checkout must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a project to checkout must be provided"))?,
                remote,
            },
            vec![],
@@ -91,7 +83,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
pub fn execute(options: Options, profile: &Profile) -> anyhow::Result<PathBuf> {
    let id = options.id;
    let storage = &profile.storage;
-
    let remote = options.remote.unwrap_or(*profile.id());
+
    let remote = options.remote.unwrap_or(profile.did());
    let doc = storage
        .repository(id)?
        .identity_doc_of(&remote)
modified radicle-cli/src/commands/clone.rs
@@ -83,9 +83,8 @@ impl Args for Options {
                _ => return Err(anyhow!(arg.unexpected())),
            }
        }
-
        let id = id.ok_or_else(|| {
-
            anyhow!("to clone, a radicle id must be provided; see `rad clone --help`")
-
        })?;
+
        let id =
+
            id.ok_or_else(|| anyhow!("to clone, an RID must be provided; see `rad clone --help`"))?;

        Ok((
            Options {
modified radicle-cli/src/commands/comment.rs
@@ -78,7 +78,8 @@ impl Args for Options {

        Ok((
            Options {
-
                id: id.ok_or_else(|| anyhow!("an issue id to comment on must be provided"))?,
+
                id: id
+
                    .ok_or_else(|| anyhow!("an issue or patch to comment on must be provided"))?,
                message,
                reply_to,
            },
modified radicle-cli/src/commands/delegate.rs
@@ -22,8 +22,9 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad delegate (add|remove) <did> [--to <id>]
-
    rad delegate list [<id>]
+
    rad delegate add <did> [--to <rid>] [<option>...]
+
    rad delegate remove <did> [--to <rid>] [<option>...]
+
    rad delegate list [<rid>] [<option>...]

    The `add` and `remove` commands are limited to managing delegates
    where the `threshold` for the quorum is exactly `1`. Otherwise,
@@ -124,5 +125,5 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {

fn get_id(id: Option<Id>) -> anyhow::Result<Id> {
    id.or_else(|| radicle::rad::cwd().ok().map(|(_, id)| id))
-
        .context("Couldn't get ID from either command line or cwd")
+
        .context("Couldn't get the RID from either command line or cwd")
}
modified radicle-cli/src/commands/delegate/add.rs
@@ -1,4 +1,5 @@
use anyhow::Context as _;
+

use radicle::{
    prelude::{Did, Id},
    storage::{WriteRepository as _, WriteStorage},
@@ -17,7 +18,7 @@ where

    let mut project = storage
        .get(&profile.public_key, id)?
-
        .context("No project with such ID exists")?;
+
        .context("No project with the given RID exists")?;

    let repo = storage.repository_mut(id)?;

modified radicle-cli/src/commands/delegate/list.rs
@@ -1,4 +1,5 @@
use anyhow::Context as _;
+

use radicle::{prelude::Id, storage::ReadStorage, Profile};

use crate::terminal as term;
@@ -9,7 +10,7 @@ where
{
    let project = storage
        .get(&profile.public_key, id)?
-
        .context("No project with such ID exists")?;
+
        .context("No project with the given RID exists")?;

    term::info!("{}", serde_json::to_string_pretty(&project.delegates)?);
    Ok(())
modified radicle-cli/src/commands/delegate/remove.rs
@@ -1,4 +1,5 @@
use anyhow::Context as _;
+

use radicle::{
    prelude::Id,
    storage::{WriteRepository as _, WriteStorage},
@@ -17,7 +18,7 @@ where

    let mut project = storage
        .get(&profile.public_key, id)?
-
        .context("No project with such ID exists")?;
+
        .context("No project with the given RID exists")?;

    let repo = storage.repository_mut(id)?;

modified radicle-cli/src/commands/edit.rs
@@ -15,9 +15,9 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad edit [<id>] [<option>...]
+
    rad edit [<rid>] [<option>...]

-
    Edits the identity document pointed to by the ID. If it isn't specified,
+
    Edits the identity document pointed to by the RID. If it isn't specified,
    the current project is edited.

Options
@@ -62,11 +62,11 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let id = options
        .id
        .or_else(|| radicle::rad::cwd().ok().map(|(_, id)| id))
-
        .context("Couldn't get ID from either command line or cwd")?;
+
        .context("Couldn't get RID from either command line or cwd")?;

    let mut project = storage
        .get(signer.public_key(), id)?
-
        .context("No project with such ID exists")?;
+
        .context("No project with the given RID exists")?;

    let repo = storage.repository(id)?;

modified radicle-cli/src/commands/fetch.rs
@@ -82,7 +82,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        Some(rid) => rid,
        None => {
            let (_, rid) = radicle::rad::repo(Path::new("."))
-
                .context("Current directory is not a Radicle project")?;
+
                .context("Current directory is not a radicle project")?;

            rid
        }
modified radicle-cli/src/commands/id.rs
@@ -1,6 +1,7 @@
use std::{ffi::OsString, str::FromStr as _};

use anyhow::{anyhow, Context as _};
+

use radicle::cob::identity::{self, Proposal, Proposals, Revision, RevisionId};
use radicle::git::Oid;
use radicle::identity::Identity;
@@ -23,14 +24,14 @@ Usage

    rad id (update|edit) [--title|-t] [--description|-d]
                         [--delegates <did>] [--threshold <num>]
-
                         [--no-confirm]
-
    rad id list
-
    rad id (show|rebase) <id> [--rev <revision id>]
-
    rad id show <id> [--rev <revision id>] [--revisions]
-
    rad id (accept|reject|close|commit) [--rev <revision id>] [--no-confirm]
+
                         [--no-confirm] [<option>...]
+
    rad id list [<option>...]
+
    rad id rebase <id> [--rev <revision-id>] [<option>...]
+
    rad id show <id> [--rev <revision-id>] [--revisions] [<option>...]
+
    rad id (accept|reject|close|commit) [--rev <revision-id>] [--no-confirm] [<option>...]

Options
-
        --help                 Print help
+
    --help                 Print help
"#,
};

@@ -160,7 +161,7 @@ impl Args for Options {
                    let val = String::from(parser.value()?.to_string_lossy());
                    rev = Some(
                        RevisionId::from_str(&val)
-
                            .map_err(|_| anyhow!("invalid revision id '{}'", val))?,
+
                            .map_err(|_| anyhow!("invalid revision '{}'", val))?,
                    );
                }
                Long("delegates") => {
@@ -185,11 +186,11 @@ impl Args for Options {

        let op = match op.unwrap_or_default() {
            OperationName::Accept => Operation::Accept {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
                rev,
            },
            OperationName::Reject => Operation::Reject {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
                rev,
            },
            OperationName::Edit => Operation::Edit {
@@ -199,7 +200,7 @@ impl Args for Options {
                threshold,
            },
            OperationName::Update => Operation::Update {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
                rev,
                title,
                description,
@@ -207,21 +208,21 @@ impl Args for Options {
                threshold,
            },
            OperationName::Rebase => Operation::Rebase {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
                rev,
            },
            OperationName::Show => Operation::Show {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
                rev,
                show_revisions,
            },
            OperationName::List => Operation::List,
            OperationName::Commit => Operation::Commit {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
                rev,
            },
            OperationName::Close => Operation::Close {
-
                id: id.ok_or_else(|| anyhow!("a proposal id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a proposal must be provided"))?,
            },
        };
        Ok((Options { op, interactive }, vec![]))
modified radicle-cli/src/commands/init.rs
@@ -5,18 +5,18 @@ use std::ffi::OsString;
use std::path::PathBuf;

use anyhow::{anyhow, bail, Context as _};
+
use serde_json as json;

use radicle::crypto::ssh;
use radicle::git::RefString;
use radicle::node::tracking::Scope;
use radicle::node::{Handle, NodeId};
+
use radicle::profile;

use crate::git;
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
use crate::terminal::Interactive;
-
use radicle::profile;
-
use serde_json as json;

pub const HELP: Help = Help {
    name: "init",
modified radicle-cli/src/commands/inspect.rs
@@ -25,7 +25,7 @@ Usage

    rad inspect <path> [<option>...]
    rad inspect <rid>  [<option>...]
-
    rad inspect
+
    rad inspect [<option>...]

    Inspects the given path or RID. If neither is specified,
    the current repository is inspected.
@@ -88,9 +88,9 @@ impl Args for Options {
                    } else if let Ok(val) = PathBuf::from_str(&val) {
                        id = radicle::rad::repo(val)
                            .map(|(_, id)| Some(id))
-
                            .context("Supplied argument is not a valid `path`")?;
+
                            .context("Supplied argument is not a valid path")?;
                    } else {
-
                        return Err(anyhow!("invalid `path` or `id` '{}'", val));
+
                        return Err(anyhow!("invalid path or RID '{}'", val));
                    }
                }
                _ => return Err(anyhow::anyhow!(arg.unexpected())),
@@ -106,7 +106,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        Some(id) => id,
        None => {
            let (_, id) = radicle::rad::repo(Path::new("."))
-
                .context("Current directory is not a Radicle project")?;
+
                .context("Current directory is not a radicle project")?;

            id
        }
@@ -122,7 +122,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let signer = term::signer(&profile)?;
    let project = storage
        .get(signer.public_key(), id)?
-
        .context("No project with such `id` exists")?;
+
        .context("No project with the given RID exists")?;

    match options.target {
        Target::Refs => {
modified radicle-cli/src/commands/issue.rs
@@ -3,20 +3,20 @@ use std::ffi::OsString;
use std::str::FromStr;

use anyhow::{anyhow, Context as _};
+

+
use radicle::cob::common::{Reaction, Tag};
+
use radicle::cob::issue;
+
use radicle::cob::issue::{CloseReason, Issues, State};
use radicle::node::Handle;
use radicle::prelude::Did;
+
use radicle::storage::WriteStorage;
+
use radicle::{cob, Node};

use crate::git::Rev;
use crate::terminal as term;
use crate::terminal::args::{string, Args, Error, Help};
use crate::terminal::Element;

-
use radicle::cob::common::{Reaction, Tag};
-
use radicle::cob::issue;
-
use radicle::cob::issue::{CloseReason, Issues, State};
-
use radicle::storage::WriteStorage;
-
use radicle::{cob, Node};
-

pub const HELP: Help = Help {
    name: "issue",
    description: "Manage issues",
@@ -24,13 +24,13 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad issue
-
    rad issue delete <id>
-
    rad issue list [--assigned <did>]
-
    rad issue open [--title <title>] [--description <text>]
-
    rad issue react <id> [--emoji <char>]
-
    rad issue show <id>
-
    rad issue state <id> [--closed | --open | --solved]
+
    rad issue [<option>...]
+
    rad issue delete <issue-id> [<option>...]
+
    rad issue list [--assigned <did>] [<option>...]
+
    rad issue open [--title <title>] [--description <text>] [<option>...]
+
    rad issue react <issue-id> [--emoji <char>] [<option>...]
+
    rad issue show <issue-id> [<option>...]
+
    rad issue state <issue-id> [--closed | --open | --solved] [<option>...]

Options

@@ -174,18 +174,18 @@ impl Args for Options {
        let op = match op.unwrap_or_default() {
            OperationName::Open => Operation::Open { title, description },
            OperationName::Show => Operation::Show {
-
                id: id.ok_or_else(|| anyhow!("an issue id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("an issue must be provided"))?,
            },
            OperationName::State => Operation::State {
-
                id: id.ok_or_else(|| anyhow!("an issue id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("an issue must be provided"))?,
                state: state.ok_or_else(|| anyhow!("a state operation must be provided"))?,
            },
            OperationName::React => Operation::React {
-
                id: id.ok_or_else(|| anyhow!("an issue id must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("an issue must be provided"))?,
                reaction: reaction.ok_or_else(|| anyhow!("a reaction emoji must be provided"))?,
            },
            OperationName::Delete => Operation::Delete {
-
                id: id.ok_or_else(|| anyhow!("an issue id to remove must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("an issue to remove must be provided"))?,
            },
            OperationName::List => Operation::List { assigned },
        };
modified radicle-cli/src/commands/ls.rs
@@ -1,9 +1,10 @@
use std::ffi::OsString;

+
use radicle::storage::{ReadRepository, ReadStorage};
+

use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};

-
use radicle::storage::{ReadRepository, ReadStorage};
use term::Element;

pub const HELP: Help = Help {
modified radicle-cli/src/commands/merge.rs
@@ -4,14 +4,15 @@ use std::fmt::Write;

use anyhow::{anyhow, Context};

-
use crate::git::Rev;
-
use crate::terminal as term;
-
use crate::terminal::args::{string, Args, Error, Help};
use radicle::cob::patch::{Patch, PatchId, Patches};
use radicle::git;
use radicle::prelude::*;
use radicle::rad;

+
use crate::git::Rev;
+
use crate::terminal as term;
+
use crate::terminal::args::{string, Args, Error, Help};
+

pub const HELP: Help = Help {
    name: "merge",
    description: "Merge a patch",
@@ -106,7 +107,7 @@ impl Args for Options {
        }

        let revision_id =
-
            revision_id.ok_or_else(|| anyhow!("a revision id to merge must be provided"))?;
+
            revision_id.ok_or_else(|| anyhow!("a revision to merge must be provided"))?;

        Ok((
            Options {
modified radicle-cli/src/commands/node.rs
@@ -1,6 +1,7 @@
use std::ffi::OsString;

use anyhow::anyhow;
+

use radicle::node::{Address, Node, NodeId, ROUTING_DB_FILE, TRACKING_DB_FILE};

use crate::terminal as term;
@@ -20,11 +21,12 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad node status
-
    rad node (start|stop)
-
    rad node connect <nid> <addr>
-
    rad node routing
-
    rad node tracking [--repos|--nodes]
+
    rad node status [<option>...]
+
    rad node start [<option>...]
+
    rad node stop [<option>...]
+
    rad node connect <nid> <addr> [<option>...]
+
    rad node routing [<option>...]
+
    rad node tracking [--repos|--nodes] [<option>...]

Options

@@ -115,7 +117,7 @@ impl Args for Options {

        let op = match op.unwrap_or_default() {
            OperationName::Connect => Operation::Connect {
-
                nid: nid.ok_or_else(|| anyhow!("a NID must be provided"))?,
+
                nid: nid.ok_or_else(|| anyhow!("an NID must be provided"))?,
                addr: addr.ok_or_else(|| anyhow!("an address must be provided"))?,
            },
            OperationName::Routing => Operation::Routing,
modified radicle-cli/src/commands/patch.rs
@@ -34,13 +34,13 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad patch
-
    rad patch list [--all|--merged|--open|--archived]
-
    rad patch show <id>
+
    rad patch [<option>...]
+
    rad patch list [--all|--merged|--open|--archived] [<option>...]
+
    rad patch show <patch-id> [<option>...]
    rad patch open [<option>...]
-
    rad patch update <id> [<option>...]
-
    rad patch checkout <id>
-
    rad patch delete <id>
+
    rad patch update <patch-id> [<option>...]
+
    rad patch checkout <patch-id> [<option>...]
+
    rad patch delete <patch-id> [<option>...]

Create/Update options

@@ -196,14 +196,14 @@ impl Args for Options {
            OperationName::Open => Operation::Open { message },
            OperationName::List => Operation::List { filter },
            OperationName::Show => Operation::Show {
-
                patch_id: patch_id.ok_or_else(|| anyhow!("a patch id must be provided"))?,
+
                patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
            },
            OperationName::Delete => Operation::Delete {
-
                patch_id: patch_id.ok_or_else(|| anyhow!("a patch id must be provided"))?,
+
                patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
            },
            OperationName::Update => Operation::Update { patch_id, message },
            OperationName::Checkout => Operation::Checkout {
-
                patch_id: patch_id.ok_or_else(|| anyhow!("a patch id must be provided"))?,
+
                patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
            },
        };

modified radicle-cli/src/commands/patch/delete.rs
@@ -1,9 +1,9 @@
-
use super::*;
-

use radicle::cob::patch;
use radicle::prelude::*;
use radicle::storage::git::Repository;

+
use super::*;
+

pub fn run(repository: &Repository, profile: &Profile, patch_id: &PatchId) -> anyhow::Result<()> {
    let signer = &term::signer(profile)?;
    let patches = patch::Patches::open(repository)?;
modified radicle-cli/src/commands/patch/show.rs
@@ -1,8 +1,5 @@
use std::process;

-
use super::common::*;
-
use super::*;
-

use radicle::cob::patch;
use radicle::git;
use radicle::storage::git::Repository;
@@ -13,6 +10,9 @@ use radicle_term::{

use crate::terminal as term;

+
use super::common::*;
+
use super::*;
+

fn show_patch_diff(
    patch: &patch::Patch,
    storage: &Repository,
modified radicle-cli/src/commands/path.rs
@@ -2,6 +2,7 @@
use std::ffi::OsString;

use anyhow::anyhow;
+

use radicle::profile;

use crate::terminal as term;
@@ -14,9 +15,9 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad path [--help]
+
    rad path [<option>...]

-
    If no argument is specified, the radicle "home" path is displayed.
+
    If no argument is specified, the radicle home path is displayed.

Options

modified radicle-cli/src/commands/push.rs
@@ -1,13 +1,13 @@
use std::ffi::OsString;
use std::path::Path;

+
use anyhow::anyhow;
+

use radicle::git;

use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};

-
use anyhow::anyhow;
-

pub const HELP: Help = Help {
    name: "push",
    description: "Publish a project to the network",
@@ -15,7 +15,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad push [--all] [<option>...]
+
    rad push [<option>...]

    By default, only the current branch is pushed.

modified radicle-cli/src/commands/review.rs
@@ -19,7 +19,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad review [<id>] [--accept|--reject] [-m [<string>]] [<option>...]
+
    rad review [<patch-id>] [--accept|--reject] [-m [<string>]] [<option>...]

    To specify a patch to review, use the fully qualified patch id
    or an unambiguous prefix of it.
@@ -118,7 +118,7 @@ impl Args for Options {

        Ok((
            Options {
-
                id: id.ok_or_else(|| anyhow!("a patch id to review must be provided"))?,
+
                id: id.ok_or_else(|| anyhow!("a patch to review must be provided"))?,
                message,
                sync,
                confirm,
modified radicle-cli/src/commands/rm.rs
@@ -17,7 +17,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad rm <id> [<option>...]
+
    rad rm <rid> [<option>...]

    Removes a project from storage.

@@ -59,7 +59,7 @@ impl Args for Options {

        Ok((
            Options {
-
                id: id.ok_or_else(|| anyhow!("an `id` must be provided; see `rad rm --help`"))?,
+
                id: id.ok_or_else(|| anyhow!("an RID must be provided; see `rad rm --help`"))?,
                confirm,
            },
            vec![],
modified radicle-cli/src/commands/self.rs
@@ -18,7 +18,7 @@ Usage

Options

-
    --nid                Show your Node ID
+
    --nid                Show your Node ID (NID)
    --did                Show your DID
    --ssh-key            Show your public key in OpenSSH format
    --ssh-fingerprint    Show your public key fingerprint in OpenSSH format
@@ -110,7 +110,7 @@ fn all(profile: &Profile) -> anyhow::Result<()> {

    let node_id = profile.id();
    table.push([
-
        term::format::style("Node ID").to_string(),
+
        term::format::style("Node ID (NID)").to_string(),
        term::format::tertiary(node_id).to_string(),
    ]);

modified radicle-cli/src/commands/tag.rs
@@ -4,14 +4,15 @@ use std::str::FromStr;
use anyhow::anyhow;
use nonempty::NonEmpty;

-
use crate::terminal as term;
-
use crate::terminal::args::{Args, Error, Help};
use radicle::cob;
use radicle::cob::common::Tag;
use radicle::cob::{issue, patch, store};
use radicle::crypto::Signer;
use radicle::storage::{self, WriteStorage};

+
use crate::terminal as term;
+
use crate::terminal::args::{Args, Error, Help};
+

pub const HELP: Help = Help {
    name: "tag",
    description: "Tag an issue or patch",
@@ -19,7 +20,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad tag <id> <tag>..
+
    rad tag <issue-id> <tag>... [<option>...]

Options

@@ -47,11 +48,7 @@ impl Args for Options {
                    return Err(Error::Help.into());
                }
                Value(ref val) if id.is_none() => {
-
                    let val = val.to_string_lossy();
-
                    let Ok(val) = cob::ObjectId::from_str(&val) else {
-
                        return Err(anyhow!("invalid issue or patch ID '{}'", val));
-
                    };
-
                    id = Some(val);
+
                    id = Some(term::args::cob(val)?);
                }
                Value(ref val) if id.is_some() => {
                    let s: String = val.parse()?;
modified radicle-cli/src/commands/track.rs
@@ -16,8 +16,8 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad track <did> [--[no-]fetch] [--alias <name>]
-
    rad track <rid> [--[no-]fetch] [--scope <scope>]
+
    rad track <did> [--[no-]fetch] [--alias <name>] [<option>...]
+
    rad track <rid> [--[no-]fetch] [--scope <scope>] [<option>...]

    The `track` command takes either a DID or an RID. Based on the argument, it will
    either update the tracking policy of a node (DID), or a repository (RID).
modified radicle-cli/src/commands/unassign.rs
@@ -1,16 +1,16 @@
use std::ffi::OsString;
-
use std::str::FromStr;

use anyhow::anyhow;
use nonempty::NonEmpty;
-
use radicle::prelude::Did;

-
use crate::terminal as term;
-
use crate::terminal::args::{Args, Error, Help};
use radicle::cob;
use radicle::cob::issue;
+
use radicle::prelude::Did;
use radicle::storage::WriteStorage;

+
use crate::terminal as term;
+
use crate::terminal::args::{Args, Error, Help};
+

pub const HELP: Help = Help {
    name: "unassign",
    description: "Unassign an issue",
@@ -18,14 +18,15 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad unassign <issue> --from <did>
+
    rad unassign <issue-id> --from <did> [<option>...]

    To unassign multiple users from an issue, you may repeat
    the `--from` option.

+
    --from <did>     Assignee to remove from the issue
+

Options

-
    --from <did>     Assignee to remove from the issue
    --help           Print help
"#,
};
@@ -56,11 +57,7 @@ impl Args for Options {
                    from.push(did);
                }
                Value(ref val) if id.is_none() => {
-
                    let val = val.to_string_lossy();
-
                    let Ok(val) = issue::IssueId::from_str(&val) else {
-
                        return Err(anyhow!("invalid Issue ID '{}'", val));
-
                    };
-
                    id = Some(val);
+
                    id = Some(term::args::issue(val)?);
                }
                _ => {
                    return Err(anyhow!(arg.unexpected()));
modified radicle-cli/src/commands/untag.rs
@@ -4,14 +4,15 @@ use std::str::FromStr;
use anyhow::anyhow;
use nonempty::NonEmpty;

-
use crate::terminal as term;
-
use crate::terminal::args::{Args, Error, Help};
use radicle::cob;
use radicle::cob::common::Tag;
use radicle::cob::{issue, patch, store};
use radicle::crypto::Signer;
use radicle::storage::{self, WriteStorage};

+
use crate::terminal as term;
+
use crate::terminal::args::{Args, Error, Help};
+

pub const HELP: Help = Help {
    name: "untag",
    description: "Untag an issue or patch",
@@ -19,7 +20,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad untag <id> <tag>..
+
    rad untag <cob-id> <tag>... [<option>...]

Options

@@ -47,11 +48,7 @@ impl Args for Options {
                    return Err(Error::Help.into());
                }
                Value(ref val) if id.is_none() => {
-
                    let val = val.to_string_lossy();
-
                    let Ok(val) = cob::ObjectId::from_str(&val) else {
-
                        return Err(anyhow!("invalid issue or patch ID '{}'", val));
-
                    };
-
                    id = Some(val);
+
                    id = Some(term::args::cob(val)?);
                }
                Value(ref val) if id.is_some() => {
                    let s: String = val.parse()?;
modified radicle-cli/src/commands/untrack.rs
@@ -17,7 +17,7 @@ pub const HELP: Help = Help {
    usage: r#"
Usage

-
    rad untrack [<id>]
+
    rad untrack [<rid>] [<option>...]

Options

@@ -45,7 +45,7 @@ impl Args for Options {
                    if let Ok(val) = Id::from_urn(&val) {
                        id = Some(val);
                    } else {
-
                        return Err(anyhow!("invalid ID '{}'", val));
+
                        return Err(anyhow!("invalid RID '{}'", val));
                    }
                }
                Long("help") => {
@@ -65,7 +65,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
    let id = options
        .id
        .or_else(|| radicle::rad::cwd().ok().map(|(_, id)| id))
-
        .context("current directory is not a git repository; please supply an `<id>`")?;
+
        .context("current directory is not a git repository; please supply an RID")?;
    let profile = ctx.profile()?;
    let storage = &profile.storage;
    let project = storage.repository(id)?.project_of(profile.id())?;
modified radicle-cli/src/commands/web.rs
@@ -1,9 +1,10 @@
use std::ffi::OsString;

use anyhow::anyhow;
-
use radicle::crypto::{PublicKey, Signature, Signer};
use serde::{Deserialize, Serialize};

+
use radicle::crypto::{PublicKey, Signature, Signer};
+

use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};

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

-
    rad web [<options>...]
+
    rad web [<option>...]

Options

modified radicle-cli/src/terminal.rs
@@ -1,6 +1,5 @@
pub mod args;
pub use args::{Args, Error, Help};
-
pub mod cob;
pub mod format;
pub mod io;
pub use io::{proposal, signer};
modified radicle-cli/src/terminal/args.rs
@@ -2,6 +2,8 @@ use std::ffi::OsString;
use std::str::FromStr;

use anyhow::anyhow;
+

+
use radicle::cob::{self, issue, patch};
use radicle::crypto;
use radicle::node::Address;
use radicle::prelude::{Did, Id, NodeId};
@@ -105,3 +107,18 @@ pub fn addr(val: &OsString) -> anyhow::Result<Address> {
pub fn string(val: &OsString) -> String {
    val.to_string_lossy().to_string()
}
+

+
pub fn issue(val: &OsString) -> anyhow::Result<issue::IssueId> {
+
    let val = val.to_string_lossy();
+
    issue::IssueId::from_str(&val).map_err(|_| anyhow!("invalid Issue ID '{}'", val))
+
}
+

+
pub fn patch(val: &OsString) -> anyhow::Result<patch::PatchId> {
+
    let val = val.to_string_lossy();
+
    patch::PatchId::from_str(&val).map_err(|_| anyhow!("invalid Patch ID '{}'", val))
+
}
+

+
pub fn cob(val: &OsString) -> anyhow::Result<cob::ObjectId> {
+
    let val = val.to_string_lossy();
+
    cob::ObjectId::from_str(&val).map_err(|_| anyhow!("invalid Object ID '{}'", val))
+
}
deleted radicle-cli/src/terminal/cob.rs
@@ -1,15 +0,0 @@
-
use std::str::FromStr;
-

-
use super::*;
-
use radicle::cob::patch;
-

-
use anyhow::anyhow;
-

-
pub fn parse_patch_id(val: OsString) -> Result<patch::PatchId, anyhow::Error> {
-
    let val = val
-
        .to_str()
-
        .ok_or_else(|| anyhow!("patch id specified is not UTF-8"))?;
-
    let patch_id =
-
        patch::PatchId::from_str(val).map_err(|_| anyhow!("invalid patch id '{}'", val))?;
-
    Ok(patch_id)
-
}
deleted radicle-term/src/cob.rs
@@ -1,15 +0,0 @@
-
use std::str::FromStr;
-

-
use super::*;
-
use radicle::cob::patch;
-

-
use anyhow::anyhow;
-

-
pub fn parse_patch_id(val: OsString) -> Result<patch::PatchId, anyhow::Error> {
-
    let val = val
-
        .to_str()
-
        .ok_or_else(|| anyhow!("patch id specified is not UTF-8"))?;
-
    let patch_id =
-
        patch::PatchId::from_str(val).map_err(|_| anyhow!("invalid patch id '{}'", val))?;
-
    Ok(patch_id)
-
}