1use anyhow::{Context, Result};
4use async_compression::tokio::bufread::GzipDecoder;
5use async_compression::tokio::write::GzipEncoder;
6use async_tar::Archive;
7use spin_common::ui::quoted_path;
8use std::path::{Path, PathBuf};
9
10pub async fn archive(source: &Path, working_dir: &Path) -> Result<PathBuf> {
12 let tar_gz_path = working_dir
14 .join(source.file_name().unwrap())
15 .with_extension("tar.gz");
16 let tar_gz = tokio::fs::File::create(tar_gz_path.as_path())
17 .await
18 .context(format!(
19 "Unable to create tar archive for source {}",
20 quoted_path(source)
21 ))?;
22
23 let tar_gz_enc = GzipEncoder::new(tar_gz);
26
27 let mut tar_builder = async_tar::Builder::new(
29 tokio_util::compat::TokioAsyncWriteCompatExt::compat_write(tar_gz_enc),
30 );
31 tar_builder
32 .append_dir_all(".", source)
33 .await
34 .context(format!(
35 "Unable to create tar archive for source {}",
36 quoted_path(source)
37 ))?;
38 tar_builder.finish().await?;
40 use tokio::io::AsyncWriteExt;
42 tar_builder
43 .into_inner()
44 .await?
45 .into_inner()
46 .shutdown()
47 .await?;
48 Ok(tar_gz_path)
49}
50
51pub async fn unarchive(source: &Path, dest: &Path) -> Result<()> {
53 let decoder = GzipDecoder::new(tokio::io::BufReader::new(
54 tokio::fs::File::open(source).await?,
55 ));
56 let archive = Archive::new(tokio_util::compat::TokioAsyncReadCompatExt::compat(decoder));
57 if let Err(e) = archive.unpack(dest).await {
58 return Err(e.into());
59 };
60 Ok(())
61}