Rewrite untar to take a visitor & simplify

signature of `download_and_extract_with_filter`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-06-11 20:31:46 +10:00
parent 5a43ee2681
commit 90a96cabc9
No known key found for this signature in database
GPG key ID: 591C0B03040416D6
4 changed files with 64 additions and 38 deletions

View file

@ -1,11 +1,14 @@
use std::fmt::Debug;
use std::fs;
use std::io::{self, Seek, Write};
use std::path::Path;
use std::io::{self, Read, Seek, Write};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use bytes::Bytes;
use futures_util::stream::{Stream, StreamExt};
use log::debug;
use scopeguard::{guard, ScopeGuard};
use tar::Entries;
use tempfile::tempfile;
use tokio::{
sync::mpsc,
@ -209,17 +212,42 @@ pub async fn extract_tar_based_stream_with_filter<
stream: impl Stream<Item = Result<Bytes, E>> + Unpin,
output: &Path,
fmt: TarBasedFmt,
filter: Option<Filter>,
filter: Filter,
) -> Result<(), BinstallError>
where
BinstallError: From<E>,
{
let path = output.to_owned();
struct Visitor<F>(F, Arc<PathBuf>);
impl<F: FnMut(&Path) -> bool + Send + 'static> TarEntriesVisitor for Visitor<F> {
fn visit<R: Read>(&mut self, entries: Entries<'_, R>) -> Result<(), BinstallError> {
for res in entries {
let mut entry = res?;
let entry_path = entry.path()?;
if self.0(&entry_path) {
debug!("Extracting {entry_path:#?}");
let dst = self.1.join(entry_path);
fs::create_dir_all(dst.parent().unwrap())?;
entry.unpack(dst)?;
}
}
Ok(())
}
}
let path = Arc::new(output.to_owned());
let visitor = Visitor(filter, path.clone());
extract_impl(stream, move |mut rx| {
fs::create_dir_all(path.parent().unwrap())?;
extract_compressed_from_readable(ReadableRx::new(&mut rx), fmt, &path, filter)
extract_compressed_from_readable(ReadableRx::new(&mut rx), fmt, &*path, Some(visitor))
})
.await
}
@ -232,12 +260,20 @@ pub async fn extract_tar_based_stream<E>(
where
BinstallError: From<E>,
{
struct DummyVisitor;
impl TarEntriesVisitor for DummyVisitor {
fn visit<R: Read>(&mut self, _entries: Entries<'_, R>) -> Result<(), BinstallError> {
unimplemented!()
}
}
let path = output.to_owned();
extract_impl(stream, move |mut rx| {
fs::create_dir_all(path.parent().unwrap())?;
extract_compressed_from_readable::<fn(&Path) -> bool, _>(
extract_compressed_from_readable::<DummyVisitor, _>(
ReadableRx::new(&mut rx),
fmt,
&path,