-
Notifications
You must be signed in to change notification settings - Fork 12
/
build.rs
100 lines (86 loc) · 3.06 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use anyhow::Result;
use std::{
env,
ffi::OsStr,
fs::File,
io::{Read, Write},
path::{Path, PathBuf},
};
use walkdir::WalkDir;
use zip::{write::FileOptions, CompressionMethod, ZipWriter};
const DEFAULT_UNIX_PERMISSIONS: u32 = 0o755;
fn main() {
let manifest_dir: PathBuf = env::var("CARGO_MANIFEST_DIR").unwrap().into();
let out_dir: PathBuf = env::var("OUT_DIR").unwrap().into();
let template_dir = manifest_dir.join("template");
let dst_file = out_dir.join("template.zip");
println!(
"Creating template zip: template_dir '{}', destination archive '{}'",
template_dir.display(),
dst_file.display(),
);
std::process::exit(match zip_dir(&template_dir, &dst_file) {
Ok(_) => {
println!(
"done: {} written to {}",
template_dir.display(),
dst_file.display()
);
0
}
Err(e) => {
eprintln!("Error: {:?}", e);
1
}
});
}
fn zip_dir(src_dir: &Path, dst_file: &Path) -> Result<()> {
if !src_dir.exists() {
anyhow::bail!("src_dir `{}` does not exist", src_dir.display());
}
if !src_dir.is_dir() {
anyhow::bail!("src_dir `{}` is not a directory", src_dir.display());
}
let file = File::create(dst_file)?;
let walk_dir = WalkDir::new(src_dir);
let walk_it = walk_dir.into_iter().filter_map(|e| e.ok());
let mut zip = ZipWriter::new(file);
let options = FileOptions::default()
.compression_method(CompressionMethod::Stored)
.unix_permissions(DEFAULT_UNIX_PERMISSIONS);
let mut buffer = Vec::new();
for entry in walk_it {
let path = entry.path();
let mut name = path.strip_prefix(&src_dir)?.to_path_buf();
// Cargo.toml files cause the folder to excluded from `cargo package` so need to be renamed
if name.file_name() == Some(OsStr::new("_Cargo.toml")) {
name.set_file_name("Cargo.toml");
}
if let Some(name) = name.to_str() {
if path.is_file() {
zip.start_file(name, options)?;
let mut f = File::open(path)?;
f.read_to_end(&mut buffer)?;
zip.write_all(&*buffer)?;
buffer.clear();
} else if !name.is_empty() {
zip.add_directory(name, options)?;
}
} else {
anyhow::bail!("the path contains invalid UTF-8 characters: `{:?}`", name);
}
}
zip.finish()?;
Ok(())
}