#![allow(clippy::needless_return)]
use std::ffi::OsStr;
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, sub_dir_name: &str, archive_zip: &mut ZipWriter<File>, options: SimpleFileOptions, out_dir: &OsStr) -> Result<(), std::io::Error> {
let relative_rules_sub_dir = PathBuf::from("Rules").join(sub_dir_name);
let rules_sub_dir = rules_dir.join(sub_dir_name);
let out_dir = PathBuf::from(&out_dir);
println!("using out_dir {:?}", out_dir.to_str());
for entry in read_dir(rules_sub_dir)? {
let entry = entry?;
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().last() {
let dir_name = dir_name.as_os_str().to_str().unwrap();
if dir_name == "zz" { continue;
}
if std::env::set_current_dir(&entry_path).is_err() {
println!("cargo::warning=couldn't change to directory '{}'", &entry_path.display());
continue;
}
let zip_name = dir_name.to_string() + ".zip"; let out_dir_zip_path = out_dir.join(&relative_rules_sub_dir).join(dir_name);
DirBuilder::new().recursive(true).create(&out_dir_zip_path).unwrap();
let out_dir_zip_path_file_name = out_dir_zip_path.join(&zip_name); let zip_file = match File::create(&out_dir_zip_path_file_name) {
Ok(file) => file,
Err(e) => return Err(std::io::Error::new(std::io::ErrorKind::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, &PathBuf::from("."), options)?;
zip.finish()?;
if n_files_in_zip > 0 {
std::env::set_current_dir(&out_dir)?;
add_file_to_zip(archive_zip, &relative_rules_sub_dir.join(dir_name).join(zip_name), options)?; } else {
remove_file(&out_dir_zip_path_file_name)?;
remove_dir(&out_dir_zip_path)?;
}
}
}
}
return Ok( () );
}
fn add_file_to_zip<W: Write + Seek>(
zip: &mut ZipWriter<W>,
path: &Path,
options: SimpleFileOptions,
) -> io::Result<()> {
println!("add_file_to_zip: file='{}'", path.to_str().unwrap());
zip.start_file_from_path(path, options)?;
let mut file = File::open(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>,
path: &Path,
options: SimpleFileOptions
) -> io::Result<usize> {
let mut n_files_in_zip = 0;
println!("current working dir: {}", std::env::current_dir()?.display());
if path.is_dir() {
for entry in read_dir(path)? {
n_files_in_zip += zip_entry(zip, &entry?.path(), options)?;
}
} else if let Some(suffix) = path.extension() {
let suffix = suffix.to_ascii_lowercase();
if suffix == "yaml" || suffix == "yml" {
add_file_to_zip(zip, path, options)?;
n_files_in_zip += 1;
}
}
return Ok(n_files_in_zip);
}
fn main() {
let out_dir = std::env::var_os("OUT_DIR").unwrap();
let archive_path = PathBuf::from(&out_dir).join("rules.zip"); println!("zip file location: '{:?}'", archive_path.to_str());
let zip_options = SimpleFileOptions::default().compression_method(CompressionMethod::BZIP2)
.compression_level(Some(9));
let rules_dir = std::env::current_dir().unwrap().join("Rules") ;
println!("rules directory '{:?}'", &rules_dir.to_string_lossy());
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_dir(&rules_dir, "Languages", &mut archive_zip, zip_options, &out_dir) {
panic!("Error: {}", e);
}
if let Err(e) = zip_dir(&rules_dir, "Braille", &mut archive_zip, zip_options, &out_dir) {
panic!("Error: {}", e);
}
if let Err(e) = archive_zip.finish() {
panic!("Error in zip.finish(): {}", e);
}
println!("cargo::rerun-if-changed=Rules");
}