cli/help: remove the help module

The `help` module is no longer needed, since `clap` handles that.

This meant that the re-exports of each command's `ABOUT` could be removed and
the `const`s can now be private.
This commit is contained in:
Fintan Halpenny 2025-10-29 10:35:05 +00:00 committed by Lorenz Leutgeb
parent 23332fa318
commit d41ac59828
58 changed files with 31 additions and 345 deletions

View File

@ -9,7 +9,6 @@ pub mod debug;
pub mod diff; pub mod diff;
pub mod follow; pub mod follow;
pub mod fork; pub mod fork;
pub mod help;
pub mod id; pub mod id;
pub mod inbox; pub mod inbox;
pub mod init; pub mod init;

View File

@ -14,7 +14,6 @@ use radicle::{profile, Profile};
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
match ctx.profile() { match ctx.profile() {

View File

@ -1,7 +1,7 @@
use clap::Parser; use clap::Parser;
use radicle::node::Alias; use radicle::node::Alias;
pub(crate) const ABOUT: &str = "Manage identities and profiles"; const ABOUT: &str = "Manage identities and profiles";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
A passphrase may be given via the environment variable `RAD_PASSPHRASE` or A passphrase may be given via the environment variable `RAD_PASSPHRASE` or
via the standard input stream if `--stdin` is used. Using either of these via the standard input stream if `--stdin` is used. Using either of these

View File

@ -7,7 +7,6 @@ use crate::terminal as term;
use term::args::BlockTarget; use term::args::BlockTarget;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -2,7 +2,7 @@ use clap::Parser;
use crate::terminal::args::BlockTarget; use crate::terminal::args::BlockTarget;
pub(crate) const ABOUT: &str = "Block repositories or nodes from being seeded or followed"; const ABOUT: &str = "Block repositories or nodes from being seeded or followed";
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -15,7 +15,6 @@ use crate::project;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -1,7 +1,7 @@
use clap::Parser; use clap::Parser;
use radicle::prelude::{Did, RepoId}; use radicle::prelude::{Did, RepoId};
pub(crate) const ABOUT: &str = "Checkout a repository into the local directory"; const ABOUT: &str = "Checkout a repository into the local directory";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
Creates a working copy from a repository in local storage. Creates a working copy from a repository in local storage.
"#; "#;

View File

@ -6,7 +6,6 @@ use radicle::storage::WriteStorage;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -2,7 +2,7 @@ use clap::Parser;
use radicle::prelude::RepoId; use radicle::prelude::RepoId;
pub const ABOUT: &str = "Remove all remotes from a repository"; const ABOUT: &str = "Remove all remotes from a repository";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
Removes all remotes from a repository, as long as they are not the Removes all remotes from a repository, as long as they are not the

View File

@ -26,7 +26,6 @@ use crate::terminal as term;
use crate::terminal::Element as _; use crate::terminal::Element as _;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -11,7 +11,7 @@ use radicle::prelude::*;
use crate::terminal; use crate::terminal;
pub(crate) const ABOUT: &str = "Clone a Radicle repository"; const ABOUT: &str = "Clone a Radicle repository";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
The `clone` command will use your local node's routing table to find seeds from The `clone` command will use your local node's routing table to find seeds from

View File

@ -2,7 +2,6 @@ mod args;
pub use args::Args; pub use args::Args;
use args::Command; use args::Command;
pub(crate) use args::ABOUT;
use std::path::Path; use std::path::Path;

View File

@ -1,7 +1,7 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use radicle::node::Alias; use radicle::node::Alias;
pub(crate) const ABOUT: &str = "Manage your local Radicle configuration"; const ABOUT: &str = "Manage your local Radicle configuration";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
If no argument is specified, prints the current radicle configuration as JSON. If no argument is specified, prints the current radicle configuration as JSON.

View File

@ -13,7 +13,6 @@ use radicle::Profile;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub const NAME: &str = "rad"; pub const NAME: &str = "rad";
pub const VERSION: &str = env!("RADICLE_VERSION"); pub const VERSION: &str = env!("RADICLE_VERSION");

View File

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
pub const ABOUT: &str = "Write out information to help debug your Radicle node remotely"; const ABOUT: &str = "Write out information to help debug your Radicle node remotely";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
Run this if you are reporting a problem in Radicle. The output is Run this if you are reporting a problem in Radicle. The output is

View File

@ -8,7 +8,6 @@ use crate::terminal as term;
pub use args::Args; pub use args::Args;
use args::Operation; use args::Operation;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -4,7 +4,7 @@ use radicle::node::{Alias, NodeId};
use crate::terminal as term; use crate::terminal as term;
pub(crate) const ABOUT: &str = "Manage node follow policies"; const ABOUT: &str = "Manage node follow policies";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
The `follow` command will print all nodes being followed, optionally filtered by alias, if no The `follow` command will print all nodes being followed, optionally filtered by alias, if no

View File

@ -7,7 +7,6 @@ use radicle::rad;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -1,6 +1,6 @@
use radicle::identity::RepoId; use radicle::identity::RepoId;
pub(crate) const ABOUT: &str = "Create a fork of a repository"; const ABOUT: &str = "Create a fork of a repository";
#[derive(Debug, clap::Parser)] #[derive(Debug, clap::Parser)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -1,213 +0,0 @@
use std::ffi::OsString;
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
pub const HELP: Help = Help {
name: "help",
description: "CLI help",
version: env!("RADICLE_VERSION"),
usage: "Usage: rad help [--help]",
};
enum CommandItem {
Lexopt(Help),
Clap {
name: &'static str,
about: &'static str,
},
}
impl CommandItem {
fn name(&self) -> &str {
match self {
CommandItem::Lexopt(help) => help.name,
CommandItem::Clap { name, .. } => name,
}
}
fn description(&self) -> &str {
match self {
CommandItem::Lexopt(help) => help.description,
CommandItem::Clap {
about: description, ..
} => description,
}
}
}
const COMMANDS: &[CommandItem] = &[
CommandItem::Clap {
name: "auth",
about: crate::commands::auth::ABOUT,
},
CommandItem::Clap {
name: "block",
about: crate::commands::block::ABOUT,
},
CommandItem::Clap {
name: "checkout",
about: crate::commands::checkout::ABOUT,
},
CommandItem::Clap {
name: "clone",
about: crate::commands::clone::ABOUT,
},
CommandItem::Clap {
name: "config",
about: crate::commands::config::ABOUT,
},
CommandItem::Clap {
name: "debug",
about: crate::commands::debug::ABOUT,
},
CommandItem::Clap {
name: "fork",
about: crate::commands::fork::ABOUT,
},
CommandItem::Lexopt(crate::commands::help::HELP),
CommandItem::Clap {
name: "id",
about: crate::commands::id::ABOUT,
},
CommandItem::Clap {
name: "init",
about: crate::commands::init::ABOUT,
},
CommandItem::Clap {
name: "inbox",
about: crate::commands::inbox::ABOUT,
},
CommandItem::Clap {
name: "inspect",
about: crate::commands::inspect::ABOUT,
},
CommandItem::Clap {
name: "issue",
about: crate::commands::issue::ABOUT,
},
CommandItem::Clap {
name: "ls",
about: crate::commands::ls::ABOUT,
},
CommandItem::Clap {
name: "node",
about: crate::commands::node::ABOUT,
},
CommandItem::Clap {
name: "patch",
about: crate::commands::patch::ABOUT,
},
CommandItem::Clap {
name: "path",
about: crate::commands::path::ABOUT,
},
CommandItem::Clap {
name: "publish",
about: crate::commands::publish::ABOUT,
},
CommandItem::Clap {
name: "clean",
about: crate::commands::clean::ABOUT,
},
CommandItem::Clap {
name: "self",
about: crate::commands::rad_self::ABOUT,
},
CommandItem::Clap {
name: "seed",
about: crate::commands::seed::ABOUT,
},
CommandItem::Clap {
name: "follow",
about: crate::commands::follow::ABOUT,
},
CommandItem::Clap {
name: "unblock",
about: crate::commands::unblock::ABOUT,
},
CommandItem::Clap {
name: "unfollow",
about: crate::commands::unfollow::ABOUT,
},
CommandItem::Clap {
name: "unseed",
about: crate::commands::unseed::ABOUT,
},
CommandItem::Clap {
name: "remote",
about: crate::commands::remote::ABOUT,
},
CommandItem::Clap {
name: "stats",
about: crate::commands::stats::ABOUT,
},
CommandItem::Clap {
name: "sync",
about: crate::commands::sync::ABOUT,
},
CommandItem::Clap {
name: "watch",
about: crate::commands::watch::ABOUT,
},
];
#[derive(Default)]
pub struct Options {}
impl Args for Options {
fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
let mut parser = lexopt::Parser::from_args(args);
if let Some(arg) = parser.next()? {
anyhow::bail!(arg.unexpected());
}
Err(Error::HelpManual { name: "rad" }.into())
}
}
pub fn run(_options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
term::print("Usage: rad <command> [--help]");
if let Err(e) = ctx.profile() {
term::blank();
match e.downcast_ref() {
Some(term::args::Error::WithHint { err, hint }) => {
term::print(term::format::yellow(err));
term::print(term::format::yellow(hint));
}
Some(e) => {
term::error(e);
}
None => {
term::error(e);
}
}
term::blank();
}
term::print("Common `rad` commands used in various situations:");
term::blank();
for help in COMMANDS {
term::info!(
"\t{} {}",
term::format::bold(format!("{:-12}", help.name())),
term::format::dim(help.description())
);
}
term::blank();
term::print("See `rad <command> --help` to learn about a specific command.");
term::blank();
term::print("Do you have feedback?");
term::print(
" - Chat <\x1b]8;;https://radicle.zulipchat.com\x1b\\radicle.zulipchat.com\x1b]8;;\x1b\\>",
);
term::print(
" - Mail <\x1b]8;;mailto:feedback@radicle.xyz\x1b\\feedback@radicle.xyz\x1b]8;;\x1b\\>",
);
term::print(" (Messages are automatically posted to the public #feedback channel on Zulip.)");
Ok(())
}

View File

@ -23,7 +23,6 @@ use crate::terminal::patch::Message;
pub use args::Args; pub use args::Args;
use args::Command; use args::Command;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -17,7 +17,7 @@ use crate::git::Rev;
use crate::terminal::Interactive; use crate::terminal::Interactive;
pub(crate) const ABOUT: &str = "Manage repository identities"; const ABOUT: &str = "Manage repository identities";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
The `id` command is used to manage and propose changes to the The `id` command is used to manage and propose changes to the
identity of a Radicle repository. identity of a Radicle repository.

View File

@ -1,7 +1,6 @@
mod args; mod args;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use std::path::Path; use std::path::Path;
use std::process; use std::process;

View File

@ -3,7 +3,7 @@ use std::{fmt::Display, str::FromStr};
use clap::{Parser, Subcommand, ValueEnum}; use clap::{Parser, Subcommand, ValueEnum};
use radicle::{node::notifications::NotificationId, prelude::RepoId}; use radicle::{node::notifications::NotificationId, prelude::RepoId};
pub(crate) const ABOUT: &str = "Manage your Radicle notifications"; const ABOUT: &str = "Manage your Radicle notifications";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
By default, this command lists all items in your inbox. By default, this command lists all items in your inbox.

View File

@ -4,7 +4,6 @@
mod args; mod args;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::TryFrom; use std::convert::TryFrom;

View File

@ -8,7 +8,7 @@ use radicle::{
}; };
use radicle_term::Interactive; use radicle_term::Interactive;
pub(crate) const ABOUT: &str = "Initialize a Radicle repository"; const ABOUT: &str = "Initialize a Radicle repository";
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -23,7 +23,6 @@ use crate::terminal::Element;
pub use args::Args; pub use args::Args;
use args::Target; use args::Target;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let rid = match args.repo { let rid = match args.repo {

View File

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
pub(crate) const ABOUT: &str = "Inspect a Radicle repository"; const ABOUT: &str = "Inspect a Radicle repository";
const LONG_ABOUT: &str = r#"Inspects the given path or RID. If neither is specified, const LONG_ABOUT: &str = r#"Inspects the given path or RID. If neither is specified,
the current repository is inspected. the current repository is inspected.
"#; "#;

View File

@ -30,7 +30,7 @@ use crate::terminal::format::Author;
use crate::terminal::issue::Format; use crate::terminal::issue::Format;
use crate::terminal::Element; use crate::terminal::Element;
pub(crate) const ABOUT: &str = "Manage issues"; const ABOUT: &str = "Manage issues";
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -1,7 +1,6 @@
mod args; mod args;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use radicle::storage::{ReadStorage, RepositoryInfo}; use radicle::storage::{ReadStorage, RepositoryInfo};

View File

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
pub(crate) const ABOUT: &str = "List repositories"; const ABOUT: &str = "List repositories";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
By default, this command shows you all repositories that you have forked or initialized. By default, this command shows you all repositories that you have forked or initialized.
If you wish to see all seeded repositories, use the `--seeded` option. If you wish to see all seeded repositories, use the `--seeded` option.

View File

@ -19,7 +19,6 @@ use crate::terminal::Element as _;
use crate::warning; use crate::warning;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use args::{Addr, Command}; use args::{Addr, Command};
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {

View File

@ -11,7 +11,7 @@ use radicle::crypto::{PublicKey, PublicKeyError};
use radicle::node::{Address, NodeId, PeerAddr, PeerAddrParseError}; use radicle::node::{Address, NodeId, PeerAddr, PeerAddrParseError};
use radicle::prelude::RepoId; use radicle::prelude::RepoId;
pub(crate) const ABOUT: &str = "Control and query the Radicle Node"; const ABOUT: &str = "Control and query the Radicle Node";
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(about = ABOUT, long_about, disable_version_flag = true)] #[command(about = ABOUT, long_about, disable_version_flag = true)]

View File

@ -33,7 +33,6 @@ use crate::terminal as term;
use crate::terminal::patch::Message; use crate::terminal::patch::Message;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use args::{AssignArgs, Command, CommentAction, LabelArgs}; use args::{AssignArgs, Command, CommentAction, LabelArgs};

View File

@ -14,7 +14,7 @@ use crate::commands::patch::review;
use crate::git::Rev; use crate::git::Rev;
use crate::terminal::patch::Message; use crate::terminal::patch::Message;
pub(crate) const ABOUT: &str = "Manage patches"; const ABOUT: &str = "Manage patches";
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -5,7 +5,6 @@ use radicle::profile;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(_args: Args, _ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(_args: Args, _ctx: impl term::Context) -> anyhow::Result<()> {
let home = profile::home()?; let home = profile::home()?;

View File

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
pub const ABOUT: &str = "Display the Radicle home path"; const ABOUT: &str = "Display the Radicle home path";
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -10,7 +10,6 @@ use radicle::storage::{SignRepository, ValidateRepository, WriteRepository, Writ
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -1,6 +1,6 @@
use radicle::identity::RepoId; use radicle::identity::RepoId;
pub(crate) const ABOUT: &str = "Publish a repository to the network"; const ABOUT: &str = "Publish a repository to the network";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
Publishing a private repository makes it public and discoverable Publishing a private repository makes it public and discoverable

View File

@ -14,7 +14,6 @@ use crate::terminal as term;
use crate::terminal::Context; use crate::terminal::Context;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use args::{Command, ListOption}; use args::{Command, ListOption};
pub fn run(args: Args, ctx: impl Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl Context) -> anyhow::Result<()> {

View File

@ -6,7 +6,7 @@ use radicle::node::NodeId;
use crate::terminal as term; use crate::terminal as term;
pub(crate) const ABOUT: &str = "Manage a repository's remotes"; const ABOUT: &str = "Manage a repository's remotes";
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -10,7 +10,6 @@ use crate::commands::sync;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -9,7 +9,7 @@ use radicle::prelude::*;
use crate::node::SyncSettings; use crate::node::SyncSettings;
use crate::terminal; use crate::terminal;
pub(crate) const ABOUT: &str = "Manage repository seeding policies"; const ABOUT: &str = "Manage repository seeding policies";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
The `seed` command, when no Repository ID is provided, will list the The `seed` command, when no Repository ID is provided, will list the

View File

@ -2,7 +2,6 @@
mod args; mod args;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use radicle::crypto::ssh; use radicle::crypto::ssh;
use radicle::node::Handle as _; use radicle::node::Handle as _;

View File

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
pub(crate) const ABOUT: &str = "Show information about your identity and device"; const ABOUT: &str = "Show information about your identity and device";
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -16,7 +16,6 @@ use serde::Serialize;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]

View File

@ -1,6 +1,6 @@
use clap::Parser; use clap::Parser;
pub(crate) const ABOUT: &str = "Displays aggregated repository and node metrics"; const ABOUT: &str = "Displays aggregated repository and node metrics";
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -26,7 +26,6 @@ use crate::terminal::format::Author;
use crate::terminal::{Table, TableOptions}; use crate::terminal::{Table, TableOptions};
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
use args::{Command, SortBy, SyncDirection, SyncMode}; use args::{Command, SortBy, SyncDirection, SyncMode};
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {

View File

@ -10,7 +10,7 @@ use radicle::{
use crate::node::SyncSettings; use crate::node::SyncSettings;
pub(crate) const ABOUT: &str = "Sync repositories to the network"; const ABOUT: &str = "Sync repositories to the network";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
By default, the current repository is synchronized both ways. By default, the current repository is synchronized both ways.

View File

@ -5,7 +5,6 @@ use crate::terminal as term;
use term::args::BlockTarget; use term::args::BlockTarget;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -2,8 +2,7 @@ use clap::Parser;
use crate::terminal::args::BlockTarget; use crate::terminal::args::BlockTarget;
pub(crate) const ABOUT: &str = const ABOUT: &str = "Unblock repositories or nodes to allow them to be seeded or followed";
"Unblock repositories or nodes to allow them to be seeded or followed";
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(about = ABOUT, disable_version_flag = true)] #[command(about = ABOUT, disable_version_flag = true)]

View File

@ -5,7 +5,6 @@ use radicle::node::Handle;
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -4,7 +4,7 @@ use radicle::node::NodeId;
use crate::terminal as term; use crate::terminal as term;
pub(crate) const ABOUT: &str = "Unfollow a peer"; const ABOUT: &str = "Unfollow a peer";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
The `unfollow` command takes a Node ID, optionally in DID format, The `unfollow` command takes a Node ID, optionally in DID format,

View File

@ -5,7 +5,6 @@ use radicle::{prelude::*, Node};
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -1,7 +1,7 @@
use clap::Parser; use clap::Parser;
use radicle::prelude::RepoId; use radicle::prelude::RepoId;
pub(crate) const ABOUT: &str = "Remove repository seeding policies"; const ABOUT: &str = "Remove repository seeding policies";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
The `unseed` command removes the seeding policy, if found, The `unseed` command removes the seeding policy, if found,

View File

@ -12,7 +12,6 @@ use radicle::storage::{ReadRepository, ReadStorage};
use crate::terminal as term; use crate::terminal as term;
pub use args::Args; pub use args::Args;
pub(crate) use args::ABOUT;
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let profile = ctx.profile()?; let profile = ctx.profile()?;

View File

@ -7,7 +7,7 @@ use radicle::git;
use radicle::git::fmt::RefString; use radicle::git::fmt::RefString;
use radicle::prelude::{NodeId, RepoId}; use radicle::prelude::{NodeId, RepoId};
pub(crate) const ABOUT: &str = "Wait for some state to be updated"; const ABOUT: &str = "Wait for some state to be updated";
const LONG_ABOUT: &str = r#" const LONG_ABOUT: &str = r#"
Watches a Git reference, and optionally exits when it reaches a target value. Watches a Git reference, and optionally exits when it reaches a target value.

View File

@ -1,7 +1,10 @@
pub mod args; pub mod args;
use std::process;
pub use args::{Args, Error, Help}; pub use args::{Args, Error, Help};
pub mod format; pub mod format;
pub mod io; pub mod io;
use clap::Parser;
pub use io::signer; pub use io::signer;
pub mod cob; pub mod cob;
pub mod comment; pub mod comment;
@ -11,17 +14,10 @@ pub mod json;
pub mod patch; pub mod patch;
pub mod upload_pack; pub mod upload_pack;
use std::ffi::OsString;
use std::process;
use clap::Parser;
pub use radicle_term::*; pub use radicle_term::*;
use radicle::profile::{Home, Profile}; use radicle::profile::{Home, Profile};
use crate::terminal;
/// Context passed to all commands. /// Context passed to all commands.
pub trait Context { pub trait Context {
/// Return the currently active profile, or an error if no profile is active. /// Return the currently active profile, or an error if no profile is active.
@ -72,74 +68,6 @@ where
} }
} }
pub fn run_command<A, C>(help: Help, cmd: C) -> !
where
A: Args,
C: Command<A, DefaultContext>,
{
let args = std::env::args_os().skip(1).collect();
run_command_args(help, cmd, args)
}
pub fn run_command_args<A, C>(help: Help, cmd: C, args: Vec<OsString>) -> !
where
A: Args,
C: Command<A, DefaultContext>,
{
use io as term;
let options = match A::from_args(args) {
Ok((opts, unparsed)) => {
if let Err(err) = args::finish(unparsed) {
term::error(err);
process::exit(1);
}
opts
}
Err(err) => {
let hint = match err.downcast_ref::<Error>() {
Some(Error::Help) => {
help.print();
process::exit(0);
}
// Print the manual, or the regular help if there's an error.
Some(Error::HelpManual { name }) => {
let Ok(status) = term::manual(name) else {
help.print();
process::exit(0);
};
if !status.success() {
help.print();
process::exit(0);
}
process::exit(status.code().unwrap_or(0));
}
Some(Error::Usage) => {
term::usage(help.name, help.usage);
process::exit(1);
}
Some(Error::WithHint { hint, .. }) => Some(hint),
None => None,
};
io::error(format!("rad {}: {err}", help.name));
if let Some(hint) = hint {
io::hint(hint);
}
process::exit(1);
}
};
match cmd.run(options, DefaultContext) {
Ok(()) => process::exit(0),
Err(err) => {
terminal::fail(help.name, &err);
process::exit(1);
}
}
}
/// Gets the default profile. Fails if there is no profile. /// Gets the default profile. Fails if there is no profile.
pub struct DefaultContext; pub struct DefaultContext;