diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26955a12..e40a9ed6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
connections via SOCKS proxy and I2P for `*.i2p{,.alt}` names is now supported.
To enable making connections via I2P, configure `node.i2p`.
+## Deprecations
+
+- The commands to read and modify particular values in Radicle configuration via
+ the CLI, i.e.,
+ - `rad config get`
+ - `rad config push`
+ - `rad config remove`
+ - `rad config set`
+ - `rad config unset`
+ were marked as obsolete. In the future, please modify Radicle configuration
+ with your favorite text editor (e.g. via `rad config edit`), or specialized
+ tools like `jq`.
+
## 1.8.0
## New Features
diff --git a/crates/radicle-cli/src/commands/config.rs b/crates/radicle-cli/src/commands/config.rs
index ae67a407..d5eb0928 100644
--- a/crates/radicle-cli/src/commands/config.rs
+++ b/crates/radicle-cli/src/commands/config.rs
@@ -5,10 +5,13 @@ use args::Command;
use std::path::Path;
-use radicle::profile::{Config, ConfigPath, RawConfig, config};
+use radicle::profile::{Config, config};
+
+#[allow(deprecated)]
+use radicle::profile::config::{ConfigPath, RawConfig};
-use crate::terminal as term;
use crate::terminal::Element as _;
+use crate::{terminal as term, warning};
pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let home = ctx.home()?;
@@ -23,6 +26,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
Command::Schema => {
term::json::to_pretty(&schemars::schema_for!(Config), path.as_path())?.print()
}
+ #[allow(deprecated)]
Command::Get { key } => {
let mut temp_config = RawConfig::from_file(&path)?;
let key: ConfigPath = key.into();
@@ -31,19 +35,27 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
})?;
print_value(value)?;
}
+ #[allow(deprecated)]
Command::Set { key, value } => {
+ warning::obsolete("rad config set");
let value = modify(path, |tmp| tmp.set(&key.into(), value.into()))?;
print_value(&value)?;
}
+ #[allow(deprecated)]
Command::Push { key, value } => {
+ warning::obsolete("rad config push");
let value = modify(path, |tmp| tmp.push(&key.into(), value.into()))?;
print_value(&value)?;
}
+ #[allow(deprecated)]
Command::Remove { key, value } => {
+ warning::obsolete("rad config remove");
let value = modify(path, |tmp| tmp.remove(&key.into(), value.into()))?;
print_value(&value)?;
}
+ #[allow(deprecated)]
Command::Unset { key } => {
+ warning::obsolete("rad config unset");
let value = modify(path, |tmp| tmp.unset(&key.into()))?;
print_value(&value)?;
}
@@ -68,6 +80,8 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
Ok(())
}
+#[deprecated]
+#[allow(deprecated)]
fn modify
(path: P, modification: M) -> anyhow::Result
where
P: AsRef,
@@ -83,6 +97,8 @@ where
}
/// Print a JSON Value.
+#[deprecated]
+#[allow(deprecated)]
fn print_value(value: &serde_json::Value) -> anyhow::Result<()> {
match value {
serde_json::Value::Null => {}
diff --git a/crates/radicle-cli/src/commands/config/args.rs b/crates/radicle-cli/src/commands/config/args.rs
index b148e6b8..d757fdc2 100644
--- a/crates/radicle-cli/src/commands/config/args.rs
+++ b/crates/radicle-cli/src/commands/config/args.rs
@@ -29,6 +29,8 @@ pub(crate) enum Command {
/// Open the config in your editor
Edit,
/// Get a value from the current configuration
+ // Command is obsolete.
+ #[command(hide = true)]
Get {
/// The JSON key path to the value you want to get
key: String,
@@ -36,6 +38,8 @@ pub(crate) enum Command {
/// Prints the JSON Schema of the Radicle configuration
Schema,
/// Set a key to a value in the current configuration
+ // Command is obsolete.
+ #[command(hide = true)]
Set {
/// The JSON key path to the value you want to set
key: String,
@@ -43,12 +47,16 @@ pub(crate) enum Command {
value: String,
},
/// Set a key in the current configuration to `null`
+ // Command is obsolete.
+ #[command(hide = true)]
Unset {
/// The JSON key path to the value you want to unset
key: String,
},
/// Push a value onto an array, which is identified by the key, in the
/// current configuration
+ // Command is obsolete.
+ #[command(hide = true)]
Push {
/// The JSON key path to the array you want to push to
key: String,
@@ -59,6 +67,8 @@ pub(crate) enum Command {
/// current configuration
///
/// All instances of the value in the array will be removed
+ // Command is obsolete.
+ #[command(hide = true)]
Remove {
/// The JSON key path to the array you want to push to
key: String,
diff --git a/crates/radicle/src/profile.rs b/crates/radicle/src/profile.rs
index 727bdb70..b43fa0b0 100644
--- a/crates/radicle/src/profile.rs
+++ b/crates/radicle/src/profile.rs
@@ -12,7 +12,7 @@
//!
pub mod config;
-pub use config::{Config, ConfigPath, RawConfig, WriteError};
+pub use config::{Config, WriteError};
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
diff --git a/crates/radicle/src/profile/config.rs b/crates/radicle/src/profile/config.rs
index b2df138a..f0157a3e 100644
--- a/crates/radicle/src/profile/config.rs
+++ b/crates/radicle/src/profile/config.rs
@@ -206,15 +206,8 @@ impl Config {
/// Write configuration to disk.
pub fn write(&self, path: &Path) -> Result<(), WriteError> {
- let value = json::to_value(self).map_err(|err| WriteError::to_json(path, err))?;
- let tmp = RawConfig(value);
- let file = fs::OpenOptions::new()
- .create_new(true)
- .write(true)
- .open(path)
- .map_err(|err| WriteError::open_file(path, err))?;
-
- tmp.write_file(path, file)
+ let contents = json::to_vec_pretty(self).map_err(|err| WriteError::to_json(path, err))?;
+ fs::write(path, contents).map_err(|err| WriteError::write_file(path, err))
}
/// Get the user alias.
@@ -225,9 +218,11 @@ impl Config {
/// Offers utility functions for editing the configuration. Validates on write.
#[derive(Debug, Clone)]
+#[deprecated]
pub struct RawConfig(json::Value);
#[derive(Debug, Error)]
+#[allow(deprecated)]
pub enum ModifyError {
#[error("the path provided was empty")]
EmptyPath,
@@ -241,6 +236,7 @@ pub enum ModifyError {
Upsert { key: String },
}
+#[allow(deprecated)]
impl RawConfig {
/// Creates a temporary configuration, by reading a configuration file from disk.
pub fn from_file(path: &Path) -> Result {
@@ -396,6 +392,7 @@ impl RawConfig {
}
}
+#[allow(deprecated)]
impl TryFrom for Config {
type Error = json::Error;
@@ -406,11 +403,14 @@ impl TryFrom for Config {
/// A struct that ensures all values are safe for JSON serialization, including handling special
/// floating point values like `NaN` and `Infinity`. Use the `From<&str>` implementation to create an instance.
+#[deprecated]
+#[allow(deprecated)]
pub struct ConfigValue(RawConfigValue);
/// This enum represents raw configuration values and should not be used directly.
/// Use the `ConfigValue` type, which validates values using its `From<&str>` implementation.
#[derive(Debug, Clone)]
+#[deprecated]
enum RawConfigValue {
Integer(i64),
Float(f64),
@@ -418,6 +418,7 @@ enum RawConfigValue {
String(String),
}
+#[allow(deprecated)]
impl From<&str> for ConfigValue {
/// Guess the type of a Value.
fn from(value: &str) -> Self {
@@ -438,12 +439,14 @@ impl From<&str> for ConfigValue {
}
}
+#[allow(deprecated)]
impl From for ConfigValue {
fn from(value: String) -> Self {
value.as_str().into()
}
}
+#[allow(deprecated)]
impl From for json::Value {
fn from(value: ConfigValue) -> Self {
match value {
@@ -461,8 +464,10 @@ impl From for json::Value {
/// Configuration attribute path.
#[derive(Default, Debug, Clone)]
+#[deprecated]
pub struct ConfigPath(Vec);
+#[allow(deprecated)]
impl ConfigPath {
fn parent(&self) -> Option {
self.0.split_last().map(|(_, tail)| Self(tail.to_vec()))
@@ -477,12 +482,14 @@ impl ConfigPath {
}
}
+#[allow(deprecated)]
impl fmt::Display for ConfigPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0.join("."))
}
}
+#[allow(deprecated)]
impl From for ConfigPath {
fn from(value: String) -> Self {
let parts: Vec = value.split('.').map(|s| s.to_string()).collect();