winisland_plugin_api/packager/
packaging.rs1use std::io::Write;
2use std::path::Path;
3
4pub fn create_zip(source_dir: &Path, output_path: &Path) -> Result<(), String> {
6 let file = std::fs::File::create(output_path)
7 .map_err(|e| format!("Cannot create ZIP '{}': {}", output_path.display(), e))?;
8 let mut zip = zip::ZipWriter::new(file);
9
10 let options = zip::write::FileOptions::<()>::default()
11 .compression_method(zip::CompressionMethod::Deflated);
12
13 add_dir(&mut zip, source_dir, source_dir, &options)?;
14
15 zip.finish()
16 .map_err(|e| format!("Cannot finalise ZIP: {}", e))?;
17 Ok(())
18}
19
20fn add_dir(
21 zip: &mut zip::ZipWriter<std::fs::File>,
22 base: &Path,
23 dir: &Path,
24 options: &zip::write::FileOptions<()>,
25) -> Result<(), String> {
26 for entry in std::fs::read_dir(dir).map_err(|e| format!("Cannot read dir: {}", e))? {
27 let entry = entry.map_err(|e| format!("Dir entry error: {}", e))?;
28 let path = entry.path();
29 let relative = path
30 .strip_prefix(base)
31 .map_err(|_| "Path prefix error".to_string())?;
32
33 if entry.file_type().map(|t| t.is_dir()).unwrap_or(false) {
34 let name = relative.to_string_lossy().replace('\\', "/") + "/";
35 zip.add_directory(&name, *options)
36 .map_err(|e| format!("Cannot add dir '{}': {}", name, e))?;
37 add_dir(zip, base, &path, options)?;
38 } else {
39 let name = relative.to_string_lossy().replace('\\', "/");
40 zip.start_file(&name, *options)
41 .map_err(|e| format!("Cannot add file '{}': {}", name, e))?;
42 let data = std::fs::read(&path)
43 .map_err(|e| format!("Cannot read '{}': {}", path.display(), e))?;
44 zip.write_all(&data)
45 .map_err(|e| format!("Cannot write '{}': {}", name, e))?;
46 }
47 }
48 Ok(())
49}