diff --git a/Cargo.lock b/Cargo.lock index 584cce3..92349a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,15 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "assert_cmd" version = "2.0.17" @@ -294,6 +303,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "difflib" version = "0.4.0" @@ -373,6 +393,12 @@ dependencies = [ "log", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.13" @@ -408,6 +434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] @@ -536,6 +563,12 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + [[package]] name = "heck" version = "0.5.0" @@ -749,6 +782,16 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "indicatif" version = "0.18.0" @@ -858,6 +901,15 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "libz-rs-sys" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b484ba8d4f775eeca644c452a56650e544bf7e617f1d170fe7298122ead5222" +dependencies = [ + "zlib-rs", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -1465,6 +1517,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" version = "0.4.10" @@ -1546,6 +1604,7 @@ dependencies = [ "tokio", "tracing", "whoami", + "zip", ] [[package]] @@ -2312,3 +2371,35 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zip" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a05c7c36fde6c09b08576c9f7fb4cda705990f73b58fe011abf7dfb24168b" +dependencies = [ + "arbitrary", + "crc32fast", + "flate2", + "indexmap", + "memchr", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36134c44663532e6519d7a6dfdbbe06f6f8192bde8ae9ed076e9b213f0e31df7" + +[[package]] +name = "zopfli" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] diff --git a/Cargo.toml b/Cargo.toml index e577129..21fe7c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ serde_json = "1.0.140" tar = "0.4.44" tempfile = "3.20" filetime = "0.2" +zip = { version = "6", default-features = false, features = ["deflate"] } tokio = { version = "1.46.1", features = ["full"] } tracing = { version = "0.1.41", features = ["log"] } whoami = "1.6.0" diff --git a/src/handlers/self_.rs b/src/handlers/self_.rs index b82f57b..38e3d18 100644 --- a/src/handlers/self_.rs +++ b/src/handlers/self_.rs @@ -12,6 +12,7 @@ use flate2::read::GzDecoder; use serde::Deserialize; use std::fs::File; use tar::Archive; +use zip::ZipArchive; #[derive(Debug, Deserialize)] struct GitHubRelease { @@ -150,16 +151,42 @@ pub async fn handle_update() -> Result<()> { let temp_dir = tempfile::tempdir()?; let archive_path = temp_dir.path().join(&archive_name); - download_file(&url, &temp_dir.path().join(archive_name), "suiup", None).await?; - - // extract the archive - let file = File::open(archive_path.as_path()) - .map_err(|_| anyhow!("Cannot open archive file: {}", archive_path.display()))?; - let tar = GzDecoder::new(file); - let mut archive = Archive::new(tar); - archive - .unpack(temp_dir.path()) - .map_err(|_| anyhow!("Cannot unpack archive file: {}", archive_path.display()))?; + download_file(&url, &temp_dir.path().join(&archive_name), "suiup", None).await?; + + // extract the archive based on file extension + if archive_name.ends_with(".zip") { + // Handle ZIP extraction + let file = File::open(archive_path.as_path()) + .map_err(|_| anyhow!("Cannot open archive file: {}", archive_path.display()))?; + let mut archive = ZipArchive::new(file) + .map_err(|_| anyhow!("Cannot read zip archive: {}", archive_path.display()))?; + + for i in 0..archive.len() { + let mut file = archive + .by_index(i) + .map_err(|_| anyhow!("Cannot read file from zip archive"))?; + let outpath = temp_dir.path().join(file.name()); + + if file.is_dir() { + std::fs::create_dir_all(&outpath)?; + } else { + if let Some(parent) = outpath.parent() { + std::fs::create_dir_all(parent)?; + } + let mut outfile = File::create(&outpath)?; + std::io::copy(&mut file, &mut outfile)?; + } + } + } else { + // Handle tar.gz extraction + let file = File::open(archive_path.as_path()) + .map_err(|_| anyhow!("Cannot open archive file: {}", archive_path.display()))?; + let tar = GzDecoder::new(file); + let mut archive = Archive::new(tar); + archive + .unpack(temp_dir.path()) + .map_err(|_| anyhow!("Cannot unpack archive file: {}", archive_path.display()))?; + } #[cfg(not(windows))] let binary = "suiup";