ghactions_toolcache/
archives.rs1#[cfg(not(feature = "zip"))]
3use std::path::Path;
4use std::path::PathBuf;
5
6use super::ToolCache;
7use crate::ToolCacheError;
8
9impl ToolCache {
10 pub async fn extract_archive(
12 &self,
13 archive: &PathBuf,
14 output: &PathBuf,
15 ) -> Result<(), ToolCacheError> {
16 let Some(extension) = archive.extension() else {
17 return Err(ToolCacheError::IoError(std::io::Error::new(
18 std::io::ErrorKind::InvalidInput,
19 "Unknown archive format",
20 )));
21 };
22
23 match extension.to_str() {
24 Some("zip") => self.extract_zip(archive, output).await,
25 Some("gz") | Some("tgz") => self.extract_targz(archive, output).await,
26 Some("tar") => self.extract_tarball(archive, output).await,
27 _ => Err(ToolCacheError::IoError(std::io::Error::new(
28 std::io::ErrorKind::InvalidInput,
29 "Unknown archive format",
30 )))?,
31 }
32 }
33
34 #[cfg(feature = "tarball")]
37 async fn extract_targz(
38 &self,
39 tarball: &PathBuf,
40 output: &PathBuf,
41 ) -> Result<(), ToolCacheError> {
42 log::debug!("Extracting tarball gzip: {:?}", tarball);
43
44 let file = std::fs::File::open(tarball)?;
46 let decoder = flate2::read::GzDecoder::new(file);
47 let mut archive = tar::Archive::new(decoder);
48 archive.set_preserve_permissions(true);
49
50 archive.unpack(output)?;
51
52 Ok(())
53 }
54
55 #[cfg(not(feature = "tarball"))]
57 async fn extract_targz(
58 &self,
59 tarball: &PathBuf,
60 output: &PathBuf,
61 ) -> Result<(), ToolCacheError> {
62 tokio::process::Command::new("tar")
63 .arg("-xzf")
64 .arg(tarball)
65 .arg("-C")
66 .arg(output)
67 .spawn()?
68 .wait()
69 .await?;
70
71 if !output.exists() {
72 return Err(ToolCacheError::IoError(std::io::Error::new(
73 std::io::ErrorKind::NotFound,
74 "Failed to extract tarball",
75 )));
76 }
77
78 Ok(())
79 }
80
81 #[cfg(feature = "tarball")]
84 async fn extract_tarball(
85 &self,
86 tarball: &PathBuf,
87 output: &PathBuf,
88 ) -> Result<(), ToolCacheError> {
89 log::debug!("Extracting tarball: {:?}", tarball);
90
91 let file = std::fs::File::open(tarball)?;
92 let mut archive = tar::Archive::new(file);
93 archive.unpack(output)?;
94
95 Ok(())
96 }
97
98 #[cfg(not(feature = "tarball"))]
100 async fn extract_tarball(
101 &self,
102 tarball: &PathBuf,
103 output: &PathBuf,
104 ) -> Result<(), ToolCacheError> {
105 tokio::process::Command::new("tar")
106 .arg("-xf")
107 .arg(tarball)
108 .arg("-C")
109 .arg(output)
110 .spawn()?
111 .wait()
112 .await?;
113
114 if !output.exists() {
115 return Err(ToolCacheError::IoError(std::io::Error::new(
116 std::io::ErrorKind::NotFound,
117 "Failed to extract tarball",
118 )));
119 }
120
121 Ok(())
122 }
123
124 #[cfg(feature = "zip")]
125 async fn extract_zip(&self, zipfile: &PathBuf, output: &PathBuf) -> Result<(), ToolCacheError> {
127 log::debug!("Extracting zipfile: {:?}", zipfile);
128
129 let file = std::fs::File::open(zipfile)?;
130 let mut archive = zip::ZipArchive::new(file)?;
131 archive.extract(output)?;
132
133 Ok(())
134 }
135
136 #[cfg(not(feature = "zip"))]
140 async fn extract_zip(&self, zipfile: &Path, output: &PathBuf) -> Result<(), ToolCacheError> {
141 tokio::process::Command::new("unzip")
142 .arg(zipfile.display().to_string())
143 .arg("-d")
144 .arg(output)
145 .spawn()?
146 .wait()
147 .await?;
148
149 if !output.exists() {
150 return Err(ToolCacheError::IoError(std::io::Error::new(
151 std::io::ErrorKind::NotFound,
152 "Failed to extract zip file",
153 )));
154 }
155
156 Ok(())
157 }
158}