1use flate2::{Compression, write::GzEncoder};
2use std::env;
3use std::fs;
4use std::path::Path;
5use tar::Builder;
6use walkdir::WalkDir;
7
8const SKIP_DIRS: &[&str] = &["target", ".git", ".hg", ".svn", "node_modules"];
10
11pub fn collect_sources(source_dir: impl AsRef<Path>) {
23 let source_dir = source_dir.as_ref();
24 let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set");
25 let tarball_path = Path::new(&out_dir).join("hector_sources.tar.gz");
26
27 let mut files: Vec<(String, std::path::PathBuf)> = Vec::new();
28
29 for entry in WalkDir::new(source_dir)
30 .follow_links(false)
31 .into_iter()
32 .filter_entry(|e| {
33 if e.file_type().is_dir() {
35 if let Some(name) = e.file_name().to_str() {
36 return !SKIP_DIRS.contains(&name);
37 }
38 }
39 true
40 })
41 .filter_map(|e| e.ok())
42 {
43 let path = entry.path();
44 if !path.is_file() {
45 continue;
46 }
47
48 let file_name = match path.file_name().and_then(|n| n.to_str()) {
49 Some(n) => n,
50 None => continue,
51 };
52
53 let include = match path.extension().and_then(|e| e.to_str()) {
54 Some("rs") | Some("toml") => true,
55 _ => {
56 file_name == "Cargo.lock"
58 || (!file_name.contains('.') && file_name.chars().all(|c| c.is_ascii_uppercase()))
59 }
60 };
61
62 if !include {
63 continue;
64 }
65
66 println!("cargo:rerun-if-changed={}", path.display());
67
68 let rel = path.to_string_lossy().into_owned();
69 files.push((rel, path.to_path_buf()));
70 }
71
72 println!("cargo:rerun-if-changed={}", source_dir.display());
73
74 let tar_gz_bytes = {
75 let buf = Vec::new();
76 let enc = GzEncoder::new(buf, Compression::best());
77 let mut ar = Builder::new(enc);
78
79 for (rel, path) in &files {
80 let data = match fs::read(path) {
81 Ok(d) => d,
82 Err(_) => continue,
83 };
84 let mut header = tar::Header::new_gnu();
85 header.set_size(data.len() as u64);
86 header.set_mode(0o644);
87 header.set_cksum();
88 ar.append_data(&mut header, rel, data.as_slice())
89 .expect("failed to add file to tar");
90 }
91
92 let enc = ar.into_inner().expect("failed to finalize tar");
93 enc.finish().expect("failed to finalize gzip")
94 };
95
96 fs::write(&tarball_path, &tar_gz_bytes).expect("failed to write hector_sources.tar.gz");
97}