xtask_toolkit/targz/
mod.rs1use std::path::{Path, PathBuf};
2
3pub struct DirCompress {
4 dir: PathBuf,
5 filter_extensions: Vec<String>,
6 filter_filename_regex: Option<regex::Regex>,
7 filter_filenames: Vec<String>,
8 search_subdirs: bool,
9}
10
11impl DirCompress {
12 pub fn new<T>(dir: T) -> Option<Self> where T: Into<PathBuf> {
13 let dir : PathBuf = dir.into();
14 dir.is_dir().then_some(Self {
15 dir,
16 filter_filenames: Vec::new(),
17 filter_extensions: Vec::new(),
18 filter_filename_regex: None,
19 search_subdirs: false,
20 })
21 }
22
23 pub fn search_subdirs(&mut self) -> &mut Self {
24 self.search_subdirs = true;
25 self
26 }
27
28 pub fn filter_extension(&mut self, extension: &str) -> &mut Self {
29 self.filter_extensions.push(extension.to_string());
30 self
31 }
32
33 pub fn filter_filename_regex(&mut self, regex: regex::Regex) -> &mut Self {
34 self.filter_filename_regex = Some(regex);
35 self
36 }
37
38 pub fn filter_filename(&mut self, filename: &str) -> &mut Self {
39 self.filter_filenames.push(filename.to_string());
40 self
41 }
42
43 pub fn compress(&self, output_file: &Path) -> Result<(), std::io::Error> {
44 let walkdir = walkdir::WalkDir::new(&self.dir);
45 let walkdir = if self.search_subdirs {
46 walkdir.max_depth(1)
47 } else {
48 walkdir
49 };
50
51 let files = walkdir
52 .into_iter()
53 .filter_map(|x| {
54 x.ok()
55 .and_then(|x| {
56 let filename = x.file_name().to_string_lossy();
57
58 for name in &self.filter_filenames {
59 if filename == name.as_str() {
60 return Some(x);
61 }
62 }
63
64 for ext in &self.filter_extensions {
65 if x.file_name().to_string_lossy().ends_with(ext) {
66 return Some(x);
67 }
68 }
69
70 if let Some(regex) = &self.filter_filename_regex {
71 if regex.is_match(filename.as_ref()) {
72 return Some(x);
73 }
74 }
75
76 None
77 })
78 .and_then(|x| x.path().is_file().then_some(x))
79 })
80 .map(|x| x.path().to_path_buf())
81 .collect::<Vec<PathBuf>>();
82
83 let dest_file = std::fs::File::create(&output_file)?;
84 let enc = flate2::write::GzEncoder::new(&dest_file, flate2::Compression::default());
85 let mut builder = tar::Builder::new(enc);
86
87 for src in files {
88 builder.append_path_with_name(
89 &src,
90 src.file_name()
91 .unwrap_or_default()
92 .to_string_lossy()
93 .to_string(),
94 )?;
95 }
96
97 Ok(())
98 }
99}