pub mod backends;
mod job;
pub mod progress;
#[cfg(test)]
pub mod test_utils;
pub mod utils;
use backends::*;
use clap::{CommandFactory, Parser, Subcommand};
use clap_complete::Shell;
use job::{Action, get_job};
use utils::*;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct CmprssArgs {
#[command(subcommand)]
format: Option<Format>,
#[clap(flatten)]
pub base_args: CommonArgs,
}
#[derive(Subcommand, Debug)]
enum Format {
Tar(TarArgs),
#[clap(visible_alias = "gz")]
Gzip(GzipArgs),
Xz(XzArgs),
#[clap(visible_alias = "bz2")]
Bzip2(Bzip2Args),
Zip(ZipArgs),
#[clap(visible_alias = "zst")]
Zstd(ZstdArgs),
Lz4(Lz4Args),
#[clap(visible_alias = "br")]
Brotli(BrotliArgs),
#[clap(visible_alias = "sz")]
Snappy(SnappyArgs),
Lzma(LzmaArgs),
#[clap(name = "7z", visible_alias = "sevenz")]
SevenZ(SevenZArgs),
#[clap(hide = true)]
Completions {
#[arg(value_enum)]
shell: Shell,
},
#[clap(hide = true)]
Manpage,
}
fn take_format_prefix(io_list: &mut Vec<String>) -> Option<Box<dyn Compressor>> {
let first = io_list.first()?;
if std::path::Path::new(first).exists() {
return None;
}
let chain = chain_from_format_str(first)?;
let format = first.clone();
io_list.remove(0);
Some(Box::new(Pipeline::with_format(chain, format)))
}
fn write_completions(shell: Shell) -> Result {
let mut cmd = CmprssArgs::command();
clap_complete::generate(shell, &mut cmd, "cmprss", &mut std::io::stdout());
Ok(())
}
fn write_manpage() -> Result {
let cmd = CmprssArgs::command();
clap_mangen::Man::new(cmd).render(&mut std::io::stdout())?;
Ok(())
}
fn command(compressor: Option<Box<dyn Compressor>>, args: &CommonArgs) -> Result {
let job = get_job(compressor, args)?;
match job.action {
Action::Compress => job.compressor.compress(job.input, job.output),
Action::Extract => job.compressor.extract(job.input, job.output),
Action::List => job.compressor.list(job.input),
Action::Append => job.compressor.append(job.input, job.output),
}
}
fn main() {
let args = CmprssArgs::parse();
match args.format {
Some(Format::Tar(a)) => command(Some(Box::new(Tar::new(&a))), &a.common_args),
Some(Format::Gzip(a)) => command(Some(Box::new(Gzip::new(&a))), &a.common_args),
Some(Format::Xz(a)) => command(Some(Box::new(Xz::new(&a))), &a.common_args),
Some(Format::Bzip2(a)) => command(Some(Box::new(Bzip2::new(&a))), &a.common_args),
Some(Format::Zip(a)) => command(Some(Box::new(Zip::new(&a))), &a.common_args),
Some(Format::Zstd(a)) => command(Some(Box::new(Zstd::new(&a))), &a.common_args),
Some(Format::Lz4(a)) => command(Some(Box::new(Lz4::new(&a))), &a.common_args),
Some(Format::Brotli(a)) => command(Some(Box::new(Brotli::new(&a))), &a.common_args),
Some(Format::Snappy(a)) => command(Some(Box::new(Snappy::new(&a))), &a.common_args),
Some(Format::Lzma(a)) => command(Some(Box::new(Lzma::new(&a))), &a.common_args),
Some(Format::SevenZ(a)) => command(Some(Box::new(SevenZ::new(&a))), &a.common_args),
Some(Format::Completions { shell }) => write_completions(shell),
Some(Format::Manpage) => write_manpage(),
None => {
let mut base_args = args.base_args;
let compressor = take_format_prefix(&mut base_args.io_list);
command(compressor, &base_args)
}
}
.unwrap_or_else(|e| {
eprintln!("ERROR(cmprss): {}", e);
std::process::exit(1);
});
}