summaryrefslogtreecommitdiffstats
path: root/third_party/rust/zip/examples/write_dir.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/zip/examples/write_dir.rs')
-rw-r--r--third_party/rust/zip/examples/write_dir.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/third_party/rust/zip/examples/write_dir.rs b/third_party/rust/zip/examples/write_dir.rs
new file mode 100644
index 0000000000..3b043528f4
--- /dev/null
+++ b/third_party/rust/zip/examples/write_dir.rs
@@ -0,0 +1,125 @@
+use std::io::prelude::*;
+use std::io::{Seek, Write};
+use std::iter::Iterator;
+use zip::result::ZipError;
+use zip::write::FileOptions;
+
+use std::fs::File;
+use std::path::Path;
+use walkdir::{DirEntry, WalkDir};
+
+fn main() {
+ std::process::exit(real_main());
+}
+
+const METHOD_STORED: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Stored);
+
+#[cfg(any(
+ feature = "deflate",
+ feature = "deflate-miniz",
+ feature = "deflate-zlib"
+))]
+const METHOD_DEFLATED: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Deflated);
+#[cfg(not(any(
+ feature = "deflate",
+ feature = "deflate-miniz",
+ feature = "deflate-zlib"
+)))]
+const METHOD_DEFLATED: Option<zip::CompressionMethod> = None;
+
+#[cfg(feature = "bzip2")]
+const METHOD_BZIP2: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Bzip2);
+#[cfg(not(feature = "bzip2"))]
+const METHOD_BZIP2: Option<zip::CompressionMethod> = None;
+
+#[cfg(feature = "zstd")]
+const METHOD_ZSTD: Option<zip::CompressionMethod> = Some(zip::CompressionMethod::Zstd);
+#[cfg(not(feature = "zstd"))]
+const METHOD_ZSTD: Option<zip::CompressionMethod> = None;
+
+fn real_main() -> i32 {
+ let args: Vec<_> = std::env::args().collect();
+ if args.len() < 3 {
+ println!(
+ "Usage: {} <source_directory> <destination_zipfile>",
+ args[0]
+ );
+ return 1;
+ }
+
+ let src_dir = &*args[1];
+ let dst_file = &*args[2];
+ for &method in [METHOD_STORED, METHOD_DEFLATED, METHOD_BZIP2, METHOD_ZSTD].iter() {
+ if method.is_none() {
+ continue;
+ }
+ match doit(src_dir, dst_file, method.unwrap()) {
+ Ok(_) => println!("done: {src_dir} written to {dst_file}"),
+ Err(e) => println!("Error: {e:?}"),
+ }
+ }
+
+ 0
+}
+
+fn zip_dir<T>(
+ it: &mut dyn Iterator<Item = DirEntry>,
+ prefix: &str,
+ writer: T,
+ method: zip::CompressionMethod,
+) -> zip::result::ZipResult<()>
+where
+ T: Write + Seek,
+{
+ let mut zip = zip::ZipWriter::new(writer);
+ let options = FileOptions::default()
+ .compression_method(method)
+ .unix_permissions(0o755);
+
+ let mut buffer = Vec::new();
+ for entry in it {
+ let path = entry.path();
+ let name = path.strip_prefix(Path::new(prefix)).unwrap();
+
+ // Write file or directory explicitly
+ // Some unzip tools unzip files with directory paths correctly, some do not!
+ if path.is_file() {
+ println!("adding file {path:?} as {name:?} ...");
+ #[allow(deprecated)]
+ zip.start_file_from_path(name, 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() {
+ // Only if not root! Avoids path spec / warning
+ // and mapname conversion failed error on unzip
+ println!("adding dir {path:?} as {name:?} ...");
+ #[allow(deprecated)]
+ zip.add_directory_from_path(name, options)?;
+ }
+ }
+ zip.finish()?;
+ Result::Ok(())
+}
+
+fn doit(
+ src_dir: &str,
+ dst_file: &str,
+ method: zip::CompressionMethod,
+) -> zip::result::ZipResult<()> {
+ if !Path::new(src_dir).is_dir() {
+ return Err(ZipError::FileNotFound);
+ }
+
+ let path = Path::new(dst_file);
+ let file = File::create(path).unwrap();
+
+ let walkdir = WalkDir::new(src_dir);
+ let it = walkdir.into_iter();
+
+ zip_dir(&mut it.filter_map(|e| e.ok()), src_dir, file, method)?;
+
+ Ok(())
+}