mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-05 02:55:31 +00:00
Add support for Gzip compression (includes .tar.gz)
This commit is contained in:
parent
bdc16fdb17
commit
3fa939ac90
@ -1,4 +1,4 @@
|
||||
use std::{fs, io::{self, Read, Write}, path::PathBuf};
|
||||
use std::{fs, io::Write, path::PathBuf};
|
||||
|
||||
use colored::Colorize;
|
||||
|
||||
@ -9,38 +9,6 @@ use super::{Compressor, Entry};
|
||||
|
||||
pub struct BzipCompressor {}
|
||||
|
||||
struct CompressorToMemory {}
|
||||
|
||||
// impl CompressorToMemory {
|
||||
// pub fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
|
||||
// let mut buffer = vec![];
|
||||
|
||||
// if files.len() != 1 {
|
||||
// eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "error".red(), format, format);
|
||||
// return Err(Error::InvalidInput);
|
||||
// }
|
||||
|
||||
// let mut contents = Vec::new();
|
||||
// let path = &files[0];
|
||||
// ensure_exists(path)?;
|
||||
|
||||
// let bytes_read = {
|
||||
// let bytes = fs::read(path)?;
|
||||
// let mut encoder = get_encoder(&format, Box::new(&mut buffer));
|
||||
// encoder.write_all(&*bytes)?;
|
||||
// bytes.as_slice().read_to_end(&mut contents)?
|
||||
// };
|
||||
|
||||
// println!("{}: compressed {:?} into memory ({} bytes)", "info".yellow(), &path, bytes_read);
|
||||
|
||||
// Ok(contents)
|
||||
// }
|
||||
|
||||
// pub fn compress_bytes(file: File) {
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
impl BzipCompressor {
|
||||
fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
|
||||
if files.len() != 1 {
|
||||
@ -82,13 +50,6 @@ impl BzipCompressor {
|
||||
}
|
||||
|
||||
// TODO: customizable compression level
|
||||
fn get_encoder<'a>(format: &CompressionFormat, buffer: Box<dyn io::Write + Send + 'a>) -> Box<dyn io::Write + Send + 'a> {
|
||||
match format {
|
||||
CompressionFormat::Bzip => Box::new(bzip2::write::BzEncoder::new(buffer, bzip2::Compression::new(4))),
|
||||
_other => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressor for BzipCompressor {
|
||||
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
|
||||
match from {
|
||||
|
@ -1,6 +1,7 @@
|
||||
mod tar;
|
||||
mod zip;
|
||||
mod bzip;
|
||||
mod tomemory;
|
||||
mod compressor;
|
||||
|
||||
pub use compressor::Compressor;
|
||||
@ -8,3 +9,4 @@ pub use self::compressor::Entry;
|
||||
pub use self::tar::TarCompressor;
|
||||
pub use self::zip::ZipCompressor;
|
||||
pub use self::bzip::BzipCompressor;
|
||||
pub use self::tomemory::GzipCompressor;
|
@ -23,25 +23,8 @@ impl TarCompressor {
|
||||
}
|
||||
};
|
||||
|
||||
// let ok = EntryType::
|
||||
println!("todo");
|
||||
|
||||
|
||||
// let mut b = Builder::new(Vec::new());
|
||||
// let mut header = Header::new_gnu();
|
||||
// let name = b"././@LongLink";
|
||||
// header.as_gnu_mut().unwrap().name[..name.len()].clone_from_slice(&name[..]);
|
||||
// header.set_mode(0o644);
|
||||
// header.set_uid(0);
|
||||
// header.set_gid(0);
|
||||
// header.set_mtime(0);
|
||||
// // + 1 to be compliant with GNU tar
|
||||
// header.set_size(size + 1);
|
||||
// header.set_entry_type(EntryType::new(entry_type));
|
||||
// header.set_cksum();
|
||||
|
||||
|
||||
|
||||
// Ok(b.into_inner()?)
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
|
97
src/compressors/tomemory.rs
Normal file
97
src/compressors/tomemory.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use std::{fs, io::{self, Read}, path::PathBuf};
|
||||
|
||||
use colored::Colorize;
|
||||
|
||||
use crate::{error::{Error, OuchResult}, extension::CompressionFormat, file::File};
|
||||
use crate::utils::ensure_exists;
|
||||
|
||||
use super::{Compressor, Entry};
|
||||
|
||||
pub struct GzipCompressor {}
|
||||
|
||||
struct CompressorToMemory {}
|
||||
|
||||
impl CompressorToMemory {
|
||||
pub fn compress_files(files: Vec<PathBuf>, format: CompressionFormat) -> OuchResult<Vec<u8>> {
|
||||
|
||||
|
||||
if files.len() != 1 {
|
||||
eprintln!("{}: cannot compress multiple files directly to {:#?}.\n Try using an intermediate archival method such as Tar.\n Example: filename.tar{}", "error".red(), format, format);
|
||||
return Err(Error::InvalidInput);
|
||||
}
|
||||
|
||||
let mut contents = Vec::new();
|
||||
let path = &files[0];
|
||||
ensure_exists(path)?;
|
||||
|
||||
let bytes_written = {
|
||||
let bytes = fs::read(path)?;
|
||||
|
||||
// let mut buffer = vec![];
|
||||
// let mut encoder = get_encoder(&format, Box::new(&mut buffer));
|
||||
// encoder.write_all(&*bytes)?;
|
||||
// bytes.as_slice().read_to_end(&mut contents)?
|
||||
Self::compress_bytes(&mut contents, bytes, format)?
|
||||
};
|
||||
|
||||
println!(
|
||||
"{}: compressed {:?} into memory ({} bytes)",
|
||||
"info".yellow(),
|
||||
&path,
|
||||
bytes_written
|
||||
);
|
||||
|
||||
Ok(contents)
|
||||
}
|
||||
|
||||
pub fn compress_file_in_memory(file: File, format:CompressionFormat ) -> OuchResult<Vec<u8>> {
|
||||
let mut compressed_contents = Vec::new();
|
||||
let file_contents = match file.contents_in_memory {
|
||||
Some(bytes) => bytes,
|
||||
None => {
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
||||
let _bytes_written = Self::compress_bytes(&mut compressed_contents, file_contents, format);
|
||||
|
||||
Ok(compressed_contents)
|
||||
}
|
||||
|
||||
pub fn compress_bytes(mut contents: &mut Vec<u8>, bytes_to_compress: Vec<u8>, format: CompressionFormat) -> OuchResult<usize> {
|
||||
let mut buffer = vec![];
|
||||
let mut encoder = get_encoder(&format, Box::new(&mut buffer));
|
||||
encoder.write_all(&*bytes_to_compress)?;
|
||||
|
||||
Ok(bytes_to_compress.as_slice().read_to_end(&mut contents)?)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn get_encoder<'a>(
|
||||
format: &CompressionFormat,
|
||||
buffer: Box<dyn io::Write + Send + 'a>,
|
||||
) -> Box<dyn io::Write + Send + 'a> {
|
||||
match format {
|
||||
CompressionFormat::Gzip => Box::new(flate2::write::GzEncoder::new(
|
||||
buffer,
|
||||
flate2::Compression::default(),
|
||||
)),
|
||||
_other => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Compressor for GzipCompressor {
|
||||
fn compress(&self, from: Entry) -> OuchResult<Vec<u8>> {
|
||||
let format = CompressionFormat::Gzip;
|
||||
match from {
|
||||
Entry::Files(files) => Ok(
|
||||
CompressorToMemory::compress_files(files, format)?
|
||||
),
|
||||
Entry::InMemory(file) => Ok(
|
||||
CompressorToMemory::compress_file_in_memory(file, format)?
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ use crate::compressors::{
|
||||
Compressor,
|
||||
TarCompressor,
|
||||
ZipCompressor,
|
||||
GzipCompressor,
|
||||
BzipCompressor,
|
||||
};
|
||||
|
||||
@ -71,6 +72,7 @@ impl Evaluator {
|
||||
CompressionFormat::Tar => Box::new(TarCompressor {}),
|
||||
CompressionFormat::Zip => Box::new(ZipCompressor {}),
|
||||
CompressionFormat::Bzip => Box::new(BzipCompressor {}),
|
||||
CompressionFormat::Gzip => Box::new(GzipCompressor {}),
|
||||
_other => todo!()
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user