use std::process::exit; use butchunker::{ chunker::{ context::ButckContext, rw::error::{ButckRWError, ButckRWErrorKind}, }, entry::{entry, print_help, print_version}, special_argument, special_flag, utils::log::init_logger, }; use just_progress::{progress, renderer}; use log::error; use tokio::join; #[tokio::main] async fn main() { // Collect arguments let mut args: Vec = std::env::args().skip(1).collect(); let version = special_flag!(args, "-v", "--version"); let help = special_flag!(args, "-h", "--help"); if version { print_version(); exit(0) } // Special arguments, early return if help || args.is_empty() { print_help(); exit(0) } // Init colored #[cfg(windows)] colored::control::set_virtual_terminal(true).unwrap(); // Output control flags let quiet = special_flag!(args, "-q", "--quiet"); let no_progress = special_flag!(args, "-np", "--no-progress"); // Logger if !quiet { let logger_level = match special_argument!(args, "-l", "--log-level") { Some(level) => match level.trim().to_lowercase().as_str() { "trace" => log::LevelFilter::Trace, "debug" => log::LevelFilter::Debug, "info" => log::LevelFilter::Info, "warn" => log::LevelFilter::Warn, "error" => log::LevelFilter::Error, _ => log::LevelFilter::Info, }, None => log::LevelFilter::Info, }; init_logger(Some(logger_level)); } let ctx = ButckContext::from_args(args.clone()); // When `--no-progress` or `--quiet` is enabled, // the progress system will not be initialized if no_progress || quiet { handle_entry_result(entry(ctx, args).await); } else { let progress = progress::init(); let renderer = renderer::ProgressSimpleRenderer::new().with_subprogress(true); let bind = progress::bind(progress, move |name, state| { if state.progress() > 0. { renderer.update(name, state) } }); join!( async { handle_entry_result(entry(ctx, args).await); progress::clear_all(); progress::close(); }, bind ); } } fn handle_entry_result(r: Result<(), ButckRWError>) { match r { Ok(_) => {} Err(e) => match e.kind() { ButckRWErrorKind::NoButckStorageFound => { error!("No butck storage found"); error!("Use `--storage ` to specify or init butck storage"); } ButckRWErrorKind::ChunkingPolicyNotSpecified => { error!("Chunking policy not specified"); error!("Use `--policy ` to specify chunking policy"); error!("or use `butck policies` to output the available policies"); } ButckRWErrorKind::ReadingMethodAmbiguous => error!("Reading method ambiguous"), ButckRWErrorKind::OutputCountMismatch => { error!("Output count mismatch"); error!("When processing a single file, use `--output-file` to specify output path"); error!( "When processing multiple files, use `--output-dir` to specify output directory" ); } ButckRWErrorKind::ChunkNotFound(chunk_id) => { error!("Chunk not found in storage: {}", chunk_id) } ButckRWErrorKind::RebuildFailed(reason) => error!("Failed to rebuild file: {}", reason), ButckRWErrorKind::ChunkFailed(_chunk_failed) => error!("Chunk failed"), ButckRWErrorKind::IOError(error) => error!("IO error: {}", error), ButckRWErrorKind::InvalidBidxFormat => error!("Invalid bidx format"), ButckRWErrorKind::ChunkingFailed(reason) => error!("Chunking failed: {}", reason), ButckRWErrorKind::IndexFileWriteFailed(reason) => { error!("Failed to write index file: {}", reason) } }, } }