From 6af1ac30dff6e698452d7d8168362c4f130dc572 Mon Sep 17 00:00:00 2001 From: Andrew Phillips Date: Thu, 14 Aug 2025 13:04:22 -0300 Subject: [PATCH] fix: resolve import issues for Args and ProgramWriter in tests Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) --- src/args.rs | 151 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 ++ src/main.rs | 191 +--------------------------------------------------- 3 files changed, 159 insertions(+), 188 deletions(-) create mode 100644 src/args.rs diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 0000000..71e0857 --- /dev/null +++ b/src/args.rs @@ -0,0 +1,151 @@ +use std::path::PathBuf; + +use clap::*; +use serde::{Deserialize, Serialize}; + +/** + * Main struct for command-line arguments. + */ +#[derive(Parser, Debug, Clone)] +#[command(author, version, about, long_about = None)] +pub struct Args { + #[command(flatten)] + pub mode: ModeArgs, + #[command(flatten)] + pub item: ItemArgs, + #[command(flatten)] + pub options: OptionsArgs, + + #[arg(help("A list of either item IDs or tags"))] + pub ids_or_tags: Vec, +} + +/** + * Struct for mode-specific arguments. + */ +#[derive(Parser, Debug, Clone)] +pub struct ModeArgs { + #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "diff", "list", "update", "delete", "info", "status"]))] + #[arg(help("Save an item using any tags or metadata provided"))] + pub save: bool, + + #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "diff", "list", "update", "delete", "info", "status"]))] + #[arg(help( + "Get an item either by it's ID or by a combination of matching tags and metatdata" + ))] + pub get: bool, + + #[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "list", "update", "delete", "info", "status"]))] + #[arg(help("Show a diff between two items by ID"))] + pub diff: bool, + + #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "update", "delete", "info", "status"]))] + #[arg(help("List items, filtering on tags or metadata if given"))] + pub list: bool, + + #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "status"]), requires("ids_or_tags"))] + #[arg(help("Update a specified item ID's tags and/or metadata"))] + pub update: bool, + + #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "update", "info", "status"]), requires("ids_or_tags"))] + #[arg(help("Delete items either by ID or by matching tags"))] + pub delete: bool, + + #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "status"]), requires("ids_or_tags"))] + #[arg(help( + "Get an item either by it's ID or by a combination of matching tags and metatdata" + ))] + pub info: bool, + + #[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "info", "server"]))] + #[arg(help("Show status of directories and supported compression algorithms"))] + pub status: bool, + + #[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "info", "status"]))] + #[arg(help("Start REST HTTP server on specified address:port or socket path"))] + pub server: Option, +} + +/** + * Struct for item-specific arguments. + */ +#[derive(Parser, Debug, Clone)] +pub struct ItemArgs { + #[arg(help_heading("Item Options"), short, long, conflicts_with_all(["get", "delete", "status"]))] + #[arg(help( + "Set metadata for the item using the format KEY=[VALUE], the metadata will be removed if VALUE is not provided" + ))] + pub meta: Vec, + + #[arg(help_heading("Item Options"), long, env("KEEP_DIGEST"))] + #[arg(help("Digest algorithm to use when saving items"))] + pub digest: Option, + + #[arg(help_heading("Item Options"), short, long, env("KEEP_COMPRESSION"))] + #[arg(help("Compression algorithm to use when saving items"))] + pub compression: Option, + + #[arg(help_heading("Item Options"), short('M'), long, env("KEEP_META_PLUGINS"))] + #[arg(help("Meta plugins to use when saving items"))] + pub meta_plugins: Vec, +} + + +/** + * Struct for general options. + */ +#[derive(Parser, Debug, Default, Clone)] +pub struct OptionsArgs { + #[arg(long, env("KEEP_DIR"))] + #[arg(help("Specify the directory to use for storage"))] + pub dir: Option, + + #[arg( + long, + env("KEEP_LIST_FORMAT"), + default_value("id,time,size,tags,meta:hostname") + )] + #[arg(help("A comma separated list of columns to display with --list"))] + pub list_format: String, + + #[arg(short('H'), long)] + #[arg(help("Display file sizes with units"))] + pub human_readable: bool, + + #[arg(short, long, action = clap::ArgAction::Count, conflicts_with("quiet"))] + #[arg(help("Increase message verbosity, can be given more than once"))] + pub verbose: u8, + + #[arg(short, long)] + #[arg(help("Do not show any messages"))] + pub quiet: bool, + + #[arg(long, value_enum, default_value("table"))] + #[arg(help("Output format (only works with --info, --status, --list)"))] + pub output_format: Option, + + #[arg(long, env("KEEP_SERVER_PASSWORD"))] + #[arg(help("Password for server authentication (requires --server)"))] + pub server_password: Option, + + #[arg(long, help("Force output even when binary data would be sent to a TTY"))] + pub force: bool, +} + +/** + * Enum for representing either a number or a string. + */ +#[derive(Debug, Clone)] +pub enum NumberOrString { + Number(i64), + Str(String), +} + +/** + * Struct for key-value pairs. + */ +#[derive(Debug, Clone)] +pub struct KeyValue { + pub key: String, + pub value: String, +} diff --git a/src/lib.rs b/src/lib.rs index 42e9aa9..3517c80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,11 @@ pub mod compression_engine; pub mod db; pub mod meta_plugin; pub mod modes; +pub mod plugins; +pub mod args; + +// Re-export Args struct for library usage +pub use args::Args; #[cfg(test)] mod tests { diff --git a/src/main.rs b/src/main.rs index 66dac87..8cc2cf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ -use std::path::PathBuf; +mod args; +mod modes; use anyhow::{Context, Error, Result, anyhow}; use clap::*; use clap::error::ErrorKind; use log::*; -mod modes; extern crate directories; use directories::ProjectDirs; @@ -27,192 +27,7 @@ extern crate serde_json; extern crate serde_yaml; extern crate serde; - -/** - * Main struct for command-line arguments. - */ -#[derive(Parser, Debug, Clone)] -#[command(author, version, about, long_about = None)] -pub struct Args { - #[command(flatten)] - mode: ModeArgs, - #[command(flatten)] - item: ItemArgs, - #[command(flatten)] - options: OptionsArgs, - - #[arg(help("A list of either item IDs or tags"))] - ids_or_tags: Vec, -} - -/** - * Struct for mode-specific arguments. - */ -#[derive(Parser, Debug, Clone)] -struct ModeArgs { - #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "diff", "list", "update", "delete", "info", "status"]))] - #[arg(help("Save an item using any tags or metadata provided"))] - save: bool, - - #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "diff", "list", "update", "delete", "info", "status"]))] - #[arg(help( - "Get an item either by it's ID or by a combination of matching tags and metatdata" - ))] - get: bool, - - #[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "list", "update", "delete", "info", "status"]))] - #[arg(help("Show a diff between two items by ID"))] - diff: bool, - - #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "update", "delete", "info", "status"]))] - #[arg(help("List items, filtering on tags or metadata if given"))] - list: bool, - - #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "delete", "info", "status"]), requires("ids_or_tags"))] - #[arg(help("Update a specified item ID's tags and/or metadata"))] - update: bool, - - #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "update", "info", "status"]), requires("ids_or_tags"))] - #[arg(help("Delete items either by ID or by matching tags"))] - delete: bool, - - #[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "status"]), requires("ids_or_tags"))] - #[arg(help( - "Get an item either by it's ID or by a combination of matching tags and metatdata" - ))] - info: bool, - - #[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "info", "server"]))] - #[arg(help("Show status of directories and supported compression algorithms"))] - status: bool, - - #[arg(group("mode"), help_heading("Mode Options"), long, conflicts_with_all(["save", "get", "diff", "list", "update", "delete", "info", "status"]))] - #[arg(help("Start REST HTTP server on specified address:port or socket path"))] - server: Option, -} - -/** - * Struct for item-specific arguments. - */ -#[derive(Parser, Debug, Clone)] -struct ItemArgs { - #[arg(help_heading("Item Options"), short, long, conflicts_with_all(["get", "delete", "status"]))] - #[arg(help( - "Set metadata for the item using the format KEY=[VALUE], the metadata will be removed if VALUE is not provided" - ))] - meta: Vec, - - #[arg(help_heading("Item Options"), long, env("KEEP_DIGEST"))] - #[arg(help("Digest algorithm to use when saving items"))] - digest: Option, - - #[arg(help_heading("Item Options"), short, long, env("KEEP_COMPRESSION"))] - #[arg(help("Compression algorithm to use when saving items"))] - compression: Option, - - #[arg(help_heading("Item Options"), short('M'), long, env("KEEP_META_PLUGINS"))] - #[arg(help("Meta plugins to use when saving items"))] - meta_plugins: Vec, -} - - -/** - * Struct for general options. - */ -#[derive(Parser, Debug, Default, Clone)] -struct OptionsArgs { - #[arg(long, env("KEEP_DIR"))] - #[arg(help("Specify the directory to use for storage"))] - dir: Option, - - #[arg( - long, - env("KEEP_LIST_FORMAT"), - default_value("id,time,size,tags,meta:hostname") - )] - #[arg(help("A comma separated list of columns to display with --list"))] - list_format: String, - - #[arg(short('H'), long)] - #[arg(help("Display file sizes with units"))] - human_readable: bool, - - #[arg(short, long, action = clap::ArgAction::Count, conflicts_with("quiet"))] - #[arg(help("Increase message verbosity, can be given more than once"))] - verbose: u8, - - #[arg(short, long)] - #[arg(help("Do not show any messages"))] - quiet: bool, - - #[arg(long, value_enum, default_value("table"))] - #[arg(help("Output format (only works with --info, --status, --list)"))] - output_format: Option, - - #[arg(long, env("KEEP_SERVER_PASSWORD"))] - #[arg(help("Password for server authentication (requires --server)"))] - server_password: Option, - - #[arg(long, help("Force output even when binary data would be sent to a TTY"))] - force: bool, -} - -/** - * Enum representing the different modes of operation. - */ -#[derive(Debug, PartialEq)] -enum KeepModes { - Unknown, - Save, - Get, - Diff, - List, - Update, - Delete, - Info, - Status, - Server, -} - -/** - * Struct for key-value pairs. - */ -#[derive(Debug, Clone)] -struct KeyValue { - key: String, - value: String, -} - -impl FromStr for KeyValue { - type Err = Error; - fn from_str(s: &str) -> Result { - match s.split_once('=') { - Some(kv) => Ok(KeyValue { - key: kv.0.to_string(), - value: kv.1.to_string(), - }), - None => Err(anyhow!("Unable to parse key=value pair")), - } - } -} - -/** - * Enum for representing either a number or a string. - */ -#[derive(Debug, Clone)] -enum NumberOrString { - Number(i64), - Str(String), -} - -impl FromStr for NumberOrString { - type Err = Error; - fn from_str(s: &str) -> Result { - Ok(s.parse::() - .map(NumberOrString::Number) - .unwrap_or_else(|_| NumberOrString::Str(s.to_string()))) - } -} +use args::{Args, KeyValue, NumberOrString, KeepModes}; /** * Main function to handle command-line arguments and execute the appropriate mode.