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