cargo-binstall/src/helpers/extracter.rs
Jiahao XU be5e8616a2
Impl new fn helpers::extracter::untar
Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2022-06-09 13:15:23 +10:00

102 lines
2.7 KiB
Rust

use std::borrow::Cow;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use flate2::read::GzDecoder;
use log::debug;
use tar::Archive;
use xz2::read::XzDecoder;
use zip::read::ZipArchive;
use zstd::stream::Decoder as ZstdDecoder;
use crate::{BinstallError, PkgFmt};
fn untar(
dat: impl Read,
path: &Path,
desired_outputs: Option<&[Cow<'_, Path>]>,
) -> Result<(), BinstallError> {
let mut tar = Archive::new(dat);
if let Some(desired_outputs) = desired_outputs {
for res in tar.entries()? {
let mut entry = res?;
let entry_path = entry.path()?;
if desired_outputs.contains(&entry_path) {
let dst = path.join(entry_path);
entry.unpack(dst)?;
}
}
} else {
tar.unpack(path)?;
}
Ok(())
}
/// Extract files from the specified source onto the specified path.
///
/// * `fmt` - must not be `PkgFmt::Bin` or `PkgFmt::Zip`.
pub(crate) fn extract_compressed_from_readable(
dat: impl Read,
fmt: PkgFmt,
path: &Path,
) -> Result<(), BinstallError> {
match fmt {
PkgFmt::Tar => {
// Extract to install dir
debug!("Extracting from tar archive to `{path:?}`");
let mut tar = Archive::new(dat);
tar.unpack(path)?;
}
PkgFmt::Tgz => {
// Extract to install dir
debug!("Decompressing from tgz archive to `{path:?}`");
let tar = GzDecoder::new(dat);
let mut tgz = Archive::new(tar);
tgz.unpack(path)?;
}
PkgFmt::Txz => {
// Extract to install dir
debug!("Decompressing from txz archive to `{path:?}`");
let tar = XzDecoder::new(dat);
let mut txz = Archive::new(tar);
txz.unpack(path)?;
}
PkgFmt::Tzstd => {
// Extract to install dir
debug!("Decompressing from tzstd archive to `{path:?}`");
// The error can only come from raw::Decoder::with_dictionary
// as of zstd 0.10.2 and 0.11.2, which is specified
// as &[] by ZstdDecoder::new, thus ZstdDecoder::new
// should not return any error.
let tar = ZstdDecoder::new(dat)?;
let mut txz = Archive::new(tar);
txz.unpack(path)?;
}
PkgFmt::Zip => panic!("Unexpected PkgFmt::Zip!"),
PkgFmt::Bin => panic!("Unexpected PkgFmt::Bin!"),
};
Ok(())
}
pub(crate) fn unzip(dat: File, dst: &Path) -> Result<(), BinstallError> {
debug!("Decompressing from zip archive to `{dst:?}`");
let mut zip = ZipArchive::new(dat)?;
zip.extract(dst)?;
Ok(())
}