summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2023-02-15 22:11:04 +0100
committerqkzk <qu3nt1n@gmail.com>2023-02-15 22:11:04 +0100
commite366d051d6835da4eab276ad28d518c57a0815fd (patch)
treec1f6b54c15403a530ed2540daeae486b25b04fbf
parent13d6b9ac1ca17315c975e7a6d10ace21f879ceb4 (diff)
decompress any archive we can create
-rw-r--r--development.md2
-rw-r--r--src/decompress.rs42
-rw-r--r--src/opener.rs33
-rw-r--r--src/preview.rs4
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(),