From 08bdfbc7c4360372468762a44a03d79df844ea1e Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Wed, 6 May 2026 19:42:22 -0400 Subject: [PATCH] refactor(cli): move cmd_settings into commands/settings.rs --- crates/relicario-cli/src/commands/mod.rs | 1 + crates/relicario-cli/src/commands/settings.rs | 98 +++++++++++++++++++ crates/relicario-cli/src/main.rs | 94 +----------------- 3 files changed, 100 insertions(+), 93 deletions(-) create mode 100644 crates/relicario-cli/src/commands/settings.rs diff --git a/crates/relicario-cli/src/commands/mod.rs b/crates/relicario-cli/src/commands/mod.rs index dcbdc68..2079ce3 100644 --- a/crates/relicario-cli/src/commands/mod.rs +++ b/crates/relicario-cli/src/commands/mod.rs @@ -15,6 +15,7 @@ pub mod init; pub mod list; pub mod rate; pub mod recovery_qr; +pub mod settings; pub mod status; pub mod sync; pub mod trash; diff --git a/crates/relicario-cli/src/commands/settings.rs b/crates/relicario-cli/src/commands/settings.rs new file mode 100644 index 0000000..226e320 --- /dev/null +++ b/crates/relicario-cli/src/commands/settings.rs @@ -0,0 +1,98 @@ +//! `relicario settings {show, trash-retention, history-retention, attachment-cap, generator-defaults}`. + +use anyhow::Result; + +use crate::SettingsAction; + +pub fn cmd_settings(action: SettingsAction) -> Result<()> { + use relicario_core::{ + Capitalization, CharClasses, GeneratorRequest, HistoryRetention, + SymbolCharset, TrashRetention, + }; + + let vault = crate::session::UnlockedVault::unlock_interactive()?; + let mut settings = vault.load_settings()?; + + match action { + SettingsAction::Show => { + println!("{}", serde_json::to_string_pretty(&settings)?); + return Ok(()); + } + SettingsAction::TrashRetention { days, forever } => { + settings.trash_retention = match (days, forever) { + (Some(d), false) => TrashRetention::Days(d), + (None, true) => TrashRetention::Forever, + _ => anyhow::bail!("specify exactly one of --days or --forever"), + }; + } + SettingsAction::HistoryRetention { last_n, days, forever } => { + settings.field_history_retention = match (last_n, days, forever) { + (Some(n), None, false) => HistoryRetention::LastN(n), + (None, Some(d), false) => HistoryRetention::Days(d), + (None, None, true) => HistoryRetention::Forever, + _ => anyhow::bail!("specify exactly one of --last-n / --days / --forever"), + }; + } + SettingsAction::AttachmentCap { + per_attachment_max_bytes, per_item_max_count, + per_vault_soft_cap_bytes, per_vault_hard_cap_bytes, + } => { + if let Some(v) = per_attachment_max_bytes { settings.attachment_caps.per_attachment_max_bytes = v; } + if let Some(v) = per_item_max_count { settings.attachment_caps.per_item_max_count = v; } + if let Some(v) = per_vault_soft_cap_bytes { settings.attachment_caps.per_vault_soft_cap_bytes = v; } + if let Some(v) = per_vault_hard_cap_bytes { settings.attachment_caps.per_vault_hard_cap_bytes = v; } + } + SettingsAction::GeneratorDefaults { + random, bip39, length, words, symbols, separator, + } => { + // Decide target mode: explicit flag wins, else preserve current. + let target_bip39 = if random { false } + else if bip39 { true } + else { matches!(settings.generator_defaults, GeneratorRequest::Bip39 { .. }) }; + + // Pull existing fields where compatible, else seed with sensible + // defaults (kept in sync with `GeneratorRequest::default()`). + let (cur_length, cur_classes, cur_charset) = match &settings.generator_defaults { + GeneratorRequest::Random { length, classes, symbol_charset } => { + (*length, *classes, symbol_charset.clone()) + } + _ => ( + 20, + CharClasses { lower: true, upper: true, digits: true, symbols: true }, + SymbolCharset::SafeOnly, + ), + }; + let (cur_words, cur_sep, cur_cap) = match &settings.generator_defaults { + GeneratorRequest::Bip39 { word_count, separator, capitalization } => { + (*word_count, separator.clone(), *capitalization) + } + _ => (5, " ".to_string(), Capitalization::Lower), + }; + + settings.generator_defaults = if target_bip39 { + GeneratorRequest::Bip39 { + word_count: words.unwrap_or(cur_words), + separator: separator.unwrap_or(cur_sep), + capitalization: cur_cap, + } + } else { + let charset = match symbols.as_deref() { + None => cur_charset, + Some("safe") => SymbolCharset::SafeOnly, + Some("extended") => SymbolCharset::Extended, + Some(other) => SymbolCharset::Custom(other.to_string()), + }; + GeneratorRequest::Random { + length: length.unwrap_or(cur_length), + classes: cur_classes, + symbol_charset: charset, + } + }; + } + } + + vault.save_settings(&settings)?; + super::commit_paths(&vault, "settings: update", &["settings.enc"])?; + eprintln!("Settings updated."); + Ok(()) +} diff --git a/crates/relicario-cli/src/main.rs b/crates/relicario-cli/src/main.rs index 6b5634a..a3fc45c 100644 --- a/crates/relicario-cli/src/main.rs +++ b/crates/relicario-cli/src/main.rs @@ -446,7 +446,7 @@ fn main() -> Result<()> { Commands::Generate { length, bip39, words, symbols, separator } => { commands::generate::cmd_generate(length, bip39, words, symbols, separator) } - Commands::Settings { action } => cmd_settings(action), + Commands::Settings { action } => commands::settings::cmd_settings(action), Commands::Sync => commands::sync::cmd_sync(), Commands::Status => commands::status::cmd_status(), Commands::Lock => { eprintln!("no cached session to lock"); Ok(()) } @@ -979,98 +979,6 @@ fn push_history( }); } -fn cmd_settings(action: SettingsAction) -> Result<()> { - use relicario_core::{ - Capitalization, CharClasses, GeneratorRequest, HistoryRetention, - SymbolCharset, TrashRetention, - }; - - let vault = crate::session::UnlockedVault::unlock_interactive()?; - let mut settings = vault.load_settings()?; - - match action { - SettingsAction::Show => { - println!("{}", serde_json::to_string_pretty(&settings)?); - return Ok(()); - } - SettingsAction::TrashRetention { days, forever } => { - settings.trash_retention = match (days, forever) { - (Some(d), false) => TrashRetention::Days(d), - (None, true) => TrashRetention::Forever, - _ => anyhow::bail!("specify exactly one of --days or --forever"), - }; - } - SettingsAction::HistoryRetention { last_n, days, forever } => { - settings.field_history_retention = match (last_n, days, forever) { - (Some(n), None, false) => HistoryRetention::LastN(n), - (None, Some(d), false) => HistoryRetention::Days(d), - (None, None, true) => HistoryRetention::Forever, - _ => anyhow::bail!("specify exactly one of --last-n / --days / --forever"), - }; - } - SettingsAction::AttachmentCap { - per_attachment_max_bytes, per_item_max_count, - per_vault_soft_cap_bytes, per_vault_hard_cap_bytes, - } => { - if let Some(v) = per_attachment_max_bytes { settings.attachment_caps.per_attachment_max_bytes = v; } - if let Some(v) = per_item_max_count { settings.attachment_caps.per_item_max_count = v; } - if let Some(v) = per_vault_soft_cap_bytes { settings.attachment_caps.per_vault_soft_cap_bytes = v; } - if let Some(v) = per_vault_hard_cap_bytes { settings.attachment_caps.per_vault_hard_cap_bytes = v; } - } - SettingsAction::GeneratorDefaults { - random, bip39, length, words, symbols, separator, - } => { - // Decide target mode: explicit flag wins, else preserve current. - let target_bip39 = if random { false } - else if bip39 { true } - else { matches!(settings.generator_defaults, GeneratorRequest::Bip39 { .. }) }; - - // Pull existing fields where compatible, else seed with sensible - // defaults (kept in sync with `GeneratorRequest::default()`). - let (cur_length, cur_classes, cur_charset) = match &settings.generator_defaults { - GeneratorRequest::Random { length, classes, symbol_charset } => { - (*length, *classes, symbol_charset.clone()) - } - _ => ( - 20, - CharClasses { lower: true, upper: true, digits: true, symbols: true }, - SymbolCharset::SafeOnly, - ), - }; - let (cur_words, cur_sep, cur_cap) = match &settings.generator_defaults { - GeneratorRequest::Bip39 { word_count, separator, capitalization } => { - (*word_count, separator.clone(), *capitalization) - } - _ => (5, " ".to_string(), Capitalization::Lower), - }; - - settings.generator_defaults = if target_bip39 { - GeneratorRequest::Bip39 { - word_count: words.unwrap_or(cur_words), - separator: separator.unwrap_or(cur_sep), - capitalization: cur_cap, - } - } else { - let charset = match symbols.as_deref() { - None => cur_charset, - Some("safe") => SymbolCharset::SafeOnly, - Some("extended") => SymbolCharset::Extended, - Some(other) => SymbolCharset::Custom(other.to_string()), - }; - GeneratorRequest::Random { - length: length.unwrap_or(cur_length), - classes: cur_classes, - symbol_charset: charset, - } - }; - } - } - - vault.save_settings(&settings)?; - commit_paths(&vault, "settings: update", &["settings.enc"])?; - eprintln!("Settings updated."); - Ok(()) -} // ── Device management ───────────────────────────────────────────────────────── /// Build a `GiteaClient` from flags or environment variables.