use std::{
fs::File, io::{Read as _, Seek, Write}, path::Path
};
use anyhow::Context;
use zip::{write::SimpleFileOptions, CompressionMethod};
pub fn zip_dir<T>(
it: &mut dyn Iterator<Item = walkdir::DirEntry>,
prefix: &Path,
writer: T,
) -> anyhow::Result<()>
where
T: Write + Seek,
{
let mut zip = zip::ZipWriter::new(writer);
let options = SimpleFileOptions::default()
.compression_method(CompressionMethod::Stored)
.unix_permissions(0o755);
let prefix = Path::new(prefix);
let mut buffer = Vec::new();
for entry in it {
let path = entry.path();
let name = path.strip_prefix(prefix).unwrap();
let path_as_string = name
.to_str()
.map(str::to_owned)
.with_context(|| format!("{name:?} Is a Non UTF-8 Path"))?;
if path.is_file() {
zip.start_file(path_as_string, options)?;
let mut f = File::open(path)?;
f.read_to_end(&mut buffer)?;
zip.write_all(&buffer)?;
buffer.clear();
} else if !name.as_os_str().is_empty() {
zip.add_directory(path_as_string, options)?;
}
}
zip.finish()?;
Ok(())
}