cli_xtask/
archive.rs

1//! Utilities for creating archives.
2
3use cargo_metadata::camino::Utf8Path;
4use flate2::{write::GzEncoder, Compression};
5
6use crate::{fs::ToRelative, Result};
7
8/// Create a `tar.gz` archive from the given paths.
9///
10/// # Examples
11///
12/// ```no_run
13/// # fn main() -> cli_xtask::Result<()> {
14/// cli_xtask::archive::create("foo.tar.gz", ["./foo/", "./bar.txt"])?;
15/// # Ok(())
16/// # }
17/// ```
18#[tracing::instrument(name = "archive::create", skip_all, err)]
19pub fn create(
20    archive_path: impl AsRef<Utf8Path>,
21    src: impl IntoIterator<Item = impl AsRef<Utf8Path>>,
22) -> Result<()> {
23    let archive = crate::fs::create_file(&archive_path)?;
24    let enc = GzEncoder::new(archive, Compression::default());
25    let mut tar = tar::Builder::new(enc);
26
27    for src in src.into_iter() {
28        let src = src.as_ref();
29        if src.is_file() {
30            tracing::info!("adding file: {}", src.to_relative());
31            tar.append_path_with_name(src, src.file_name().unwrap())?;
32        } else {
33            tracing::info!("adding directory: {}", src.to_relative());
34            tar.append_dir_all(src.file_name().unwrap(), src)?;
35        }
36    }
37
38    // errors in drop are ignored, so we should flush the data here
39    let enc = tar.into_inner()?;
40    let archive = enc.finish()?;
41    archive.sync_all()?;
42
43    Ok(())
44}