evaluator: Verify if input files are decompressible
[ouch.git] / src / decompressors / tar.rs
blob5461b080cc55e34168ead357ac0023d381d62d8b
1 use std::{
2     fs,
3     io::{Cursor, Read},
4     path::{Path, PathBuf},
5 };
7 use colored::Colorize;
8 use tar::{self, Archive};
10 use super::decompressor::{DecompressionResult, Decompressor};
11 use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils};
13 #[derive(Debug)]
14 pub struct TarDecompressor {}
16 impl TarDecompressor {
17     fn unpack_files(from: File, into: &Path, flags: &oof::Flags) -> crate::Result<Vec<PathBuf>> {
18         println!(
19             "{}: attempting to decompress {:?}",
20             "ouch".bright_blue(),
21             &from.path
22         );
23         let mut files_unpacked = vec![];
24         let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
26         let mut archive: Archive<Box<dyn Read>> = match from.contents_in_memory {
27             Some(bytes) => tar::Archive::new(Box::new(Cursor::new(bytes))),
28             None => {
29                 let file = fs::File::open(&from.path)?;
30                 tar::Archive::new(Box::new(file))
31             }
32         };
34         for file in archive.entries()? {
35             let mut file = file?;
37             let file_path = PathBuf::from(into).join(file.path()?);
38             if file_path.exists()
39                 && !utils::permission_for_overwriting(&file_path, flags, &confirm)?
40             {
41                 // The user does not want to overwrite the file
42                 continue;
43             }
45             file.unpack_in(into)?;
47             println!(
48                 "{}: {:?} extracted. ({})",
49                 "info".yellow(),
50                 into.join(file.path()?),
51                 Bytes::new(file.size())
52             );
54             let file_path = fs::canonicalize(file_path)?;
55             files_unpacked.push(file_path);
56         }
58         Ok(files_unpacked)
59     }
62 impl Decompressor for TarDecompressor {
63     fn decompress(
64         &self,
65         from: File,
66         into: &Option<File>,
67         flags: &oof::Flags,
68     ) -> crate::Result<DecompressionResult> {
69         let destination_path = utils::get_destination_path(into);
71         utils::create_path_if_non_existent(destination_path)?;
73         let files_unpacked = Self::unpack_files(from, destination_path, flags)?;
75         Ok(DecompressionResult::FilesUnpacked(files_unpacked))
76     }