From 4374132e2fb88a58c08cc1a1a8bfa644ecc2db8e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Sep 2024 11:50:14 -0600 Subject: [PATCH] Add support for compressing to .tgz, add gio network mount example --- Cargo.lock | 137 +++++++++++++++++++++----------------------- Cargo.toml | 6 +- examples/mount.rs | 23 ++++++++ src/app.rs | 35 ++++++++++-- src/menu.rs | 12 ++-- src/operation.rs | 141 ++++++++++++++++++++++++++++++---------------- 6 files changed, 219 insertions(+), 135 deletions(-) create mode 100644 examples/mount.rs diff --git a/Cargo.lock b/Cargo.lock index 0102160..561d96d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] @@ -254,9 +254,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "apply" @@ -396,9 +396,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", @@ -655,17 +655,17 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide 0.8.0", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.16" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ "jobserver", "libc", @@ -942,9 +942,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.8" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8" dependencies = [ "smallvec", "target-lexicon", @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1232,7 +1232,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "quote", "syn 1.0.109", @@ -1246,10 +1246,12 @@ dependencies = [ "dirs 5.0.1", "env_logger", "fastrand 2.1.1", + "flate2", "fork", "freedesktop_entry_parser", "fs_extra", "gio", + "glib", "glob", "i18n-embed", "i18n-embed-fl", @@ -1306,7 +1308,7 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.12.1" -source = "git+https://github.com/pop-os/cosmic-text.git#9d132f8ebdb350d3db22c1502f72484a8f8c4b8a" +source = "git+https://github.com/pop-os/cosmic-text.git#e8f567cf5b456dfab749a575c257acaa36f622d9" dependencies = [ "bitflags 2.6.0", "fontdb", @@ -1329,7 +1331,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "almost", "cosmic-config", @@ -1817,9 +1819,9 @@ dependencies = [ [[package]] name = "error-code" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" [[package]] name = "etagere" @@ -2365,15 +2367,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "gio" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c49f117d373ffcc98a35d114db5478bc223341cff53e39a5d6feced9e2ddffe" +checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" dependencies = [ "futures-channel", "futures-core", @@ -2384,14 +2386,13 @@ dependencies = [ "libc", "pin-project-lite", "smallvec", - "thiserror", ] [[package]] name = "gio-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd743ba4714d671ad6b6234e8ab2a13b42304d0e13ab7eba1dcdd78a7d6d4ef" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" dependencies = [ "glib-sys", "gobject-sys", @@ -2419,9 +2420,9 @@ checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" [[package]] name = "glib" -version = "0.19.9" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39650279f135469465018daae0ba53357942a5212137515777d5fdca74984a44" +checksum = "95648aac01b75503000bb3bcaa5ec7a7a2dd61e43636b8b1814854de94dd80e4" dependencies = [ "bitflags 2.6.0", "futures-channel", @@ -2436,14 +2437,13 @@ dependencies = [ "libc", "memchr", "smallvec", - "thiserror", ] [[package]] name = "glib-macros" -version = "0.19.9" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4429b0277a14ae9751350ad9b658b1be0abb5b54faa5bcdf6e74a3372582fad7" +checksum = "302f1d633c9cdef4350330e7b68fd8016e2834bb106c93fdf9789fcde753c1ab" dependencies = [ "heck 0.5.0", "proc-macro-crate 3.2.0", @@ -2454,9 +2454,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.19.8" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2dc18d3a82b0006d470b13304fbbb3e0a9bd4884cf985a60a7ed733ac2c4a5" +checksum = "92eee4531c1c9abba945d19378b205031b5890e1f99c319ba0503b6e0c06a163" dependencies = [ "libc", "system-deps", @@ -2470,9 +2470,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -2515,9 +2515,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.19.8" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e697e252d6e0416fd1d9e169bda51c0f1c926026c39ca21fbe8b1bb5c3b8b9e" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" dependencies = [ "glib-sys", "libc", @@ -2774,7 +2774,7 @@ dependencies = [ [[package]] name = "iced" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "dnd", "iced_accessibility", @@ -2793,7 +2793,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "accesskit", "accesskit_unix", @@ -2803,7 +2803,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "bitflags 2.6.0", "dnd", @@ -2825,7 +2825,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "futures", "iced_core", @@ -2838,7 +2838,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "bitflags 2.6.0", "bytemuck", @@ -2862,7 +2862,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2874,7 +2874,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "dnd", "iced_accessibility", @@ -2888,7 +2888,7 @@ dependencies = [ [[package]] name = "iced_sctk" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "enum-repr", "float-cmp", @@ -2915,7 +2915,7 @@ dependencies = [ [[package]] name = "iced_style" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "iced_core", "once_cell", @@ -2925,7 +2925,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "bytemuck", "cosmic-text", @@ -2942,7 +2942,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "as-raw-xcb-connection", "bitflags 2.6.0", @@ -2971,7 +2971,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "dnd", "iced_accessibility", @@ -2989,7 +2989,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "dnd", "iced_accessibility", @@ -3187,9 +3187,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ "crossbeam-deque", "globset", @@ -3505,7 +3505,7 @@ checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#b66f8986d1b897e53471f05fdc27b851cb4fa958" +source = "git+https://github.com/pop-os/libcosmic.git#05da0a83b25e857a85f8ac4e02097d21d367d63d" dependencies = [ "apply", "ashpd 0.9.1", @@ -4381,9 +4381,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -4691,15 +4691,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quick-xml" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.36.1" @@ -5168,18 +5159,18 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -5571,9 +5562,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.2.2" +version = "7.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +checksum = "070a0a5e7da2d24be457809c4b3baa57a835fd2829ad8b86f9a049052fe71031" dependencies = [ "cfg-expr", "heck 0.5.0", @@ -7248,9 +7239,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "xmlwriter" diff --git a/Cargo.toml b/Cargo.toml index 002281a..0b027a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,10 @@ chrono = { version = "0.4", features = ["unstable-locales"] } dirs = "5.0.1" env_logger = "0.11" freedesktop_entry_parser = { version = "1.3", optional = true } +flate2 = "1.0" fs_extra = { git = "https://github.com/pop-os/fs_extra.git" } -gio = { version = "0.19", optional = true } +gio = { version = "0.20", optional = true } +glib = { version = "0.20", optional = true } glob = "0.3" icu_collator = "1.5" icu_provider = { version = "1.5", features = ["sync"] } @@ -65,7 +67,7 @@ features = ["serde"] [features] default = ["desktop", "gvfs", "notify", "winit", "wgpu"] desktop = ["libcosmic/desktop", "dep:freedesktop_entry_parser", "dep:xdg"] -gvfs = ["dep:gio"] +gvfs = ["dep:gio", "dep:glib"] notify = ["dep:notify-rust"] wayland = ["libcosmic/wayland"] winit = ["libcosmic/winit"] diff --git a/examples/mount.rs b/examples/mount.rs new file mode 100644 index 0000000..f75214d --- /dev/null +++ b/examples/mount.rs @@ -0,0 +1,23 @@ +use gio::prelude::*; +use std::env; + +fn main() { + let uri = env::args().nth(1).expect("no uri provided"); + let context = glib::MainContext::new(); + context.block_on(async { + let mount_op = gio::MountOperation::new(); + mount_op.connect_ask_password(|mount_op, message, default_user, default_domain, flags| { + println!( + "{}, {}, {}, {:?}", + message, default_user, default_domain, flags + ); + mount_op.set_anonymous(true); + mount_op.reply(gio::MountOperationResult::Handled); + }); + let file = gio::File::for_uri(&uri); + let res = file + .mount_enclosing_volume_future(gio::MountMountFlags::empty(), Some(&mount_op)) + .await; + println!("{:?}", res); + }); +} diff --git a/src/app.rs b/src/app.rs index fecbe71..b562f00 100644 --- a/src/app.rs +++ b/src/app.rs @@ -303,19 +303,32 @@ impl ContextPage { } } -#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] pub enum ArchiveType { + Tgz, + #[default] Zip, } impl ArchiveType { - pub fn extension(&self) -> String { + pub fn all() -> &'static [Self] { + &[Self::Tgz, Self::Zip] + } + + pub fn extension(&self) -> &str { match self { - ArchiveType::Zip => ".zip".to_string(), + ArchiveType::Tgz => ".tgz", + ArchiveType::Zip => ".zip", } } } +impl AsRef for ArchiveType { + fn as_ref(&self) -> &str { + self.extension() + } +} + #[derive(Clone, Debug)] pub enum DialogPage { Compress { @@ -1299,7 +1312,7 @@ impl Application for App { if let Some(destination) = current_path.parent().zip(current_path.file_stem()) { let to = destination.0.to_path_buf(); let name = destination.1.to_str().unwrap_or_default().to_string(); - let archive_type = ArchiveType::Zip; + let archive_type = ArchiveType::default(); self.dialog_pages.push_back(DialogPage::Compress { paths, to, @@ -2436,6 +2449,8 @@ impl Application for App { } }; + let archive_types = ArchiveType::all(); + let selected = archive_types.iter().position(|&x| x == *archive_type); dialog .primary_action( widget::button::suggested(fl!("create")) @@ -2455,12 +2470,20 @@ impl Application for App { paths: paths.clone(), to: to.clone(), name: name.clone(), - archive_type: archive_type.clone(), + archive_type: *archive_type, }) }) .on_submit_maybe(complete_maybe) .into(), - widget::text::body(".zip").into(), + widget::dropdown(archive_types, selected, move |index| { + Message::DialogUpdate(DialogPage::Compress { + paths: paths.clone(), + to: to.clone(), + name: name.clone(), + archive_type: archive_types[index], + }) + }) + .into(), ]) .align_items(Alignment::Center) .spacing(space_xxs) diff --git a/src/menu.rs b/src/menu.rs index e04ef89..7747db3 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -126,10 +126,14 @@ pub fn context_menu<'a>( children.push(menu_item(fl!("copy"), Action::Copy).into()); children.push(container(horizontal_rule(1)).padding([0, 8]).into()); - let supported_archive_types = ["application/x-tar", "application/zip"] - .iter() - .filter_map(|mime_type| mime_type.parse::().ok()) - .collect::>(); + let supported_archive_types = [ + "application/x-compressed-tar", + "application/x-tar", + "application/zip", + ] + .iter() + .filter_map(|mime_type| mime_type.parse::().ok()) + .collect::>(); selected_types.retain(|t| !supported_archive_types.contains(t)); if selected_types.is_empty() { children.push(menu_item(fl!("extract-here"), Action::ExtractHere).into()); diff --git a/src/operation.rs b/src/operation.rs index 4d7afdb..b5ac4e7 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -15,7 +15,9 @@ use walkdir::WalkDir; use crate::{ app::{ArchiveType, DialogPage, Message}, config::IconSizes, - fl, tab, + fl, + mime_icon::mime_for_path, + tab, }; fn err_str(err: T) -> String { @@ -374,26 +376,31 @@ impl Operation { } => { let msg_tx = msg_tx.clone(); tokio::task::spawn_blocking(move || -> Result<(), String> { + let Some(relative_root) = to.parent() else { + return Err(format!("path {:?} has no parent directory", to)); + }; + + let mut paths = paths; + for path in paths.clone().iter() { + if path.is_dir() { + let new_paths_it = WalkDir::new(path).into_iter(); + for entry in new_paths_it.skip(1) { + let entry = entry.map_err(err_str)?; + paths.push(entry.path().to_path_buf()); + } + } + } + match archive_type { - ArchiveType::Zip => { + ArchiveType::Tgz => { let mut archive = fs::File::create(&to) .map(io::BufWriter::new) - .map(zip::ZipWriter::new) + .map(|w| { + flate2::write::GzEncoder::new(w, flate2::Compression::default()) + }) + .map(tar::Builder::new) .map_err(err_str)?; - let zip_options = zip::write::SimpleFileOptions::default(); - - let mut paths = paths; - for path in paths.clone().iter() { - if path.is_dir() { - let new_paths_it = WalkDir::new(path).into_iter(); - for entry in new_paths_it.skip(1) { - let entry = entry.map_err(err_str)?; - paths.push(entry.path().to_path_buf()); - } - } - } - let total_paths = paths.len(); for (i, path) in paths.iter().enumerate() { executor::block_on(async { @@ -405,27 +412,56 @@ impl Operation { .await; }); - if let Some(relative_root) = to.parent() { - if let Some(relative_path) = - path.strip_prefix(relative_root).map_err(err_str)?.to_str() - { - if path.is_file() { - archive - .start_file(relative_path, zip_options) - .map_err(err_str)?; + if let Some(relative_path) = + path.strip_prefix(relative_root).map_err(err_str)?.to_str() + { + archive + .append_path_with_name(path, relative_path) + .map_err(err_str)?; + } + } - let mut buffer = Vec::new(); - let mut file = fs::File::open(&path) - .map(io::BufReader::new) - .map_err(err_str)?; + archive.finish().map_err(err_str)?; + } + ArchiveType::Zip => { + let mut archive = fs::File::create(&to) + .map(io::BufWriter::new) + .map(zip::ZipWriter::new) + .map_err(err_str)?; - file.read_to_end(&mut buffer).map_err(err_str)?; - archive.write_all(&buffer).map_err(err_str)?; - } else { - archive - .add_directory(relative_path, zip_options) - .map_err(err_str)?; - } + //TODO: set unix_permissions per file? + let zip_options = zip::write::SimpleFileOptions::default(); + + let total_paths = paths.len(); + for (i, path) in paths.iter().enumerate() { + executor::block_on(async { + let total_progress = (i as f32) / total_paths as f32; + let _ = msg_tx + .lock() + .await + .send(Message::PendingProgress(id, 100.0 * total_progress)) + .await; + }); + + if let Some(relative_path) = + path.strip_prefix(relative_root).map_err(err_str)?.to_str() + { + if path.is_file() { + archive + .start_file(relative_path, zip_options) + .map_err(err_str)?; + + let mut buffer = Vec::new(); + let mut file = fs::File::open(&path) + .map(io::BufReader::new) + .map_err(err_str)?; + + file.read_to_end(&mut buffer).map_err(err_str)?; + archive.write_all(&buffer).map_err(err_str)?; + } else { + archive + .add_directory(relative_path, zip_options) + .map_err(err_str)?; } } } @@ -611,21 +647,26 @@ impl Operation { } } - if let Some(mime) = mime_guess::from_path(&path).first() { - match mime.essence_str() { - "application/x-tar" => fs::File::open(path) - .map(io::BufReader::new) - .map(tar::Archive::new) - .and_then(|mut archive| archive.unpack(new_dir)) - .map_err(err_str)?, - "application/zip" => fs::File::open(path) - .map(io::BufReader::new) - .map(zip::ZipArchive::new) - .map_err(err_str)? - .and_then(|mut archive| archive.extract(new_dir)) - .map_err(err_str)?, - _ => Err(format!("unsupported mime type {:?}", mime))?, - } + let mime = mime_for_path(&path); + match mime.essence_str() { + "application/x-compressed-tar" => fs::File::open(path) + .map(io::BufReader::new) + .map(flate2::read::GzDecoder::new) + .map(tar::Archive::new) + .and_then(|mut archive| archive.unpack(new_dir)) + .map_err(err_str)?, + "application/x-tar" => fs::File::open(path) + .map(io::BufReader::new) + .map(tar::Archive::new) + .and_then(|mut archive| archive.unpack(new_dir)) + .map_err(err_str)?, + "application/zip" => fs::File::open(path) + .map(io::BufReader::new) + .map(zip::ZipArchive::new) + .map_err(err_str)? + .and_then(|mut archive| archive.extract(new_dir)) + .map_err(err_str)?, + _ => Err(format!("unsupported mime type {:?}", mime))?, } } }