Refactor: Simplify untar with new enum Op

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-06-12 17:03:39 +10:00
parent b2c34137cc
commit 17fcac7e63
No known key found for this signature in database
GPG key ID: 591C0B03040416D6
2 changed files with 33 additions and 29 deletions

View file

@ -225,8 +225,7 @@ where
extract_compressed_from_readable::<DummyVisitor, _>( extract_compressed_from_readable::<DummyVisitor, _>(
ReadableRx::new(&mut rx), ReadableRx::new(&mut rx),
fmt, fmt,
&path, Op::UnpackToPath(&path),
None,
) )
}) })
.await .await
@ -246,12 +245,7 @@ where
extract_impl(stream, move |mut rx| { extract_impl(stream, move |mut rx| {
fs::create_dir_all(path.parent().unwrap())?; fs::create_dir_all(path.parent().unwrap())?;
extract_compressed_from_readable( extract_compressed_from_readable(ReadableRx::new(&mut rx), fmt, Op::Visit(&mut visitor))?;
ReadableRx::new(&mut rx),
fmt,
&*path,
Some(&mut visitor),
)?;
Ok(visitor) Ok(visitor)
}) })

View file

@ -23,23 +23,28 @@ impl<V: TarEntriesVisitor> TarEntriesVisitor for &mut V {
} }
} }
#[derive(Debug)]
pub(super) enum Op<'a, V: TarEntriesVisitor> {
UnpackToPath(&'a Path),
Visit(V),
}
/// * `f` - If Some, then this function will pass /// * `f` - If Some, then this function will pass
/// the entries of the `dat` to it and let it decides /// the entries of the `dat` to it and let it decides
/// what to do with the tar. /// what to do with the tar.
fn untar<R: Read, V: TarEntriesVisitor>( fn untar<R: Read, V: TarEntriesVisitor>(dat: R, op: Op<'_, V>) -> Result<(), BinstallError> {
dat: R,
path: &Path,
visitor: Option<V>,
) -> Result<(), BinstallError> {
let mut tar = Archive::new(dat); let mut tar = Archive::new(dat);
if let Some(mut visitor) = visitor { match op {
debug!("Untaring with filter"); Op::Visit(mut visitor) => {
debug!("Untaring with callback");
visitor.visit(tar.entries()?)?; visitor.visit(tar.entries()?)?;
} else { }
debug!("Untaring entire tar"); Op::UnpackToPath(path) => {
tar.unpack(path)?; debug!("Untaring entire tar");
tar.unpack(path)?;
}
} }
debug!("Untaring completed"); debug!("Untaring completed");
@ -57,42 +62,47 @@ fn untar<R: Read, V: TarEntriesVisitor>(
pub(super) fn extract_compressed_from_readable<V: TarEntriesVisitor, R: BufRead>( pub(super) fn extract_compressed_from_readable<V: TarEntriesVisitor, R: BufRead>(
dat: R, dat: R,
fmt: TarBasedFmt, fmt: TarBasedFmt,
path: &Path, op: Op<'_, V>,
visitor: Option<V>,
) -> Result<(), BinstallError> { ) -> Result<(), BinstallError> {
use TarBasedFmt::*; use TarBasedFmt::*;
let msg = if let Op::UnpackToPath(path) = op {
format!("destination: {path:#?}")
} else {
"process in-memory".to_string()
};
match fmt { match fmt {
Tar => { Tar => {
// Extract to install dir // Extract to install dir
debug!("Extracting from tar archive to `{path:?}`"); debug!("Extracting from tar archive: {msg}");
untar(dat, path, visitor)? untar(dat, op)?
} }
Tgz => { Tgz => {
// Extract to install dir // Extract to install dir
debug!("Decompressing from tgz archive to `{path:?}`"); debug!("Decompressing from tgz archive {msg}");
let tar = GzDecoder::new(dat); let tar = GzDecoder::new(dat);
untar(tar, path, visitor)?; untar(tar, op)?;
} }
Txz => { Txz => {
// Extract to install dir // Extract to install dir
debug!("Decompressing from txz archive to `{path:?}`"); debug!("Decompressing from txz archive {msg}");
let tar = XzDecoder::new(dat); let tar = XzDecoder::new(dat);
untar(tar, path, visitor)?; untar(tar, op)?;
} }
Tzstd => { Tzstd => {
// Extract to install dir // Extract to install dir
debug!("Decompressing from tzstd archive to `{path:?}`"); debug!("Decompressing from tzstd archive {msg}");
// The error can only come from raw::Decoder::with_dictionary // The error can only come from raw::Decoder::with_dictionary
// as of zstd 0.10.2 and 0.11.2, which is specified // as of zstd 0.10.2 and 0.11.2, which is specified
// as &[] by ZstdDecoder::new, thus ZstdDecoder::new // as &[] by ZstdDecoder::new, thus ZstdDecoder::new
// should not return any error. // should not return any error.
let tar = ZstdDecoder::with_buffer(dat)?; let tar = ZstdDecoder::with_buffer(dat)?;
untar(tar, path, visitor)?; untar(tar, op)?;
} }
}; };