use fs_err as fs;
use rattler_conda_types::package::CondaArchiveType;
use std::path::{Path, PathBuf};
fn folder_from_tar_bz2(
archive_path: &Path,
find_path: &Path,
dest_folder: &Path,
) -> Result<(), std::io::Error> {
let reader = fs::File::open(archive_path)?;
let mut archive = rattler_package_streaming::read::stream_tar_bz2(reader);
archive.set_preserve_permissions(true);
for entry in archive.entries()? {
let mut entry = entry?;
let path = entry.path()?;
if let Ok(stripped_path) = path.strip_prefix(find_path) {
let dest_file = dest_folder.join(stripped_path);
if let Some(parent_folder) = dest_file.parent()
&& !parent_folder.exists()
{
fs::create_dir_all(parent_folder)?;
}
entry.unpack(dest_file)?;
}
}
Ok(())
}
fn folder_from_conda(
archive_path: &Path,
find_path: &Path,
dest_folder: &Path,
) -> Result<(), std::io::Error> {
let reader = fs::File::open(archive_path)?;
let mut archive = if find_path.starts_with("info") {
rattler_package_streaming::seek::stream_conda_info(reader)
.expect("Could not open conda file")
} else {
todo!("Not implemented yet");
};
archive.set_preserve_permissions(true);
for entry in archive.entries()? {
let mut entry = entry?;
let path = entry.path()?;
if let Ok(stripped_path) = path.strip_prefix(find_path) {
let dest_file = dest_folder.join(stripped_path);
if let Some(parent_folder) = dest_file.parent()
&& !parent_folder.exists()
{
fs::create_dir_all(parent_folder)?;
}
entry.unpack(dest_file)?;
}
}
Ok(())
}
pub fn extract_recipe(package: &Path, dest_folder: &Path) -> Result<(), std::io::Error> {
let archive_type = CondaArchiveType::try_from(package).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"package does not point to valid archive",
)
})?;
let path = PathBuf::from("info/recipe");
match archive_type {
CondaArchiveType::TarBz2 => folder_from_tar_bz2(package, &path, dest_folder)?,
CondaArchiveType::Conda => folder_from_conda(package, &path, dest_folder)?,
};
Ok(())
}