From a35b5f9248da7452441f5806b57decc2cb7f34ba Mon Sep 17 00:00:00 2001 From: Jeremiah Russell Date: Mon, 20 Oct 2025 15:30:47 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs(cli):=20add=20comprehensive?= =?UTF-8?q?=20module=20documentation=20and=20function=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add extensive module-level documentation explaining CLI architecture - Document all CLI structs with detailed field explanations and usage examples - Add comprehensive function documentation covering all main workflow functions - Include safety considerations, error handling, and configuration guidance - Fix configuration parameter name: credentials -> credential_file - Document logging levels, exit codes, and environment variable overrides - Add detailed explanations of rule processing workflow and safety features --- src/cli/main.rs | 362 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 358 insertions(+), 4 deletions(-) diff --git a/src/cli/main.rs b/src/cli/main.rs index 7326fd9..1fc5640 100644 --- a/src/cli/main.rs +++ b/src/cli/main.rs @@ -1,3 +1,114 @@ +//! # Gmail Message Cull CLI Application +//! +//! A command-line interface for managing Gmail messages with automated retention rules. +//! This CLI provides powerful tools for querying, filtering, and managing Gmail messages +//! based on labels, age, and custom rules with built-in safety features like dry-run mode. +//! +//! ## Overview +//! +//! The CLI is built around three main command categories: +//! +//! - **Labels**: List and inspect Gmail labels for message organization +//! - **Messages**: Query, filter, and perform batch operations on Gmail messages +//! - **Rules**: Configure and execute automated message lifecycle management rules +//! +//! ## Authentication +//! +//! The CLI uses OAuth2 for Gmail API authentication with the following configuration: +//! +//! - **Configuration file**: `~/.cull-gmail/cull-gmail.toml` +//! - **Credential file**: OAuth2 credentials from Google Cloud Platform +//! - **Token storage**: Automatic token caching in `~/.cull-gmail/gmail1/` +//! +//! ## Command Structure +//! +//! ```bash +//! cull-gmail [OPTIONS] [COMMAND] +//! ``` +//! +//! ### Global Options +//! +//! - `-v, --verbose...`: Increase logging verbosity (can be used multiple times) +//! - `-q, --quiet...`: Decrease logging verbosity +//! - `-h, --help`: Show help information +//! - `-V, --version`: Show version information +//! +//! ### Commands +//! +//! 1. **`labels`**: List all available Gmail labels +//! 2. **`messages`**: Query and operate on Gmail messages +//! 3. **`rules`**: Configure and execute retention rules +//! +//! ## Configuration File Format +//! +//! The CLI expects a TOML configuration file at `~/.cull-gmail/cull-gmail.toml`: +//! +//! ```toml +//! # OAuth2 credential file (required) +//! credential_file = "client_secret.json" +//! +//! # Configuration root directory +//! config_root = "h:.cull-gmail" +//! +//! # Rules configuration file +//! rules = "rules.toml" +//! +//! # Default execution mode (false = dry-run, true = execute) +//! execute = false +//! ``` +//! +//! ## Safety Features +//! +//! - **Dry-run mode**: Default behavior prevents accidental data loss +//! - **Comprehensive logging**: Detailed operation tracking with multiple verbosity levels +//! - **Error handling**: Graceful error recovery with meaningful error messages +//! - **Confirmation prompts**: For destructive operations +//! +//! ## Usage Examples +//! +//! ### List Gmail Labels +//! ```bash +//! cull-gmail labels +//! ``` +//! +//! ### Query Messages +//! ```bash +//! # List recent messages +//! cull-gmail messages -m 10 list +//! +//! # Find old promotional emails +//! cull-gmail messages -Q "label:promotions older_than:1y" list +//! ``` +//! +//! ### Execute Rules +//! ```bash +//! # Preview rule execution (dry-run) +//! cull-gmail rules run +//! +//! # Execute rules for real +//! cull-gmail rules run --execute +//! ``` +//! +//! ## Error Handling +//! +//! The CLI returns the following exit codes: +//! - **0**: Success +//! - **101**: Error (check stderr and logs for details) +//! +//! ## Logging +//! +//! Logging is controlled through command-line verbosity flags and environment variables: +//! +//! - **Default**: Info level logging for the cull-gmail crate +//! - **Verbose (`-v`)**: Debug level logging +//! - **Very Verbose (`-vv`)**: Trace level logging +//! - **Quiet (`-q`)**: Error level logging only +//! +//! Environment variable override: +//! ```bash +//! export RUST_LOG=cull_gmail=debug +//! ``` + use clap::{Parser, Subcommand}; mod labels_cli; @@ -12,28 +123,103 @@ use labels_cli::LabelsCli; use messages_cli::MessagesCli; use rules_cli::RulesCli; +/// Main CLI application structure defining global options and subcommands. +/// +/// This struct represents the root of the command-line interface, providing +/// global configuration options and dispatching to specific subcommands for +/// labels, messages, and rules management. +/// +/// # Global Options +/// +/// - **Logging**: Configurable verbosity levels for operation visibility +/// - **Subcommands**: Optional command selection (defaults to rule execution) +/// +/// # Default Behavior +/// +/// When no subcommand is provided, the CLI executes the default rule processing +/// workflow, loading rules from the configuration file and executing them +/// according to the current execution mode (dry-run or live). #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Cli { + /// Logging verbosity control. + /// + /// Use `-q` for quiet (errors only), default for info level, + /// `-v` for debug level, `-vv` for trace level. #[clap(flatten)] logging: clap_verbosity_flag::Verbosity, + + /// Optional subcommand selection. + /// + /// If not provided, the CLI will execute the default rule processing workflow. #[command(subcommand)] sub_command: Option, } +/// Available CLI subcommands for Gmail message management. +/// +/// Each subcommand provides specialized functionality for different aspects +/// of Gmail message lifecycle management, from inspection to automated processing. +/// +/// # Command Categories +/// +/// - **Messages**: Direct message querying, filtering, and batch operations +/// - **Labels**: Gmail label inspection and management +/// - **Rules**: Automated message lifecycle rule configuration and execution +/// +/// # Display Order +/// +/// Commands are ordered by typical usage workflow: inspect labels first, +/// then query specific messages, and finally configure automated rules. #[derive(Subcommand, Debug)] enum SubCmds { - /// List messages + /// Query, filter, and perform batch operations on Gmail messages. + /// + /// Supports advanced Gmail query syntax, label filtering, and batch actions + /// including trash and permanent deletion with safety controls. #[clap(name = "messages", display_order = 3, next_help_heading = "Labels")] Message(MessagesCli), - /// List labels + + /// List and inspect available Gmail labels. + /// + /// Displays all labels in your Gmail account with their internal IDs, + /// useful for understanding label structure before creating queries or rules. #[clap(name = "labels", display_order = 2, next_help_heading = "Rules")] Labels(LabelsCli), - /// Configure and run rules + + /// Configure and execute automated message retention rules. + /// + /// Provides rule-based message lifecycle management with configurable + /// retention periods, label targeting, and automated actions. #[clap(name = "rules", display_order = 2)] Rules(RulesCli), } +/// CLI application entry point with comprehensive error handling and logging setup. +/// +/// This function initializes the async runtime, parses command-line arguments, +/// configures logging based on user preferences, and orchestrates the main +/// application workflow with proper error handling and exit code management. +/// +/// # Process Flow +/// +/// 1. **Argument Parsing**: Parse command-line arguments using clap +/// 2. **Logging Setup**: Initialize logging with user-specified verbosity +/// 3. **Application Execution**: Run the main application logic +/// 4. **Error Handling**: Handle errors with detailed reporting +/// 5. **Exit Code**: Return appropriate exit codes for shell integration +/// +/// # Exit Codes +/// +/// - **0**: Successful execution +/// - **101**: Error occurred (details logged and printed to stderr) +/// +/// # Error Reporting +/// +/// Errors are reported through multiple channels: +/// - **Logging**: Structured error logging for debugging +/// - **stderr**: User-friendly error messages +/// - **Exit codes**: Shell-scriptable status reporting #[tokio::main] async fn main() { let args = Cli::parse(); @@ -57,6 +243,34 @@ async fn main() { }); } +/// Main application logic dispatcher handling subcommand execution and default behavior. +/// +/// This function orchestrates the core application workflow by: +/// 1. Loading configuration from files and environment +/// 2. Initializing the Gmail API client with OAuth2 authentication +/// 3. Dispatching to appropriate subcommands or executing default rule processing +/// +/// # Arguments +/// +/// * `args` - Parsed command-line arguments containing global options and subcommands +/// +/// # Returns +/// +/// Returns `Result<()>` indicating success or failure of the operation. +/// +/// # Default Behavior +/// +/// When no subcommand is specified, the function executes the default rule processing +/// workflow, loading rules from configuration and executing them based on the +/// current execution mode setting. +/// +/// # Error Handling +/// +/// Errors can occur during: +/// - Configuration loading and parsing +/// - Gmail client initialization and authentication +/// - Subcommand execution +/// - Rule processing operations async fn run(args: Cli) -> Result<()> { let (config, client_config) = get_config()?; @@ -75,6 +289,35 @@ async fn run(args: Cli) -> Result<()> { } } +/// Creates and configures a logging builder with appropriate verbosity levels. +/// +/// This function sets up structured logging for the application with: +/// - Minimum info-level logging for user-facing information +/// - Configurable verbosity based on command-line flags +/// - Timestamp formatting for operation tracking +/// - Focused logging on the cull-gmail crate to reduce noise +/// +/// # Arguments +/// +/// * `level` - Desired log level filter from command-line verbosity flags +/// +/// # Returns +/// +/// Returns a configured `env_logger::Builder` ready for initialization. +/// +/// # Logging Levels +/// +/// - **Error**: Critical failures and unrecoverable errors +/// - **Warn**: Non-fatal issues, dry-run notifications, missing resources +/// - **Info**: General operation progress, message counts, rule execution +/// - **Debug**: Detailed operation info, API calls, configuration values +/// - **Trace**: Very detailed debugging information +/// +/// # Default Behavior +/// +/// The function enforces a minimum of Info-level logging to ensure users +/// receive adequate feedback about application operations, even when +/// verbosity is not explicitly requested. fn get_logging(level: log::LevelFilter) -> env_logger::Builder { let level = if level > log::LevelFilter::Info { level @@ -92,13 +335,54 @@ fn get_logging(level: log::LevelFilter) -> env_logger::Builder { builder } +/// Loads and parses application configuration from multiple sources. +/// +/// This function implements a hierarchical configuration loading strategy: +/// 1. **Default values**: Sensible defaults for all configuration options +/// 2. **Configuration file**: User-specific settings from `~/.cull-gmail/cull-gmail.toml` +/// 3. **Environment variables**: Runtime overrides with `APP_` prefix +/// +/// # Returns +/// +/// Returns a tuple containing: +/// - **Config**: Raw configuration for general application settings +/// - **ClientConfig**: Processed Gmail client configuration with OAuth2 setup +/// +/// # Configuration Hierarchy +/// +/// Settings are applied in this order (later sources override earlier ones): +/// 1. Built-in defaults +/// 2. Configuration file values +/// 3. Environment variable overrides +/// +/// # Configuration Parameters +/// +/// ## Default Values: +/// - `credentials`: "credential.json" - OAuth2 credential file name +/// - `config_root`: "h:.cull-gmail" - Configuration directory (home-relative) +/// - `rules`: "rules.toml" - Rules configuration file name +/// - `execute`: true - Default execution mode (can be overridden for safety) +/// +/// ## Environment Variables: +/// - `APP_CREDENTIALS`: Override credential file name +/// - `APP_CONFIG_ROOT`: Override configuration directory +/// - `APP_RULES`: Override rules file name +/// - `APP_EXECUTE`: Override execution mode (true/false) +/// +/// # Error Handling +/// +/// Configuration errors can occur due to: +/// - Missing or inaccessible configuration files +/// - Invalid TOML syntax in configuration files +/// - Missing OAuth2 credential files +/// - Invalid OAuth2 credential format or structure fn get_config() -> Result<(Config, ClientConfig)> { let home_dir = env::home_dir().unwrap(); let path = home_dir.join(".cull-gmail/cull-gmail.toml"); log::info!("Loading config from {}", path.display()); let configurations = config::Config::builder() - .set_default("credentials", "credential.json")? + .set_default("credential_file", "credential.json")? .set_default("config_root", "h:.cull-gmail")? .set_default("rules", "rules.toml")? .set_default("execute", true)? @@ -114,6 +398,41 @@ fn get_config() -> Result<(Config, ClientConfig)> { )) } +/// Executes automated message retention rules across Gmail labels. +/// +/// This function orchestrates the rule-based message processing workflow by: +/// 1. Organizing rules by their target labels +/// 2. Processing each label according to its configured rule +/// 3. Executing or simulating actions based on execution mode +/// +/// # Arguments +/// +/// * `client` - Mutable Gmail client for API operations +/// * `rules` - Loaded rules configuration containing all retention policies +/// * `execute` - Whether to actually perform actions (true) or dry-run (false) +/// +/// # Returns +/// +/// Returns `Result<()>` indicating success or failure of the rule processing. +/// +/// # Rule Processing Flow +/// +/// For each configured label: +/// 1. **Rule Lookup**: Find the retention rule for the label +/// 2. **Rule Application**: Apply rule criteria to find matching messages +/// 3. **Action Determination**: Determine appropriate action (trash/delete) +/// 4. **Execution**: Execute action or simulate for dry-run +/// +/// # Safety Features +/// +/// - **Dry-run mode**: When `execute` is false, actions are logged but not performed +/// - **Error isolation**: Errors for individual labels don't stop processing of other labels +/// - **Detailed logging**: Comprehensive logging of rule execution and results +/// +/// # Error Handling +/// +/// The function continues processing even if individual rules fail, logging +/// warnings for missing rules, processing errors, or action failures. async fn run_rules(client: &mut GmailClient, rules: Rules, execute: bool) -> Result<()> { let rules_by_labels = rules.get_rules_by_label(); @@ -145,6 +464,41 @@ async fn run_rules(client: &mut GmailClient, rules: Rules, execute: bool) -> Res Ok(()) } +/// Executes the specified end-of-life action on messages for a Gmail label. +/// +/// This function performs the actual message operations (trash or delete) based on +/// the rule configuration and execution mode. It handles both recoverable (trash) +/// and permanent (delete) operations with appropriate logging and error handling. +/// +/// # Arguments +/// +/// * `action` - The end-of-life action to perform (Trash or Delete) +/// * `client` - Gmail client configured with messages to process +/// * `label` - Label name for context in logging and error reporting +/// +/// # Actions +/// +/// ## Trash +/// - **Operation**: Moves messages to Gmail's Trash folder +/// - **Reversibility**: Messages can be recovered from Trash for ~30 days +/// - **Safety**: Relatively safe operation with recovery options +/// +/// ## Delete +/// - **Operation**: Permanently deletes messages from Gmail +/// - **Reversibility**: **IRREVERSIBLE** - messages cannot be recovered +/// - **Safety**: High-risk operation requiring careful consideration +/// +/// # Error Handling +/// +/// The function logs errors but does not propagate them, allowing rule processing +/// to continue for other labels even if one action fails. Errors are reported through: +/// - **Warning logs**: Structured logging for debugging +/// - **Label context**: Error messages include label name for traceability +/// +/// # Safety Considerations +/// +/// This function should only be called when execute mode is enabled and after +/// appropriate user confirmation for destructive operations. async fn execute_action(action: EolAction, client: &GmailClient, label: &str) { match action { EolAction::Trash => {