diff options
Diffstat (limited to 'src/bin/butck.rs')
| -rw-r--r-- | src/bin/butck.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/bin/butck.rs b/src/bin/butck.rs new file mode 100644 index 0000000..6a81fbb --- /dev/null +++ b/src/bin/butck.rs @@ -0,0 +1,109 @@ +use std::process::exit; + +use butchunker::{ + chunker::{ + context::ButckContext, + entry::{entry, print_help, print_version}, + rw::error::{ButckRWError, ButckRWErrorKind}, + }, + log::init_logger, + special_argument, special_flag, +}; +use just_progress::{progress, renderer}; +use log::error; +use tokio::join; + +#[tokio::main] +async fn main() { + // Collect arguments + let mut args: Vec<String> = 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| renderer.update(name, state)); + join!( + async { + handle_entry_result(entry(ctx, args).await); + 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 <PATH>` to specify or init butck storage"); + } + ButckRWErrorKind::ChunkingPolicyNotSpecified => { + error!("Chunking policy not specified"); + error!("Use `--policy <policy_name>` 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"), + }, + } +} |
