diff --git a/Cargo.lock b/Cargo.lock index fe3771e..e58c1f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,6 +1242,7 @@ dependencies = [ name = "cosmic-files" version = "0.1.0" dependencies = [ + "bzip2", "chrono", "dirs 5.0.1", "env_logger", @@ -1261,6 +1262,7 @@ dependencies = [ "image", "libc", "libcosmic", + "liblzma", "log", "mime_guess", "notify-debouncer-full", @@ -3576,6 +3578,26 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "liblzma" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c45fc6fcf5b527d3cf89c1dee8c327943984b0dc8bfcf6e100473b00969e63" +dependencies = [ + "liblzma-sys", +] + +[[package]] +name = "liblzma-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63117d31458acdb7b406f6c60090aa8e1e7cd6e283f8ee02ce585ed68c53fe39" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "libm" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index c74db0b..89dfd41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ chrono = { version = "0.4", features = ["unstable-locales"] } dirs = "5.0.1" env_logger = "0.11" freedesktop_entry_parser = "1.3" -flate2 = "1.0" fs_extra = { git = "https://github.com/pop-os/fs_extra.git" } gio = { version = "0.20", optional = true } glib = { version = "0.20", optional = true } @@ -35,7 +34,6 @@ rayon = "1" regex = "1" serde = { version = "1", features = ["serde_derive"] } shlex = { version = "1.3" } -tar = "0.4.41" tokio = { version = "1", features = ["sync"] } trash = { git = "https://github.com/jackpot51/trash-rs.git", branch = "delete-info" } url = "2.5" @@ -43,6 +41,11 @@ walkdir = "2.5.0" wayland-client = { version = "0.31.5", optional = true } xdg = { version = "2.5.2", optional = true } xdg-mime = "0.3" +# Compression +bzip2 = { version = "0.4", optional = true } #TODO: replace with pure Rust crate +flate2 = "1.0" +liblzma = { version = "0.3", optional = true } #TODO: replace with pure Rust crate +tar = "0.4.41" # Internationalization i18n-embed = { version = "0.14", features = [ "fluent-system", @@ -66,7 +69,7 @@ version = "0.2.1" features = ["serde"] [features] -default = ["desktop", "gvfs", "notify", "winit", "wgpu"] +default = ["bzip2", "desktop", "gvfs", "liblzma", "notify", "winit", "wgpu"] desktop = ["libcosmic/desktop", "dep:xdg"] gvfs = ["dep:gio", "dep:glib"] notify = ["dep:notify-rust"] diff --git a/src/menu.rs b/src/menu.rs index dd64abb..3fbd50c 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -131,9 +131,18 @@ pub fn context_menu<'a>( children.push(divider::horizontal::light().into()); let supported_archive_types = [ + "application/gzip", "application/x-compressed-tar", "application/x-tar", "application/zip", + #[cfg(feature = "bzip2")] + "application/x-bzip", + #[cfg(feature = "bzip2")] + "application/x-bzip-compressed-tar", + #[cfg(feature = "liblzma")] + "application/x-xz", + #[cfg(feature = "liblzma")] + "application/x-xz-compressed-tar", ] .iter() .filter_map(|mime_type| mime_type.parse::().ok()) diff --git a/src/operation.rs b/src/operation.rs index 15dabcc..5c6a04f 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -635,22 +635,26 @@ impl Operation { if let Some(file_stem) = path.file_stem() { let mut new_dir = to.join(file_stem); + // Make sure all extension parts are removed (file_stem may still contain them) + while new_dir.extension().is_some() { + new_dir.set_extension(""); + } if new_dir.exists() { - let mut extensionless_path = path.to_owned(); - extensionless_path.set_extension(""); if let Some(new_dir_parent) = new_dir.parent() { - new_dir = copy_unique_path(&extensionless_path, new_dir_parent); + new_dir = copy_unique_path(&new_dir, new_dir_parent); } } 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/gzip" | "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) @@ -662,6 +666,24 @@ impl Operation { .map_err(err_str)? .and_then(|mut archive| archive.extract(new_dir)) .map_err(err_str)?, + #[cfg(feature = "bzip2")] + "application/x-bzip" | "application/x-bzip-compressed-tar" => { + fs::File::open(path) + .map(io::BufReader::new) + .map(bzip2::read::BzDecoder::new) + .map(tar::Archive::new) + .and_then(|mut archive| archive.unpack(new_dir)) + .map_err(err_str)? + } + #[cfg(feature = "liblzma")] + "application/x-xz" | "application/x-xz-compressed-tar" => { + fs::File::open(path) + .map(io::BufReader::new) + .map(liblzma::read::XzDecoder::new) + .map(tar::Archive::new) + .and_then(|mut archive| archive.unpack(new_dir)) + .map_err(err_str)? + } _ => Err(format!("unsupported mime type {:?}", mime))?, } }