use std::{
fs::{self, File},
io::{Error, ErrorKind, Read, Result, Write},
path::Path,
};
use zip::{self, ZipWriter};
pub fn zip_files(in_path: &str, output_file: &Path) -> Result<()> {
let final_file = File::create(output_file)?;
let mut zipwriter = zip::ZipWriter::new(final_file);
zipper(&mut zipwriter, Path::new(&in_path), None)?;
zipwriter.finish()?;
Ok(())
}
fn zipper(writer: &mut ZipWriter<File>, base_path: &Path, prefix: Option<String>) -> Result<()> {
let prefix = if let Some(prefix) = prefix {
format!("{}", &prefix)
} else {
String::new()
};
let options =
zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Stored);
let dir: fs::ReadDir = fs::read_dir(base_path)?;
let mut buffer = vec![];
for entry in dir {
let entry: fs::DirEntry = entry.map_err(|e| Error::from(e))?;
let cur_entry = entry.path();
let name: &str = cur_entry
.file_name()
.ok_or(ErrorKind::InvalidData)?
.to_str()
.ok_or(ErrorKind::InvalidData)?;
let name = format!("{}{}", &prefix, &name);
if cur_entry.is_file() {
writer.start_file(name, options)?;
let mut f = File::open(&cur_entry)?;
f.read_to_end(&mut buffer)?;
writer.write_all(&buffer)?;
buffer.clear();
} else if cur_entry.is_dir() {
let prefix = format!("{}/", name);
zipper(writer, &cur_entry, Some(prefix))?;
}
}
Ok(())
}