#[cfg(not(feature = "zip"))]
use std::path::Path;
use std::path::PathBuf;
use super::ToolCache;
use crate::ToolCacheError;
impl ToolCache {
pub async fn extract_archive(
&self,
archive: &PathBuf,
output: &PathBuf,
) -> Result<(), ToolCacheError> {
let Some(extension) = archive.extension() else {
return Err(ToolCacheError::IoError(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Unknown archive format",
)));
};
match extension.to_str() {
Some("zip") => self.extract_zip(archive, output).await,
Some("gz") | Some("tgz") => self.extract_targz(archive, output).await,
Some("tar") => self.extract_tarball(archive, output).await,
_ => Err(ToolCacheError::IoError(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Unknown archive format",
)))?,
}
}
#[cfg(feature = "tarball")]
async fn extract_targz(
&self,
tarball: &PathBuf,
output: &PathBuf,
) -> Result<(), ToolCacheError> {
log::debug!("Extracting tarball gzip: {:?}", tarball);
let file = std::fs::File::open(tarball)?;
let decoder = flate2::read::GzDecoder::new(file);
let mut archive = tar::Archive::new(decoder);
archive.set_preserve_permissions(true);
archive.unpack(output)?;
Ok(())
}
#[cfg(not(feature = "tarball"))]
async fn extract_targz(
&self,
tarball: &PathBuf,
output: &PathBuf,
) -> Result<(), ToolCacheError> {
tokio::process::Command::new("tar")
.arg("-xzf")
.arg(tarball)
.arg("-C")
.arg(output)
.spawn()?
.wait()
.await?;
if !output.exists() {
return Err(ToolCacheError::IoError(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Failed to extract tarball",
)));
}
Ok(())
}
#[cfg(feature = "tarball")]
async fn extract_tarball(
&self,
tarball: &PathBuf,
output: &PathBuf,
) -> Result<(), ToolCacheError> {
log::debug!("Extracting tarball: {:?}", tarball);
let file = std::fs::File::open(tarball)?;
let mut archive = tar::Archive::new(file);
archive.unpack(output)?;
Ok(())
}
#[cfg(not(feature = "tarball"))]
async fn extract_tarball(
&self,
tarball: &PathBuf,
output: &PathBuf,
) -> Result<(), ToolCacheError> {
tokio::process::Command::new("tar")
.arg("-xf")
.arg(tarball)
.arg("-C")
.arg(output)
.spawn()?
.wait()
.await?;
if !output.exists() {
return Err(ToolCacheError::IoError(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Failed to extract tarball",
)));
}
Ok(())
}
#[cfg(feature = "zip")]
async fn extract_zip(&self, zipfile: &PathBuf, output: &PathBuf) -> Result<(), ToolCacheError> {
log::debug!("Extracting zipfile: {:?}", zipfile);
let file = std::fs::File::open(zipfile)?;
let mut archive = zip::ZipArchive::new(file)?;
archive.extract(output)?;
Ok(())
}
#[cfg(not(feature = "zip"))]
async fn extract_zip(&self, zipfile: &Path, output: &PathBuf) -> Result<(), ToolCacheError> {
tokio::process::Command::new("unzip")
.arg(zipfile.display().to_string())
.arg("-d")
.arg(output)
.spawn()?
.wait()
.await?;
if !output.exists() {
return Err(ToolCacheError::IoError(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Failed to extract zip file",
)));
}
Ok(())
}
}