diff --git a/radicle-cli/src/commands/config.rs b/radicle-cli/src/commands/config.rs
index 3581a982..906bdc24 100644
--- a/radicle-cli/src/commands/config.rs
+++ b/radicle-cli/src/commands/config.rs
@@ -2,8 +2,11 @@
use std::ffi::OsString;
use std::path::Path;
use std::process;
+use std::str::FromStr;
use anyhow::anyhow;
+use radicle::node::Alias;
+use radicle::profile::Config;
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
@@ -18,11 +21,10 @@ Usage
rad config [...]
rad config show [ ...]
- rad config init [ ...]
+ rad config init --alias [...]
rad config edit [ ...]
rad config get [...]
-
If no argument is specified, prints the current radicle configuration as JSON.
To initialize a new configuration file, use `rad config init`.
@@ -44,6 +46,7 @@ enum Operation {
pub struct Options {
op: Operation,
+ alias: Option,
}
impl Args for Options {
@@ -52,6 +55,7 @@ impl Args for Options {
let mut parser = lexopt::Parser::from_args(args);
let mut op: Option = None;
+ let mut alias = None;
#[allow(clippy::never_loop)]
while let Some(arg) = parser.next()? {
@@ -59,6 +63,13 @@ impl Args for Options {
Long("help") | Short('h') => {
return Err(Error::Help.into());
}
+ Long("alias") => {
+ let value = parser.value()?;
+ let input = value.to_string_lossy();
+ let input = Alias::from_str(&input)?;
+
+ alias = Some(input);
+ }
Value(val) if op.is_none() => match val.to_string_lossy().as_ref() {
"show" => op = Some(Operation::Show),
"edit" => op = Some(Operation::Edit),
@@ -78,6 +89,7 @@ impl Args for Options {
Ok((
Options {
op: op.unwrap_or_default(),
+ alias,
},
vec![],
))
@@ -85,14 +97,16 @@ impl Args for Options {
}
pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
- let profile = ctx.profile()?;
- let path = profile.home.config();
+ let home = ctx.home()?;
+ let path = home.config();
match options.op {
Operation::Show => {
+ let profile = ctx.profile()?;
term::json::to_pretty(&profile.config, path.as_path())?.print();
}
Operation::Get(key) => {
+ let profile = ctx.profile()?;
let data = serde_json::to_value(profile.config)?;
if let Some(value) = get_value(&data, &key) {
print_value(value)?;
@@ -102,7 +116,16 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
if path.try_exists()? {
anyhow::bail!("configuration file already exists at `{}`", path.display());
}
- profile.config.write(&path)?;
+ Config::init(
+ options.alias.ok_or(anyhow!(
+ "an alias must be provided to initialize a new configuration"
+ ))?,
+ &path,
+ )?;
+ term::success!(
+ "Initialized new Radicle configuration at {}",
+ path.display()
+ );
}
Operation::Edit => {
let Some(cmd) = term::editor::default_editor() else {
diff --git a/radicle-cli/src/main.rs b/radicle-cli/src/main.rs
index 232c5af4..adbc2bab 100644
--- a/radicle-cli/src/main.rs
+++ b/radicle-cli/src/main.rs
@@ -75,7 +75,7 @@ fn print_help() -> anyhow::Result<()> {
println!("{DESCRIPTION}");
println!();
- rad_help::run(Default::default(), term::profile)
+ rad_help::run(Default::default(), term::DefaultContext)
}
fn run(command: Command) -> Result<(), Option> {
diff --git a/radicle-cli/src/terminal.rs b/radicle-cli/src/terminal.rs
index 3d64ca68..13ad9532 100644
--- a/radicle-cli/src/terminal.rs
+++ b/radicle-cli/src/terminal.rs
@@ -14,7 +14,7 @@ use std::process;
pub use radicle_term::*;
-use radicle::profile::Profile;
+use radicle::profile::{Home, Profile};
use crate::terminal;
@@ -22,20 +22,17 @@ use crate::terminal;
pub trait Context {
/// Return the currently active profile, or an error if no profile is active.
fn profile(&self) -> Result;
+ /// Return the Radicle home.
+ fn home(&self) -> Result;
}
impl Context for Profile {
fn profile(&self) -> Result {
Ok(self.clone())
}
-}
-impl Context for F
-where
- F: Fn() -> Result,
-{
- fn profile(&self) -> Result {
- self()
+ fn home(&self) -> Result {
+ Ok(self.home.clone())
}
}
@@ -57,7 +54,7 @@ where
pub fn run_command(help: Help, cmd: C) -> !
where
A: Args,
- C: Command anyhow::Result>,
+ C: Command,
{
let args = std::env::args_os().skip(1).collect();
@@ -67,7 +64,7 @@ where
pub fn run_command_args (help: Help, cmd: C, args: Vec) -> !
where
A: Args,
- C: Command anyhow::Result>,
+ C: Command,
{
use io as term;
@@ -108,7 +105,7 @@ where
}
};
- match cmd.run(options, self::profile) {
+ match cmd.run(options, DefaultContext) {
Ok(()) => process::exit(0),
Err(err) => {
terminal::fail(help.name, &err);
@@ -117,17 +114,25 @@ where
}
}
-/// Get the default profile. Fails if there is no profile.
-pub fn profile() -> Result {
- match Profile::load() {
- Ok(profile) => Ok(profile),
- Err(radicle::profile::Error::NotFound(path)) => Err(args::Error::WithHint {
- err: anyhow::anyhow!("Radicle profile not found in '{}'.", path.display()),
- hint: "To setup your radicle profile, run `rad auth`.",
+/// Gets the default profile. Fails if there is no profile.
+pub struct DefaultContext;
+
+impl Context for DefaultContext {
+ fn home(&self) -> Result {
+ radicle::profile::home()
+ }
+
+ fn profile(&self) -> Result {
+ match Profile::load() {
+ Ok(profile) => Ok(profile),
+ Err(radicle::profile::Error::NotFound(path)) => Err(args::Error::WithHint {
+ err: anyhow::anyhow!("Radicle profile not found in '{}'.", path.display()),
+ hint: "To setup your radicle profile, run `rad auth`.",
+ }
+ .into()),
+ Err(radicle::profile::Error::Config(e)) => Err(e.into()),
+ Err(e) => Err(anyhow::anyhow!("Could not load radicle profile: {e}")),
}
- .into()),
- Err(radicle::profile::Error::Config(e)) => Err(e.into()),
- Err(e) => Err(anyhow::anyhow!("Could not load radicle profile: {e}")),
}
}