use crate::filter::FileFilter;
use crate::formats::{
gz::GzipFormat, sevenz::SevenZFormat, xz::XzFormat, zip::ZipFormat, zstd::ZstdFormat,
CompressionFormat, CompressionOptions, CompressionStats, Format,
};
use crate::progress::Progress;
use crate::Result;
use std::path::Path;
pub fn compress(
input_path: &Path,
output_path: &Path,
options: CompressionOptions,
filter: FileFilter,
show_progress: bool,
verbose: bool,
format_override: Option<Format>,
) -> Result<CompressionStats> {
if verbose {
println!(
"compressing {} to {}",
input_path.display(),
output_path.display()
);
}
let format = format_override
.map(Ok)
.unwrap_or_else(|| detect_output_format(output_path))?;
if verbose {
println!("using {} format", format.name());
}
let total_size = crate::utils::calculate_directory_size(input_path, &filter)?;
let progress = Progress::new(show_progress, total_size);
let stats = match format {
Format::Zstd => {
ZstdFormat::compress(input_path, output_path, &options, &filter, Some(&progress))?
}
Format::Gzip => {
GzipFormat::compress(input_path, output_path, &options, &filter, Some(&progress))?
}
Format::Xz => {
XzFormat::compress(input_path, output_path, &options, &filter, Some(&progress))?
}
Format::Zip => {
ZipFormat::compress(input_path, output_path, &options, &filter, Some(&progress))?
}
Format::SevenZ => {
SevenZFormat::compress(input_path, output_path, &options, &filter, Some(&progress))?
}
};
progress.finish();
if verbose {
println!(
"compressed {} ({}) -> {} ({}) ratio {:.2}",
input_path.display(),
crate::utils::format_bytes(stats.input_size),
output_path.display(),
crate::utils::format_bytes(stats.output_size),
stats.compression_ratio
);
}
Ok(stats)
}
fn detect_output_format(output_path: &Path) -> Result<Format> {
Format::from_extension(output_path).ok_or_else(|| {
anyhow::anyhow!(
"cannot determine compression format from extension: {}",
output_path.display()
)
})
}