#![allow(clippy::needless_return)]
use std::fs::{read_dir, DirBuilder, File, remove_file, remove_dir};
use std::io::{self, Read, Seek, Write};
use std::path::{Path, PathBuf};
use zip::write::{ZipWriter, SimpleFileOptions};
use zip::CompressionMethod;
fn zip_dir(rules_dir: &Path, archive_zip: &mut ZipWriter<File>, options: SimpleFileOptions, out_dir: &Path, current_out_dir: &Path) -> Result<(), std::io::Error> {
for entry in read_dir(rules_dir)?.flatten() {
let entry_path = entry.path();
if let Some(suffix) = entry_path.extension() {
if suffix == "zip" {
continue;
}
}
if entry_path.is_dir(){
if let Some(dir_name) = entry_path.components().next_back() {
let dir_name = dir_name.as_os_str().to_str().unwrap();
if dir_name == "zz" { continue;
}
let zip_name = dir_name.to_string() + ".zip"; let current_out_dir_zip_path = current_out_dir.join(dir_name);
DirBuilder::new().recursive(true).create(¤t_out_dir_zip_path).unwrap();
let zipped_dir_file_name = current_out_dir_zip_path.join(&zip_name); let zip_file = match File::create(&zipped_dir_file_name) {
Ok(file) => file,
Err(e) => return Err(std::io::Error::other(
format!("build.rs couldn't create {:?}: {}", &zip_name, e))),
};
let mut zip = ZipWriter::new(zip_file);
let n_files_in_zip = zip_entry(&mut zip, &entry_path, &PathBuf::from("."), options)?;
zip.finish()?;
if n_files_in_zip > 0 {
let relative_out_dir = current_out_dir_zip_path.strip_prefix(out_dir).unwrap(); add_file_to_zip(archive_zip, &zipped_dir_file_name, &relative_out_dir.join(&zip_name), options)?;
} else {
remove_file(&zipped_dir_file_name)?;
remove_dir(¤t_out_dir_zip_path)?;
}
}
} else if let Some(suffix) = &entry_path.extension() {
let suffix = suffix.to_ascii_lowercase();
if suffix == "yaml" || suffix == "yml" {
DirBuilder::new().recursive(true).create(current_out_dir).unwrap();
let entry_name = entry_path.components().next_back().unwrap().as_os_str().to_str().unwrap();
let out_dir_file_name = current_out_dir.join(entry_name); std::fs::copy(&entry_path, &out_dir_file_name)?;
let relative_out_dir = out_dir_file_name.strip_prefix(out_dir).unwrap();
add_file_to_zip(archive_zip, relative_out_dir, relative_out_dir, options)?;
}
}
}
return Ok( () );
}
fn zip_other_files(rules_dir: &Path, archive_zip: &mut ZipWriter<File>, options: SimpleFileOptions, out_dir: &Path, current_out_dir: &Path) -> Result<(), std::io::Error> {
for entry in read_dir(rules_dir)? {
let entry = entry?;
let entry_path = entry.path();
let entry_name = entry_path.components().next_back().unwrap().as_os_str().to_str().unwrap();
if entry_path.is_dir(){
if entry_name == "Intent" { zip_other_files(&rules_dir.join("Intent"), archive_zip, options, out_dir, ¤t_out_dir.join("Intent"))?;
}
} else if let Some(suffix) = &entry_path.extension() {
let suffix = suffix.to_ascii_lowercase();
if suffix == "yaml" || suffix == "yml" {
DirBuilder::new().recursive(true).create(current_out_dir).unwrap();
let out_dir_file_name = current_out_dir.join(entry_name); std::fs::copy(&entry_path, &out_dir_file_name)?;
let relative_out_dir = out_dir_file_name.strip_prefix(out_dir).unwrap();
add_file_to_zip(archive_zip, relative_out_dir, relative_out_dir, options)?;
}
}
}
return Ok( () );
}
fn add_file_to_zip<W: Write + Seek>(
zip: &mut ZipWriter<W>,
in_dir_path: &Path,
out_dir_path: &Path,
options: SimpleFileOptions,
) -> io::Result<()> {
zip.start_file_from_path(out_dir_path, options)?;
let mut file = File::open(in_dir_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
zip.write_all(&buffer)?;
return Ok(());
}
#[allow(clippy::unused_io_amount)]
fn zip_entry<W: Write + Seek>(
zip: &mut ZipWriter<W>,
full_path: &Path,
relative_path: &Path,
options: SimpleFileOptions
) -> io::Result<usize> {
let mut n_files_in_zip = 0;
if full_path.is_dir() {
for entry in read_dir(full_path)? {
let entry_path = entry?.path();
let entry_name = entry_path.components().next_back().unwrap().as_os_str().to_str().unwrap();
n_files_in_zip += zip_entry(zip, &entry_path, &relative_path.join(entry_name), options)?;
}
} else if let Some(suffix) = full_path.extension() {
let suffix = suffix.to_ascii_lowercase();
if suffix == "yaml" || suffix == "yml" {
add_file_to_zip(zip, full_path, relative_path, options)?;
n_files_in_zip += 1;
}
}
return Ok(n_files_in_zip);
}
fn main() {
if std::env::var("CARGO_FEATURE_INCLUDE_ZIP").is_ok() {
let out_dir = std::env::var_os("OUT_DIR").unwrap();
let out_dir = PathBuf::from(&out_dir);
let rules_dir = std::env::current_dir().unwrap().join("Rules") ;
let rules_out_dir = PathBuf::from(&out_dir).join("Rules");
if std::env::set_current_dir(&out_dir).is_err() {
println!("cargo::warning=couldn't change to directory '{}'", &out_dir.display());
return;
}
let archive_path = PathBuf::from("rules.zip"); let compile_target = std::env::var("CARGO_CFG_TARGET_FAMILY").unwrap(); let compression_method = if compile_target == "wasm" {
CompressionMethod::DEFLATE } else {
CompressionMethod::BZIP2
};
let zip_options = SimpleFileOptions::default().compression_method(compression_method)
.compression_level(Some(9));
let archive_zip_file = match File::create(&archive_path) {
Ok(file) => file,
Err(e) => panic!("build.rs couldn't create {:?}: {}", &archive_path.to_str(), e),
};
let mut archive_zip = ZipWriter::new(archive_zip_file);
if let Err(e) = zip_other_files(&rules_dir, &mut archive_zip, zip_options, &out_dir, &rules_out_dir) {
panic!("Error: {}", e);
}
if let Err(e) = zip_dir(&rules_dir.join("Languages"), &mut archive_zip, zip_options, &out_dir, &rules_out_dir.join("Languages")) {
panic!("Error: {}", e);
}
if let Err(e) = zip_dir(&rules_dir.join("Braille"), &mut archive_zip, zip_options, &out_dir, &rules_out_dir.join("Braille")) {
panic!("Error: {}", e);
}
if let Err(e) = archive_zip.finish() {
panic!("Error in zip.finish(): {}", e);
}
println!("cargo::rerun-if-changed=Rules");
}
}