cli: Unify format of help messages

Signed-off-by: xphoniex <dj.2dixx@gmail.com>
This commit is contained in:
xphoniex 2023-03-16 15:51:51 +00:00 committed by Alexis Sellier
parent 992e94ebe4
commit 414477a316
No known key found for this signature in database
38 changed files with 159 additions and 177 deletions

View File

@ -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

View File

@ -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) [..]

View File

@ -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
"#,
};

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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,
},

View File

@ -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")
}

View File

@ -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)?;

View File

@ -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(())

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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
}

View File

@ -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![]))

View File

@ -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",

View File

@ -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 => {

View File

@ -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 },
};

View File

@ -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 {

View File

@ -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 {

View File

@ -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,

View File

@ -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"))?,
},
};

View File

@ -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)?;

View File

@ -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,

View File

@ -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

View File

@ -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.

View File

@ -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,

View File

@ -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![],

View File

@ -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(),
]);

View File

@ -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()?;

View File

@ -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).

View File

@ -1,15 +1,15 @@
use std::ffi::OsString;
use std::str::FromStr;
use anyhow::anyhow;
use nonempty::NonEmpty;
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};
use radicle::cob;
use radicle::cob::issue;
use radicle::storage::WriteStorage;
pub const HELP: Help = Help {
name: "unassign",
@ -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()));

View File

@ -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()?;

View File

@ -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())?;

View File

@ -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

View File

@ -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};

View File

@ -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))
}

View File

@ -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)
}

View File

@ -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)
}