use std::path::Path;
use async_zip::base::read::seek::ZipFileReader;
use tokio::io::{AsyncRead, AsyncSeek};
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
use crate::ExtractError;
use super::shared::{DEFAULT_BUF_SIZE, extract_tar_zst_entry};
pub async fn extract_conda(
reader: impl AsyncRead + AsyncSeek + Send + Unpin + 'static,
destination: &Path,
) -> Result<(), ExtractError> {
tokio::fs::create_dir_all(destination)
.await
.map_err(ExtractError::CouldNotCreateDestination)?;
let destination = destination.to_owned();
let mut compat_reader = reader.compat();
let mut buf_reader =
futures::io::BufReader::with_capacity(DEFAULT_BUF_SIZE, &mut compat_reader);
let mut zip_reader = ZipFileReader::new(&mut buf_reader)
.await
.map_err(|e| ExtractError::IoError(std::io::Error::other(e)))?;
let num_entries = zip_reader.file().entries().len();
for index in 0..num_entries {
let entry = zip_reader.file().entries().get(index).ok_or_else(|| {
ExtractError::IoError(std::io::Error::new(
std::io::ErrorKind::NotFound,
"entry not found",
))
})?;
let filename = entry.filename().as_str().map_err(|e| {
ExtractError::IoError(std::io::Error::new(std::io::ErrorKind::InvalidData, e))
})?;
if filename.ends_with(".tar.zst") {
let entry_reader = zip_reader
.reader_with_entry(index)
.await
.map_err(|e| ExtractError::IoError(std::io::Error::other(e)))?;
let mut compat_entry = entry_reader.compat();
extract_tar_zst_entry(&mut compat_entry, &destination).await?;
}
}
Ok(())
}