diff options
author | qkzk <qu3nt1n@gmail.com> | 2023-02-15 22:11:04 +0100 |
---|---|---|
committer | qkzk <qu3nt1n@gmail.com> | 2023-02-15 22:11:04 +0100 |
commit | e366d051d6835da4eab276ad28d518c57a0815fd (patch) | |
tree | c1f6b54c15403a530ed2540daeae486b25b04fbf | |
parent | 13d6b9ac1ca17315c975e7a6d10ace21f879ceb4 (diff) |
decompress any archive we can create
-rw-r--r-- | development.md | 2 | ||||
-rw-r--r-- | src/decompress.rs | 42 | ||||
-rw-r--r-- | src/opener.rs | 33 | ||||
-rw-r--r-- | src/preview.rs | 4 |
4 files changed, 64 insertions, 17 deletions
diff --git a/development.md b/development.md index 27373be..ca8220c 100644 --- a/development.md +++ b/development.md @@ -381,7 +381,7 @@ New view: Tree ! Toggle with 't', fold with 'z'. Navigate normally. - [x] tree: use the length of the screen to avoid parsing non displayed lines - [x] navigate in marks - [x] compress flagged files: method is chosen from a list of compression method. - - [ ] decompress any archive, not only zips... + - [x] decompress any archive we can create - [ ] Version 0.1.50 : safety & memory usage diff --git a/src/decompress.rs b/src/decompress.rs index 007edbc..a7d3575 100644 --- a/src/decompress.rs +++ b/src/decompress.rs @@ -1,13 +1,13 @@ +use crate::fm_error::{FmError, FmResult}; +use flate2::read::{GzDecoder, ZlibDecoder}; use std::fs::File; use std::path::Path; +use tar::Archive; -use crate::fm_error::{FmError, FmResult}; - -/// Decompress a compressed file into its parent directory. +/// Decompress a zipped compressed file into its parent directory. /// It may fail an return a `FmError` if the file has no parent, /// which should be impossible. -/// It used `compress_tools` which is a wrapper around `libarchive`. -pub fn decompress(source: &Path) -> FmResult<()> { +pub fn decompress_zip(source: &Path) -> FmResult<()> { let file = File::open(source)?; let mut zip = zip::ZipArchive::new(file)?; @@ -19,7 +19,37 @@ pub fn decompress(source: &Path) -> FmResult<()> { Ok(()) } -pub fn list_files<P>(source: P) -> FmResult<Vec<String>> +/// Decompress a gz compressed file into its parent directory. +/// It may fail an return a `FmError` if the file has no parent, +/// which should be impossible. +pub fn decompress_gz(source: &Path) -> FmResult<()> { + let tar_gz = File::open(source)?; + let tar = GzDecoder::new(tar_gz); + let mut archive = Archive::new(tar); + let parent = source + .parent() + .ok_or_else(|| FmError::custom("decompress", "source should have a parent"))?; + archive.unpack(parent)?; + + Ok(()) +} + +/// Decompress a zlib compressed file into its parent directory. +/// It may fail an return a `FmError` if the file has no parent, +/// which should be impossible. +pub fn decompress_xz(source: &Path) -> FmResult<()> { + let tar_xz = File::open(source)?; + let tar = ZlibDecoder::new(tar_xz); + let mut archive = Archive::new(tar); + let parent = source + .parent() + .ok_or_else(|| FmError::custom("decompress", "source should have a parent"))?; + archive.unpack(parent)?; + + Ok(()) +} + +pub fn list_files_zip<P>(source: P) -> FmResult<Vec<String>> where P: AsRef<Path>, { diff --git a/src/opener.rs b/src/opener.rs index 5e218e1..46d2fde 100644 --- a/src/opener.rs +++ b/src/opener.rs @@ -10,7 +10,7 @@ use crate::constant_strings_paths::{ DEFAULT_AUDIO_OPENER, DEFAULT_IMAGE_OPENER, DEFAULT_OFFICE_OPENER, DEFAULT_OPENER, DEFAULT_READABLE_OPENER, DEFAULT_TEXT_OPENER, DEFAULT_VECTORIAL_OPENER, DEFAULT_VIDEO_OPENER, }; -use crate::decompress::decompress; +use crate::decompress::{decompress_gz, decompress_xz, decompress_zip}; use crate::fileinfo::extract_extension; use crate::fm_error::{FmError, FmResult}; @@ -70,10 +70,13 @@ impl ExtensionKind { "pdf" | "epub" => Self::Readable, - "lzip" | "lzma" | "rar" | "tgz" | "zip" | "gzip" | "bzip2" | "xz" | "7z" => { - Self::Internal(InternalVariant::Decompress) - } + "zip" => Self::Internal(InternalVariant::DecompressZip), + + "xz" | "7z" => Self::Internal(InternalVariant::DecompressXz), + "lzip" | "lzma" | "rar" | "tgz" | "gz" | "bzip2" => { + Self::Internal(InternalVariant::DecompressGz) + } _ => Self::Default, } } @@ -120,8 +123,18 @@ impl OpenerAssociation { OpenerInfo::external(DEFAULT_VIDEO_OPENER), ), ( - ExtensionKind::Internal(InternalVariant::Decompress), - OpenerInfo::internal(ExtensionKind::Internal(InternalVariant::Decompress)) + ExtensionKind::Internal(InternalVariant::DecompressZip), + OpenerInfo::internal(ExtensionKind::Internal(InternalVariant::DecompressZip)) + .unwrap(), + ), + ( + ExtensionKind::Internal(InternalVariant::DecompressGz), + OpenerInfo::internal(ExtensionKind::Internal(InternalVariant::DecompressGz)) + .unwrap(), + ), + ( + ExtensionKind::Internal(InternalVariant::DecompressXz), + OpenerInfo::internal(ExtensionKind::Internal(InternalVariant::DecompressXz)) .unwrap(), ), ]), @@ -172,7 +185,9 @@ impl OpenerAssociation { /// libarchive internally. #[derive(Clone, Hash, PartialEq, Eq, Debug)] pub enum InternalVariant { - Decompress, + DecompressZip, + DecompressXz, + DecompressGz, } /// A way to open one kind of files. @@ -267,7 +282,9 @@ impl Opener { )?; } else { match open_info.internal_variant.as_ref().unwrap() { - InternalVariant::Decompress => decompress(filepath)?, + InternalVariant::DecompressZip => decompress_zip(filepath)?, + InternalVariant::DecompressXz => decompress_xz(filepath)?, + InternalVariant::DecompressGz => decompress_gz(filepath)?, }; } Ok(()) diff --git a/src/preview.rs b/src/preview.rs index c6fdad5..0caf9d2 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -17,7 +17,7 @@ use tuikit::attr::{Attr, Color}; use users::UsersCache; use crate::config::Colors; -use crate::decompress::list_files; +use crate::decompress::list_files_zip; use crate::fileinfo::{FileInfo, FileKind}; use crate::filter::FilterKind; use crate::fm_error::{FmError, FmResult}; @@ -411,7 +411,7 @@ pub struct ZipContent { impl ZipContent { fn new(path: &Path) -> FmResult<Self> { - let content = list_files(path)?; + let content = list_files_zip(path)?; Ok(Self { length: content.len(), |