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