Skip to content

Commit

Permalink
feat: standalone gz
Browse files Browse the repository at this point in the history
  • Loading branch information
jondot committed Dec 1, 2022
1 parent 23cfdbf commit 651effa
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 3 deletions.
3 changes: 2 additions & 1 deletion decompress/Cargo.toml
Expand Up @@ -13,14 +13,15 @@ readme = "../README.md"

[features]
default = ["all"]
all = ["tarball", "tarxz", "targz", "tarbz", "tarzst", "zip", "ar"]
all = ["tarball", "tarxz", "targz", "tarbz", "tarzst", "zip", "ar", "gz"]

tarball = ["dep:tar"]
tarzst = ["tarball", "dep:zstd"]
targz = ["tarball", "dep:flate2"]
tarbz = ["tarball", "dep:bzip2"]
tarxz = ["tarball", "dep:xz"]
zip = ["dep:zip"]
gz = ["dep:flate2"]
ar = ["dep:ar"]

[dependencies]
Expand Down
54 changes: 54 additions & 0 deletions decompress/src/decompressors/gz.rs
@@ -0,0 +1,54 @@
use crate::{DecompressError, Decompression, Decompressor, ExtractOpts};
use lazy_static::lazy_static;
use regex::Regex;
use std::{fs, io};
use std::{fs::File, io::BufReader, path::Path};

lazy_static! {
static ref RE: Regex = Regex::new(r"(?i)\.gz$").unwrap();
}

#[derive(Default)]
pub struct Gz {
re: Option<Regex>,
}

impl Gz {
#[must_use]
pub fn new(re: Option<Regex>) -> Self {
Self { re }
}
#[must_use]
pub fn build(re: Option<Regex>) -> Box<Self> {
Box::new(Self::new(re))
}
}

impl Decompressor for Gz {
fn test(&self, archive: &Path) -> bool {
archive
.file_name()
.and_then(std::ffi::OsStr::to_str)
.map_or(false, |f| self.re.as_ref().unwrap_or(&*RE).is_match(f))
}

fn decompress(
&self,
archive: &Path,
to: &Path,
_opts: &ExtractOpts,
) -> Result<Decompression, DecompressError> {
let fd = BufReader::new(File::open(archive)?);
let dec = flate2::bufread::GzDecoder::new(fd);
if !Path::new(to).exists() {
let _res = fs::create_dir_all(to);
}
let mut outfile =
fs::File::create(&to.join(archive.file_stem().ok_or_else(|| {
DecompressError::Error("cannot compose a file name".to_string())
})?))?;

io::copy(&mut BufReader::new(dec), &mut outfile)?;
Ok(Decompression { id: "gz" })
}
}
3 changes: 3 additions & 0 deletions decompress/src/decompressors/mod.rs
Expand Up @@ -13,6 +13,9 @@ pub mod tarxz;
#[cfg(feature = "tarbz")]
pub mod tarbz;

#[cfg(feature = "gz")]
pub mod gz;

#[cfg(feature = "targz")]
pub mod targz;

Expand Down
8 changes: 6 additions & 2 deletions decompress/src/lib.rs
Expand Up @@ -72,10 +72,10 @@ impl Default for Decompress {
fn default() -> Self {
Self {
decompressors: vec![
#[cfg(feature = "targz")]
Box::<decompressors::targz::Targz>::default(),
#[cfg(feature = "zip")]
Box::<decompressors::zip::Zip>::default(),
#[cfg(feature = "targz")]
Box::<decompressors::targz::Targz>::default(),
#[cfg(feature = "tarball")]
Box::<decompressors::tarball::Tarball>::default(),
#[cfg(feature = "tarxz")]
Expand All @@ -84,6 +84,10 @@ impl Default for Decompress {
Box::<decompressors::tarbz::Tarbz>::default(),
#[cfg(feature = "tarzst")]
Box::<decompressors::tarzst::Tarzst>::default(),
// order is important, `gz` is placed only after the targz variant did not match
// if it's placed above targz, it will unpack and leave a tar archive.
#[cfg(feature = "gz")]
Box::<decompressors::gz::Gz>::default(),
#[cfg(feature = "ar")]
Box::<decompressors::ar::Ar>::default(),
],
Expand Down
1 change: 1 addition & 0 deletions decompress/tests/archives_test.rs
Expand Up @@ -28,6 +28,7 @@ use rstest::rstest;
#[case("inner.tar.zst", "inner_zst_1", 1)]
#[case("inner.tar.bz2", "inner_bz2_1", 1)]
#[case("bare.ar", "bare_ar", 0)]
#[case("sub.txt.gz", "gz_1", 0)]
#[trace]
fn test_archives(#[case] archive: &str, #[case] outdir: &str, #[case] strip: usize) {
dec_test(&Decompress::default(), archive, outdir, strip).unwrap();
Expand Down
1 change: 1 addition & 0 deletions decompress/tests/expected/gz_1/sub.txt
@@ -0,0 +1 @@
I'm in a subfolder
Binary file added decompress/tests/fixtures/sub.txt.gz
Binary file not shown.

0 comments on commit 651effa

Please sign in to comment.