From a06e67b0c9623fac6969e08309dff515ff4f63e2 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 15 May 2022 20:16:48 +0100 Subject: [PATCH] bundle auto-zip: works, but needs some progress reporting Signed-off-by: Ian Jackson --- Cargo.toml | 2 +- cli/usebundles.rs | 56 ++++++++++++++++++++++++++++++++++++++++++---- support/imports.rs | 2 +- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 684dbe46..fc7fa67b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,6 @@ unicase="2" url="2" vecdeque-stableix="1" xmlparser = "0.13" -zip="0.6" ambassador = "0.3.1" @@ -74,6 +73,7 @@ const-default = { version="1", features=["derive" ] } enum-map = { version="2" , features=["serde" ] } image = { version = "0.24", default-features=false, features=["jpeg","png"] } index_vec = { version="0.1.1", features=["serde" ] } +zip = { version="0.6", features=["time" ] } # Repeated in other Cargo.toml's because importing does not work properly fehler="1" diff --git a/cli/usebundles.rs b/cli/usebundles.rs index 1f0461a4..83b70367 100644 --- a/cli/usebundles.rs +++ b/cli/usebundles.rs @@ -74,14 +74,62 @@ impl BundleForUpload { bundle } -// #[throws(AE)] - pub fn prepare_from_dir(_file: &str, walk: W) -> Result + #[throws(AE)] + pub fn prepare_from_dir(dir: &str, walk: W) -> Self where W: Iterator> { + let zipfile = tempfile::tempfile().context("create tmp zipfile")?; + let zipfile = BufWriter::new(zipfile); + let mut zipfile = zipfile::ZipWriter::new(zipfile); + for ent in walk { - eprintln!("GOT {:?} {:?}", &ent, &ent.as_ref().unwrap().file_name()); + let ent = ent?; + if ent.file_type().is_dir() { continue } + + let tail = { + let comps = ent.path().components().rev() + .take(ent.depth()) + .collect_vec(); + comps.into_iter().rev().collect::() + }; + + let tail = tail.to_str() + .ok_or_else(|| anyhow!("non-UTF-8 path in bundle {:?}", tail))?; + + (||{ + let mut f = File::open(ent.path()) + .context("start to read")?; + + let metadata = f.metadata().context("fstat")?; + + let perms = metadata.permissions().mode() & 0o700; + let perms = perms * 0o111; + + // Can't copy timestamp due to lack of useful support in + // the `zip` crate. + + let options = zipfile::write::FileOptions::default() + .compression_level(Some(1)) + .unix_permissions(perms); + + let () = zipfile.start_file(tail, options) // yoy no typestate! + .context("start to write")?; + + io::copy(&mut f, &mut zipfile) + .context("copy data")?; + + Ok::<_,AE>(()) + })() + .with_context(|| format!("{:?}", tail)) + .context("add member")?; } - panic!("NYI") + + let zipfile = zipfile.finish().context("finish zipfile")?; + let mut zipfile = zipfile.into_inner() + .map_err(|e| e.into_error()).context("flush zipfile")?; + zipfile.rewind().context("rewind zipfile")?; + + Self::prepare_open_file(dir, zipfile)? } } diff --git a/support/imports.rs b/support/imports.rs index f244656d..4b2b7968 100644 --- a/support/imports.rs +++ b/support/imports.rs @@ -21,7 +21,7 @@ pub use std::net::{IpAddr, SocketAddr, ToSocketAddrs, Ipv6Addr, Ipv4Addr}; pub use std::os::linux::fs::MetadataExt as _; // todo why linux for st_mode?? pub use std::os::unix; pub use std::os::unix::ffi::OsStrExt; -pub use std::os::unix::fs::{MetadataExt, OpenOptionsExt}; +pub use std::os::unix::fs::{MetadataExt, OpenOptionsExt, PermissionsExt}; pub use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; pub use std::os::unix::net::UnixStream; pub use std::os::unix::process::{CommandExt, ExitStatusExt}; -- 2.30.2