From ce693344cac20d7541738819928cef00333b0099 Mon Sep 17 00:00:00 2001 From: Greg von Nessi Date: Mon, 16 Feb 2026 15:57:12 +0000 Subject: [PATCH] Split CLI main.rs into cli, dispatcher, and main modules Separate argument definitions (cli.rs), command dispatch (dispatcher.rs), and entry point (main.rs) so adding new commands touches focused files instead of one 638-line monolith. --- cdx-cli/src/cli.rs | 411 ++++++++++++++++++++++++++ cdx-cli/src/dispatcher.rs | 193 ++++++++++++ cdx-cli/src/main.rs | 607 +------------------------------------- 3 files changed, 612 insertions(+), 599 deletions(-) create mode 100644 cdx-cli/src/cli.rs create mode 100644 cdx-cli/src/dispatcher.rs diff --git a/cdx-cli/src/cli.rs b/cdx-cli/src/cli.rs new file mode 100644 index 0000000..28b1a68 --- /dev/null +++ b/cdx-cli/src/cli.rs @@ -0,0 +1,411 @@ +//! CLI argument definitions. + +use clap::{Parser, Subcommand}; +use clap_complete::Shell; +use std::path::PathBuf; + +#[derive(Parser)] +#[command(name = "cdx")] +#[command(author, version, about = "Codex Document Format CLI", long_about = None)] +#[command(propagate_version = true)] +pub struct Cli { + #[command(subcommand)] + pub command: Commands, + + /// Increase output verbosity + #[arg(short, long, global = true)] + pub verbose: bool, + + /// Suppress non-error output + #[arg(short, long, global = true)] + pub quiet: bool, + + /// Output as JSON (for scripting) + #[arg(long, global = true)] + pub json: bool, + + /// Color output control + #[arg(long, value_enum, default_value = "auto", global = true)] + pub color: ColorChoice, +} + +#[derive(Clone, Copy, PartialEq, Eq, clap::ValueEnum)] +pub enum ColorChoice { + Auto, + Always, + Never, +} + +#[derive(Subcommand)] +pub enum Commands { + /// Create a new Codex document + Create { + /// Document title (required) + #[arg(short, long)] + title: String, + + /// Author name(s) + #[arg(short, long)] + author: Vec, + + /// Initial state + #[arg(long, default_value = "draft")] + state: String, + + /// Input content file (markdown, text) + #[arg(short, long)] + input: Option, + + /// Output file + output: PathBuf, + }, + + /// Validate document structure and hashes + Validate { + /// Codex document to validate + file: PathBuf, + }, + + /// Display document information + Inspect { + /// Codex document to inspect + file: PathBuf, + + /// Show detailed block information + #[arg(long)] + blocks: bool, + + /// Show signature details + #[arg(long)] + signatures: bool, + + /// Show provenance chain + #[arg(long)] + provenance: bool, + }, + + /// Show comprehensive document status + Status { + /// Codex document to check + file: PathBuf, + }, + + /// Add a digital signature + Sign { + /// Codex document to sign + file: PathBuf, + + /// Private key file (PEM format) + #[arg(short, long)] + key: PathBuf, + + /// Signer name + #[arg(short, long)] + name: String, + + /// Signer email + #[arg(short, long)] + email: Option, + + /// Signature algorithm + #[arg(short, long, default_value = "ES256")] + algorithm: String, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Verify signatures and integrity + Verify { + /// Codex document to verify + file: PathBuf, + + /// Public key file(s) for signature verification + #[arg(short, long)] + key: Vec, + }, + + /// Extract content or assets + Extract { + /// Codex document to extract from + file: PathBuf, + + /// Output directory for extraction + #[arg(short, long, default_value = ".")] + output: PathBuf, + + /// Extract content as JSON + #[arg(long)] + content: bool, + + /// Extract as plain text + #[arg(long)] + text: bool, + + /// Extract specific asset + #[arg(long)] + asset: Option, + + /// Extract all assets + #[arg(long)] + all_assets: bool, + }, + + /// Generate shell completions + Completions { + /// Shell to generate completions for + shell: Shell, + }, + + /// Submit document for review (draft → review) + #[command(name = "submit-review")] + SubmitReview { + /// Codex document to submit + file: PathBuf, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Freeze document (review → frozen) + Freeze { + /// Codex document to freeze + file: PathBuf, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Publish document (frozen → published) + Publish { + /// Codex document to publish + file: PathBuf, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Revert document to draft (review → draft) + Revert { + /// Codex document to revert + file: PathBuf, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Fork document to create new version with lineage + Fork { + /// Codex document to fork + file: PathBuf, + + /// Output file for the forked document + #[arg(short, long)] + output: PathBuf, + + /// Note describing the changes + #[arg(short, long)] + note: Option, + }, + + /// Generate a Merkle proof for a block + Prove { + /// Codex document + file: PathBuf, + + /// Block ID to prove + #[arg(long, conflicts_with = "block_index")] + block_id: Option, + + /// Block index to prove (0-based) + #[arg(long, conflicts_with = "block_id")] + block_index: Option, + + /// Output file for the proof JSON + #[arg(short, long)] + output: Option, + }, + + /// Verify a Merkle proof against a document + #[command(name = "verify-proof")] + VerifyProof { + /// Codex document + file: PathBuf, + + /// Proof JSON file + proof: PathBuf, + }, + + /// Show document lineage (ancestor chain) + #[command(name = "show-lineage")] + ShowLineage { + /// Codex document + file: PathBuf, + }, + + /// Display document metadata + #[command(name = "get-metadata")] + GetMetadata { + /// Codex document + file: PathBuf, + }, + + /// Set document metadata fields + #[command(name = "set-metadata")] + SetMetadata { + /// Codex document + file: PathBuf, + + /// Set title + #[arg(long)] + title: Option, + + /// Set creator(s) + #[arg(long)] + creator: Vec, + + /// Set subject(s) + #[arg(long)] + subject: Vec, + + /// Set description + #[arg(long)] + description: Option, + + /// Set publisher + #[arg(long)] + publisher: Option, + + /// Set language (BCP 47 code) + #[arg(long)] + language: Option, + + /// Set rights statement + #[arg(long)] + rights: Option, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Pack a directory or JSON into a .cdx archive + Pack { + /// Input directory or JSON file + input: PathBuf, + + /// Output .cdx file + #[arg(short, long)] + output: PathBuf, + + /// Input is combined JSON from Pandoc writer + #[arg(long)] + from_json: bool, + }, + + /// Compare two Codex documents + Diff { + /// First document + file1: PathBuf, + + /// Second document + file2: PathBuf, + }, + + /// Show timestamps in a document + #[command(name = "show-timestamps")] + ShowTimestamps { + /// Codex document + file: PathBuf, + }, + + /// Verify timestamps in a document + #[command(name = "verify-timestamps")] + VerifyTimestamps { + /// Codex document + file: PathBuf, + }, + + /// Add a timestamp record to a document + #[command(name = "add-timestamp")] + AddTimestamp { + /// Codex document + file: PathBuf, + + /// Timestamp method (rfc3161, bitcoin, ethereum, opentimestamps) + #[arg(long)] + method: String, + + /// Timestamp authority URL or name + #[arg(long)] + authority: String, + + /// Base64-encoded timestamp token + #[arg(long)] + token: String, + + /// Timestamp time (RFC 3339 format, defaults to now) + #[arg(long)] + time: Option, + + /// Transaction ID (for blockchain timestamps) + #[arg(long)] + transaction_id: Option, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Acquire a timestamp from a timestamp authority + #[command(name = "timestamp-acquire")] + TimestampAcquire { + /// Codex document to timestamp + file: PathBuf, + + /// Timestamp method (rfc3161, ots, auto) + #[arg(short, long, default_value = "auto")] + method: Option, + + /// TSA server URL (for rfc3161, uses defaults if not specified) + #[arg(short, long)] + server: Option, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Encrypt a document with password-based encryption + Encrypt { + /// Codex document to encrypt + file: PathBuf, + + /// Password (will prompt if not provided) + #[arg(short, long)] + password: Option, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, + + /// Decrypt a password-encrypted document + Decrypt { + /// Codex document to decrypt + file: PathBuf, + + /// Password (will prompt if not provided) + #[arg(short, long)] + password: Option, + + /// Output file (default: overwrite input) + #[arg(short, long)] + output: Option, + }, +} diff --git a/cdx-cli/src/dispatcher.rs b/cdx-cli/src/dispatcher.rs new file mode 100644 index 0000000..014f9ea --- /dev/null +++ b/cdx-cli/src/dispatcher.rs @@ -0,0 +1,193 @@ +//! Command dispatch. + +use anyhow::Result; +use clap::CommandFactory; +use clap_complete::generate; +use std::io; + +use crate::cli::{Cli, Commands}; +use crate::commands; +use crate::output; + +#[allow(clippy::too_many_lines)] // flat match dispatching each CLI subcommand — no shared logic to extract +pub fn run_command(command: Commands, output_config: &output::OutputConfig) -> Result<()> { + match command { + Commands::Create { + title, + author, + state, + input, + output: output_path, + } => commands::create::run(&title, &author, &state, input, &output_path, output_config), + + Commands::Validate { file } => commands::validate::run(&file, output_config), + + Commands::Inspect { + file, + blocks, + signatures, + provenance, + } => commands::inspect::run(&file, blocks, signatures, provenance, output_config), + + Commands::Status { file } => commands::status::run(&file, output_config), + + Commands::Sign { + file, + key, + name, + email, + algorithm, + output: output_path, + } => commands::sign::run( + &file, + &key, + &name, + email, + &algorithm, + output_path, + output_config, + ), + + Commands::Verify { file, key } => commands::verify::run(&file, &key, output_config), + + Commands::Extract { + file, + output: output_path, + content, + text, + asset, + all_assets, + } => commands::extract::run( + &file, + &output_path, + content, + text, + asset.as_deref(), + all_assets, + output_config, + ), + + Commands::Completions { shell } => { + generate(shell, &mut Cli::command(), "cdx", &mut io::stdout()); + Ok(()) + } + + Commands::SubmitReview { file, output } => { + commands::review::run(&file, output, output_config) + } + + Commands::Freeze { file, output } => commands::freeze::run(&file, output, output_config), + + Commands::Publish { file, output } => commands::publish::run(&file, output, output_config), + + Commands::Revert { file, output } => commands::revert::run(&file, output, output_config), + + Commands::Fork { file, output, note } => { + commands::fork::run(&file, &output, note, output_config) + } + + Commands::Prove { + file, + block_id, + block_index, + output, + } => commands::prove::run_prove(&file, block_id, block_index, output, output_config), + + Commands::VerifyProof { file, proof } => { + commands::prove::run_verify_proof(&file, &proof, output_config) + } + + Commands::ShowLineage { file } => commands::prove::run_show_lineage(&file, output_config), + + Commands::GetMetadata { file } => { + commands::metadata::run_get_metadata(&file, output_config) + } + + Commands::SetMetadata { + file, + title, + creator, + subject, + description, + publisher, + language, + rights, + output, + } => { + let params = commands::metadata::SetMetadataParams { + file, + title, + creator, + subject, + description, + publisher, + language, + rights, + output, + }; + commands::metadata::run_set_metadata(¶ms, output_config) + } + + Commands::Pack { + input, + output: output_path, + from_json, + } => commands::pack::run(&input, &output_path, from_json, output_config), + + Commands::Diff { file1, file2 } => commands::diff::run(&file1, &file2, output_config), + + Commands::ShowTimestamps { file } => { + commands::timestamp::run_show_timestamps(&file, output_config) + } + + Commands::VerifyTimestamps { file } => { + commands::timestamp::run_verify_timestamps(&file, output_config) + } + + Commands::AddTimestamp { + file, + method, + authority, + token, + time, + transaction_id, + output, + } => { + let params = commands::timestamp::AddTimestampParams { + file, + method, + authority, + token, + time, + transaction_id, + _output: output, + }; + commands::timestamp::run_add_timestamp(¶ms, output_config) + } + + Commands::TimestampAcquire { + file, + method, + server, + output, + } => commands::timestamp::run_acquire_timestamp( + &file, + method.as_deref(), + server.as_deref(), + output, + output_config, + ), + + Commands::Encrypt { + file, + password, + output, + } => commands::encrypt::run(&file, password, output, output_config), + + Commands::Decrypt { + file, + password, + output, + } => commands::decrypt::run(&file, password, output, output_config), + } +} diff --git a/cdx-cli/src/main.rs b/cdx-cli/src/main.rs index bcfb0d1..bc049d9 100644 --- a/cdx-cli/src/main.rs +++ b/cdx-cli/src/main.rs @@ -5,430 +5,22 @@ #![warn(clippy::pedantic)] #![allow(clippy::module_name_repetitions)] +mod cli; mod commands; +mod dispatcher; mod output; -use anyhow::Result; -use clap::{CommandFactory, Parser, Subcommand}; -use clap_complete::{generate, Shell}; +use clap::Parser; use colored::Colorize; -use std::io; -use std::path::PathBuf; - -#[derive(Parser)] -#[command(name = "cdx")] -#[command(author, version, about = "Codex Document Format CLI", long_about = None)] -#[command(propagate_version = true)] -struct Cli { - #[command(subcommand)] - command: Commands, - - /// Increase output verbosity - #[arg(short, long, global = true)] - verbose: bool, - - /// Suppress non-error output - #[arg(short, long, global = true)] - quiet: bool, - - /// Output as JSON (for scripting) - #[arg(long, global = true)] - json: bool, - - /// Color output control - #[arg(long, value_enum, default_value = "auto", global = true)] - color: ColorChoice, -} - -#[derive(Clone, Copy, PartialEq, Eq, clap::ValueEnum)] -enum ColorChoice { - Auto, - Always, - Never, -} - -#[derive(Subcommand)] -enum Commands { - /// Create a new Codex document - Create { - /// Document title (required) - #[arg(short, long)] - title: String, - - /// Author name(s) - #[arg(short, long)] - author: Vec, - - /// Initial state - #[arg(long, default_value = "draft")] - state: String, - - /// Input content file (markdown, text) - #[arg(short, long)] - input: Option, - - /// Output file - output: PathBuf, - }, - - /// Validate document structure and hashes - Validate { - /// Codex document to validate - file: PathBuf, - }, - - /// Display document information - Inspect { - /// Codex document to inspect - file: PathBuf, - - /// Show detailed block information - #[arg(long)] - blocks: bool, - - /// Show signature details - #[arg(long)] - signatures: bool, - - /// Show provenance chain - #[arg(long)] - provenance: bool, - }, - - /// Show comprehensive document status - Status { - /// Codex document to check - file: PathBuf, - }, - - /// Add a digital signature - Sign { - /// Codex document to sign - file: PathBuf, - - /// Private key file (PEM format) - #[arg(short, long)] - key: PathBuf, - - /// Signer name - #[arg(short, long)] - name: String, - - /// Signer email - #[arg(short, long)] - email: Option, - - /// Signature algorithm - #[arg(short, long, default_value = "ES256")] - algorithm: String, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Verify signatures and integrity - Verify { - /// Codex document to verify - file: PathBuf, - - /// Public key file(s) for signature verification - #[arg(short, long)] - key: Vec, - }, - - /// Extract content or assets - Extract { - /// Codex document to extract from - file: PathBuf, - - /// Output directory for extraction - #[arg(short, long, default_value = ".")] - output: PathBuf, - - /// Extract content as JSON - #[arg(long)] - content: bool, - - /// Extract as plain text - #[arg(long)] - text: bool, - - /// Extract specific asset - #[arg(long)] - asset: Option, - - /// Extract all assets - #[arg(long)] - all_assets: bool, - }, - - /// Generate shell completions - Completions { - /// Shell to generate completions for - shell: Shell, - }, - - /// Submit document for review (draft → review) - #[command(name = "submit-review")] - SubmitReview { - /// Codex document to submit - file: PathBuf, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Freeze document (review → frozen) - Freeze { - /// Codex document to freeze - file: PathBuf, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Publish document (frozen → published) - Publish { - /// Codex document to publish - file: PathBuf, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Revert document to draft (review → draft) - Revert { - /// Codex document to revert - file: PathBuf, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Fork document to create new version with lineage - Fork { - /// Codex document to fork - file: PathBuf, - - /// Output file for the forked document - #[arg(short, long)] - output: PathBuf, - - /// Note describing the changes - #[arg(short, long)] - note: Option, - }, - - /// Generate a Merkle proof for a block - Prove { - /// Codex document - file: PathBuf, - - /// Block ID to prove - #[arg(long, conflicts_with = "block_index")] - block_id: Option, - - /// Block index to prove (0-based) - #[arg(long, conflicts_with = "block_id")] - block_index: Option, - - /// Output file for the proof JSON - #[arg(short, long)] - output: Option, - }, - - /// Verify a Merkle proof against a document - #[command(name = "verify-proof")] - VerifyProof { - /// Codex document - file: PathBuf, - - /// Proof JSON file - proof: PathBuf, - }, - - /// Show document lineage (ancestor chain) - #[command(name = "show-lineage")] - ShowLineage { - /// Codex document - file: PathBuf, - }, - - /// Display document metadata - #[command(name = "get-metadata")] - GetMetadata { - /// Codex document - file: PathBuf, - }, - - /// Set document metadata fields - #[command(name = "set-metadata")] - SetMetadata { - /// Codex document - file: PathBuf, - - /// Set title - #[arg(long)] - title: Option, - - /// Set creator(s) - #[arg(long)] - creator: Vec, - - /// Set subject(s) - #[arg(long)] - subject: Vec, - - /// Set description - #[arg(long)] - description: Option, - - /// Set publisher - #[arg(long)] - publisher: Option, - - /// Set language (BCP 47 code) - #[arg(long)] - language: Option, - - /// Set rights statement - #[arg(long)] - rights: Option, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Pack a directory or JSON into a .cdx archive - Pack { - /// Input directory or JSON file - input: PathBuf, - - /// Output .cdx file - #[arg(short, long)] - output: PathBuf, - - /// Input is combined JSON from Pandoc writer - #[arg(long)] - from_json: bool, - }, - - /// Compare two Codex documents - Diff { - /// First document - file1: PathBuf, - - /// Second document - file2: PathBuf, - }, - - /// Show timestamps in a document - #[command(name = "show-timestamps")] - ShowTimestamps { - /// Codex document - file: PathBuf, - }, - - /// Verify timestamps in a document - #[command(name = "verify-timestamps")] - VerifyTimestamps { - /// Codex document - file: PathBuf, - }, - - /// Add a timestamp record to a document - #[command(name = "add-timestamp")] - AddTimestamp { - /// Codex document - file: PathBuf, - - /// Timestamp method (rfc3161, bitcoin, ethereum, opentimestamps) - #[arg(long)] - method: String, - - /// Timestamp authority URL or name - #[arg(long)] - authority: String, - - /// Base64-encoded timestamp token - #[arg(long)] - token: String, - - /// Timestamp time (RFC 3339 format, defaults to now) - #[arg(long)] - time: Option, - - /// Transaction ID (for blockchain timestamps) - #[arg(long)] - transaction_id: Option, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Acquire a timestamp from a timestamp authority - #[command(name = "timestamp-acquire")] - TimestampAcquire { - /// Codex document to timestamp - file: PathBuf, - - /// Timestamp method (rfc3161, ots, auto) - #[arg(short, long, default_value = "auto")] - method: Option, - - /// TSA server URL (for rfc3161, uses defaults if not specified) - #[arg(short, long)] - server: Option, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Encrypt a document with password-based encryption - Encrypt { - /// Codex document to encrypt - file: PathBuf, - - /// Password (will prompt if not provided) - #[arg(short, long)] - password: Option, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, - - /// Decrypt a password-encrypted document - Decrypt { - /// Codex document to decrypt - file: PathBuf, - - /// Password (will prompt if not provided) - #[arg(short, long)] - password: Option, - - /// Output file (default: overwrite input) - #[arg(short, long)] - output: Option, - }, -} fn main() { - let cli = Cli::parse(); + let cli = cli::Cli::parse(); // Configure color output match cli.color { - ColorChoice::Always => colored::control::set_override(true), - ColorChoice::Never => colored::control::set_override(false), - ColorChoice::Auto => {} + cli::ColorChoice::Always => colored::control::set_override(true), + cli::ColorChoice::Never => colored::control::set_override(false), + cli::ColorChoice::Auto => {} } let output_config = output::OutputConfig { @@ -437,7 +29,7 @@ fn main() { json: cli.json, }; - let result = run_command(cli.command, &output_config); + let result = dispatcher::run_command(cli.command, &output_config); if let Err(e) = result { if !cli.quiet { @@ -453,186 +45,3 @@ fn main() { std::process::exit(1); } } - -#[allow(clippy::too_many_lines)] // flat match dispatching each CLI subcommand — no shared logic to extract -fn run_command(command: Commands, output_config: &output::OutputConfig) -> Result<()> { - match command { - Commands::Create { - title, - author, - state, - input, - output: output_path, - } => commands::create::run(&title, &author, &state, input, &output_path, output_config), - - Commands::Validate { file } => commands::validate::run(&file, output_config), - - Commands::Inspect { - file, - blocks, - signatures, - provenance, - } => commands::inspect::run(&file, blocks, signatures, provenance, output_config), - - Commands::Status { file } => commands::status::run(&file, output_config), - - Commands::Sign { - file, - key, - name, - email, - algorithm, - output: output_path, - } => commands::sign::run( - &file, - &key, - &name, - email, - &algorithm, - output_path, - output_config, - ), - - Commands::Verify { file, key } => commands::verify::run(&file, &key, output_config), - - Commands::Extract { - file, - output: output_path, - content, - text, - asset, - all_assets, - } => commands::extract::run( - &file, - &output_path, - content, - text, - asset.as_deref(), - all_assets, - output_config, - ), - - Commands::Completions { shell } => { - generate(shell, &mut Cli::command(), "cdx", &mut io::stdout()); - Ok(()) - } - - Commands::SubmitReview { file, output } => { - commands::review::run(&file, output, output_config) - } - - Commands::Freeze { file, output } => commands::freeze::run(&file, output, output_config), - - Commands::Publish { file, output } => commands::publish::run(&file, output, output_config), - - Commands::Revert { file, output } => commands::revert::run(&file, output, output_config), - - Commands::Fork { file, output, note } => { - commands::fork::run(&file, &output, note, output_config) - } - - Commands::Prove { - file, - block_id, - block_index, - output, - } => commands::prove::run_prove(&file, block_id, block_index, output, output_config), - - Commands::VerifyProof { file, proof } => { - commands::prove::run_verify_proof(&file, &proof, output_config) - } - - Commands::ShowLineage { file } => commands::prove::run_show_lineage(&file, output_config), - - Commands::GetMetadata { file } => { - commands::metadata::run_get_metadata(&file, output_config) - } - - Commands::SetMetadata { - file, - title, - creator, - subject, - description, - publisher, - language, - rights, - output, - } => { - let params = commands::metadata::SetMetadataParams { - file, - title, - creator, - subject, - description, - publisher, - language, - rights, - output, - }; - commands::metadata::run_set_metadata(¶ms, output_config) - } - - Commands::Pack { - input, - output: output_path, - from_json, - } => commands::pack::run(&input, &output_path, from_json, output_config), - - Commands::Diff { file1, file2 } => commands::diff::run(&file1, &file2, output_config), - - Commands::ShowTimestamps { file } => { - commands::timestamp::run_show_timestamps(&file, output_config) - } - - Commands::VerifyTimestamps { file } => { - commands::timestamp::run_verify_timestamps(&file, output_config) - } - - Commands::AddTimestamp { - file, - method, - authority, - token, - time, - transaction_id, - output, - } => { - let params = commands::timestamp::AddTimestampParams { - file, - method, - authority, - token, - time, - transaction_id, - _output: output, - }; - commands::timestamp::run_add_timestamp(¶ms, output_config) - } - - Commands::TimestampAcquire { - file, - method, - server, - output, - } => commands::timestamp::run_acquire_timestamp( - &file, - method.as_deref(), - server.as_deref(), - output, - output_config, - ), - - Commands::Encrypt { - file, - password, - output, - } => commands::encrypt::run(&file, password, output, output_config), - - Commands::Decrypt { - file, - password, - output, - } => commands::decrypt::run(&file, password, output, output_config), - } -}