Add support for bzip and xz tar files, part of #122

This commit is contained in:
Jeremy Soller 2024-09-17 12:31:54 -06:00
parent ed2aeadc79
commit d0359af0b5
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
4 changed files with 68 additions and 12 deletions

22
Cargo.lock generated
View file

@ -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"

View file

@ -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"]

View file

@ -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::<Mime>().ok())

View file

@ -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))?,
}
}