znippy-cli 0.5.0

CLI for Znippy, a parallel chunked compression system.
// znippy-cli/src/main.rs

use anyhow::Result;
use clap::{Parser, Subcommand};
use std::path::PathBuf;

use znippy_common::{VerifyReport, list_archive_contents, verify_archive_integrity};
use znippy_compress::compress_dir;
use znippy_decompress::decompress_archive;

#[derive(Parser)]
#[command(name = "znippy")]
#[command(about = "Znippy: fast archive format with per-file compression", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Compress a directory into a .znippy archive
    Compress {
        #[arg(short, long)]
        input: PathBuf,

        #[arg(short, long)]
        output: PathBuf,

        #[arg(long)]
        no_skip: bool,
    },

    /// Decompress a .znippy archive
    Decompress {
        #[arg(short, long)]
        input: PathBuf,

        #[arg(short, long)]
        output: PathBuf,
    },

    /// List contents of a .znippy archive
    List {
        #[arg(short, long)]
        input: PathBuf,
    },

    /// Verify archive integrity (checksum)
    Verify {
        #[arg(short, long)]
        input: PathBuf,
    },
}

pub fn run() -> Result<()> {
    env_logger::init();
    let cli = Cli::parse();

    match cli.command {
        Commands::Compress {
            input,
            output,
            no_skip,
        } => {
            let report = compress_dir(&input, &output, no_skip)?;
            println!("\nβœ… Komprimering klar:");
            println!("πŸ“ Totalt antal filer:         {}", report.total_files);
            println!("πŸ“ Totalt antal chunks:         {}", report.chunks);

            println!("πŸ“‚ Totalt antal kataloger:     {}", report.total_dirs);
            println!("πŸ“¦ Filer komprimerade:         {}", report.compressed_files);
            println!(
                "πŸ“„ Filer ej komprimerade:      {}",
                report.uncompressed_files
            );
            println!("πŸ“₯ Totalt inlΓ€sta bytes:       {}", report.total_bytes_in);
            println!("πŸ“€ Totalt skrivna bytes:       {}", report.total_bytes_out);
            println!("πŸ“‰ Bytes som komprimerades:    {}", report.compressed_bytes);
            println!(
                "πŸ“ƒ Bytes ej komprimerade:      {}",
                report.uncompressed_bytes
            );
            println!(
                "πŸ“Š Komprimeringsgrad:          {:.2}%",
                report.compression_ratio
            );
        }

        Commands::Decompress { input, output } => {
            let report: VerifyReport = decompress_archive(&input, &output)?;
            println!("\nβœ… Dekomprimering och verifiering klar:");
            println!("πŸ“ Totala filer:       {}", report.total_files);
            println!("πŸ” Verifierade filer:  {}", report.verified_files);
            println!("πŸ“₯  chunks:    {}", report.chunks);
            println!("❌ Korrupta filer:     {}", report.corrupt_files);
            println!("πŸ“₯ Totala bytes:       {}", report.total_bytes);
            println!("πŸ“€ Verifierade bytes:  {}", report.verified_bytes);
            println!("⚠️  Korrupta bytes:    {}", report.corrupt_bytes);
        }

        Commands::List { input } => {
            list_archive_contents(&input)?;
        }

        Commands::Verify { input } => {
            let report: VerifyReport = verify_archive_integrity(&input)?;
            println!("\nπŸ” Verifiering klar:");
            println!("πŸ“ Totala filer:       {}", report.total_files);
            println!("πŸ” Verifierade filer:  {}", report.verified_files);
            println!("❌ Korrupta filer:     {}", report.corrupt_files);
            println!("πŸ“₯ Totala bytes:       {}", report.total_bytes);
            println!("πŸ“€ Verifierade bytes:  {}", report.verified_bytes);
            println!("⚠️  Korrupta bytes:    {}", report.corrupt_bytes);
        }
    }

    Ok(())
}