//! Per-command modules — one file per top-level subcommand. //! //! `main.rs` holds the clap surface (argument enums) and the dispatch //! `match`; the actual command bodies live here. Helpers shared between //! command modules (e.g. `commit_paths`, `resolve_query`) are defined in //! this file as `pub(crate)` so siblings can pull them in via //! `use crate::commands::*`. pub mod generate; pub mod get; pub mod init; pub mod list; pub mod rate; pub mod status; pub mod sync; pub mod trash; use anyhow::Result; pub(crate) fn commit_paths( vault: &crate::session::UnlockedVault, message: &str, paths: &[&str], ) -> Result<()> { let mut args: Vec<&str> = vec!["add"]; args.extend_from_slice(paths); let status = crate::helpers::git_command(vault.root(), &args).status()?; if !status.success() { anyhow::bail!("git add failed"); } let status = crate::helpers::git_command(vault.root(), &["commit", "-m", message]).status()?; if !status.success() { anyhow::bail!("git commit failed"); } Ok(()) } pub(crate) fn resolve_query<'a>( manifest: &'a relicario_core::Manifest, query: &str, ) -> Result<&'a relicario_core::ManifestEntry> { if let Some(entry) = manifest.items.values().find(|e| e.id.as_str() == query) { return Ok(entry); } let hits: Vec<_> = manifest.search(query); match hits.len() { 0 => anyhow::bail!("no item matches `{query}`"), 1 => Ok(hits[0]), _ => { let titles: Vec<&str> = hits.iter().map(|e| e.title.as_str()).collect(); anyhow::bail!("ambiguous — {} matches: {}", hits.len(), titles.join(", ")) } } }