diff --git a/src/archive/rar.rs b/src/archive/rar.rs index 072de5e..9219561 100644 --- a/src/archive/rar.rs +++ b/src/archive/rar.rs @@ -4,7 +4,7 @@ use std::path::Path; use unrar::Archive; -use crate::{error::Error, list::FileInArchive, utils::logger::Logger}; +use crate::{error::Error, list::FileInArchive, utils::logger::info}; /// Unpacks the archive given by `archive_path` into the folder given by `output_folder`. /// Assumes that output_folder is empty @@ -18,7 +18,7 @@ pub fn unpack_archive(archive_path: &Path, output_folder: &Path, quiet: bool) -> let entry = header.entry(); archive = if entry.is_file() { if !quiet { - logger.info(format!( + info(format!( "{} extracted. ({})", entry.filename.display(), entry.unpacked_size diff --git a/src/archive/sevenz.rs b/src/archive/sevenz.rs index 5272203..7e7a5a7 100644 --- a/src/archive/sevenz.rs +++ b/src/archive/sevenz.rs @@ -11,7 +11,11 @@ use same_file::Handle; use crate::{ error::FinalError, - utils::{self, cd_into_same_dir_as, Bytes, EscapedPathDisplay, FileVisibilityPolicy}, + utils::{ + self, cd_into_same_dir_as, + logger::{info, warning}, + Bytes, EscapedPathDisplay, FileVisibilityPolicy, + }, }; pub fn compress_sevenz( @@ -41,7 +45,7 @@ where // If the output_path is the same as the input file, warn the user and skip the input (in order to avoid compression recursion) if let Ok(handle) = &output_handle { if matches!(Handle::from_path(path), Ok(x) if &x == handle) { - logger.warning(format!( + warning(format!( "The output file and the input file are the same: `{}`, skipping...", output_path.display() )); @@ -55,7 +59,7 @@ where // spoken text for users using screen readers, braille displays // and so on if !quiet { - logger.info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); + info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); } let metadata = match path.metadata() { @@ -108,7 +112,7 @@ where if entry.is_directory() { if !quiet { - logger.info(format!( + info(format!( "File {} extracted to \"{}\"", entry.name(), file_path.display() @@ -119,7 +123,7 @@ where } } else { if !quiet { - logger.info(format!( + info(format!( "{:?} extracted. ({})", file_path.display(), Bytes::new(entry.size()) diff --git a/src/archive/tar.rs b/src/archive/tar.rs index c75f9d2..b7755c3 100644 --- a/src/archive/tar.rs +++ b/src/archive/tar.rs @@ -14,7 +14,11 @@ use same_file::Handle; use crate::{ error::FinalError, list::FileInArchive, - utils::{self, Bytes, EscapedPathDisplay, FileVisibilityPolicy}, + utils::{ + self, + logger::{info, warning}, + Bytes, EscapedPathDisplay, FileVisibilityPolicy, + }, }; /// Unpacks the archive given by `archive` into the folder given by `into`. @@ -34,7 +38,7 @@ pub fn unpack_archive(reader: Box, output_folder: &Path, quiet: bool) // spoken text for users using screen readers, braille displays // and so on if !quiet { - logger.info(format!( + info(format!( "{:?} extracted. ({})", utils::strip_cur_dir(&output_folder.join(file.path()?)), Bytes::new(file.size()), @@ -104,7 +108,7 @@ where // If the output_path is the same as the input file, warn the user and skip the input (in order to avoid compression recursion) if let Ok(handle) = &output_handle { if matches!(Handle::from_path(path), Ok(x) if &x == handle) { - logger.warning(format!( + warning(format!( "The output file and the input file are the same: `{}`, skipping...", output_path.display() )); @@ -118,7 +122,7 @@ where // spoken text for users using screen readers, braille displays // and so on if !quiet { - logger.info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); + info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); } if path.is_dir() { diff --git a/src/archive/zip.rs b/src/archive/zip.rs index 23a3295..6df7308 100644 --- a/src/archive/zip.rs +++ b/src/archive/zip.rs @@ -20,8 +20,9 @@ use crate::{ error::FinalError, list::FileInArchive, utils::{ - self, cd_into_same_dir_as, get_invalid_utf8_paths, pretty_format_list_of_paths, strip_cur_dir, Bytes, - EscapedPathDisplay, FileVisibilityPolicy, + self, cd_into_same_dir_as, get_invalid_utf8_paths, + logger::{info, info_accessible, warning}, + pretty_format_list_of_paths, strip_cur_dir, Bytes, EscapedPathDisplay, FileVisibilityPolicy, }, }; @@ -53,7 +54,7 @@ where // spoken text for users using screen readers, braille displays // and so on if !quiet { - logger.info(format!("File {} extracted to \"{}\"", idx, file_path.display())); + info(format!("File {} extracted to \"{}\"", idx, file_path.display())); } fs::create_dir_all(&file_path)?; } @@ -67,7 +68,7 @@ where // same reason is in _is_dir: long, often not needed text if !quiet { - logger.info(format!( + info(format!( "{:?} extracted. ({})", file_path.display(), Bytes::new(file.size()) @@ -175,7 +176,7 @@ where // If the output_path is the same as the input file, warn the user and skip the input (in order to avoid compression recursion) if let Ok(handle) = &output_handle { if matches!(Handle::from_path(path), Ok(x) if &x == handle) { - logger.warning(format!( + warning(format!( "The output file and the input file are the same: `{}`, skipping...", output_path.display() )); @@ -187,7 +188,7 @@ where // spoken text for users using screen readers, braille displays // and so on if !quiet { - logger.info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); + info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); } let metadata = match path.metadata() { diff --git a/src/check.rs b/src/check.rs index c46cc74..70ed119 100644 --- a/src/check.rs +++ b/src/check.rs @@ -11,7 +11,10 @@ use std::{ use crate::{ error::FinalError, extension::{build_archive_file_suggestion, Extension, PRETTY_SUPPORTED_ALIASES, PRETTY_SUPPORTED_EXTENSIONS}, - utils::{pretty_format_list_of_paths, try_infer_extension, user_wants_to_continue, EscapedPathDisplay}, + utils::{ + logger::{info_accessible, warning}, + pretty_format_list_of_paths, try_infer_extension, user_wants_to_continue, EscapedPathDisplay, + }, QuestionAction, QuestionPolicy, Result, }; @@ -53,7 +56,7 @@ pub fn check_mime_type( .compression_formats .ends_with(detected_format.compression_formats) { - logger.warning(format!( + warning(format!( "The file extension: `{}` differ from the detected extension: `{}`", outer_ext, detected_format )); diff --git a/src/commands/compress.rs b/src/commands/compress.rs index ea7e1cc..2f24cff 100644 --- a/src/commands/compress.rs +++ b/src/commands/compress.rs @@ -104,7 +104,7 @@ pub fn compress_files( } Zip => { if !formats.is_empty() { - warn_user_about_loading_zip_in_memory(logger.clone()); + warn_user_about_loading_zip_in_memory(); if !user_wants_to_continue(output_path, question_policy, QuestionAction::Compression)? { return Ok(false); @@ -132,7 +132,7 @@ pub fn compress_files( } SevenZip => { if !formats.is_empty() { - warn_user_about_loading_sevenz_in_memory(logger.clone()); + warn_user_about_loading_sevenz_in_memory(); if !user_wants_to_continue(output_path, question_policy, QuestionAction::Compression)? { return Ok(false); diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index 00390e8..63c42d8 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -13,7 +13,7 @@ use crate::{ CompressionFormat::{self, *}, Extension, }, - utils::{self, nice_directory_display, user_wants_to_continue}, + utils::{self, logger::info_accessible, nice_directory_display, user_wants_to_continue}, QuestionAction, QuestionPolicy, BUFFER_CAPACITY, }; @@ -122,7 +122,7 @@ pub fn decompress_file( } Zip => { if formats.len() > 1 { - warn_user_about_loading_zip_in_memory(logger.clone()); + warn_user_about_loading_zip_in_memory(); if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? { return Ok(()); @@ -150,10 +150,7 @@ pub fn decompress_file( let unpack_fn: Box UnpackResult> = if formats.len() > 1 { let mut temp_file = tempfile::NamedTempFile::new()?; io::copy(&mut reader, &mut temp_file)?; - let logger_clone = logger.clone(); - Box::new(move |output_dir| { - crate::archive::rar::unpack_archive(temp_file.path(), output_dir, quiet, logger_clone) - }) + Box::new(move |output_dir| crate::archive::rar::unpack_archive(temp_file.path(), output_dir, quiet)) } else { Box::new(|output_dir| crate::archive::rar::unpack_archive(input_file_path, output_dir, quiet)) }; @@ -172,7 +169,7 @@ pub fn decompress_file( } SevenZip => { if formats.len() > 1 { - warn_user_about_loading_sevenz_in_memory(logger.clone()); + warn_user_about_loading_sevenz_in_memory(); if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? { return Ok(()); diff --git a/src/commands/list.rs b/src/commands/list.rs index 6e46363..05e37c3 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -65,7 +65,7 @@ pub fn list_archive_contents( Tar => Box::new(crate::archive::tar::list_archive(tar::Archive::new(reader))), Zip => { if formats.len() > 1 { - warn_user_about_loading_zip_in_memory(logger.clone()); + warn_user_about_loading_zip_in_memory(); if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? { return Ok(()); @@ -94,7 +94,7 @@ pub fn list_archive_contents( } SevenZip => { if formats.len() > 1 { - warn_user_about_loading_zip_in_memory(logger.clone()); + warn_user_about_loading_zip_in_memory(); if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? { return Ok(()); } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 5a6af18..102a9e6 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -7,7 +7,7 @@ mod list; use std::{ ops::ControlFlow, path::PathBuf, - sync::{mpsc, Arc, Condvar, Mutex, OnceLock}, + sync::{Arc, Condvar, Mutex}, }; use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; @@ -22,30 +22,30 @@ use crate::{ list::ListOptions, utils::{ self, - logger::{map_message, setup_channel, PrintMessage}, + logger::{info_accessible, map_message, setup_channel, warning}, to_utf, EscapedPathDisplay, FileVisibilityPolicy, }, CliArgs, QuestionPolicy, }; /// Warn the user that (de)compressing this .zip archive might freeze their system. -fn warn_user_about_loading_zip_in_memory(logger: Logger) { +fn warn_user_about_loading_zip_in_memory() { const ZIP_IN_MEMORY_LIMITATION_WARNING: &str = "\n\ \tThe format '.zip' is limited and cannot be (de)compressed using encoding streams.\n\ \tWhen using '.zip' with other formats, (de)compression must be done in-memory\n\ \tCareful, you might run out of RAM if the archive is too large!"; - logger.warning(ZIP_IN_MEMORY_LIMITATION_WARNING.to_string()); + warning(ZIP_IN_MEMORY_LIMITATION_WARNING.to_string()); } /// Warn the user that (de)compressing this .7z archive might freeze their system. -fn warn_user_about_loading_sevenz_in_memory(logger: Logger) { +fn warn_user_about_loading_sevenz_in_memory() { const SEVENZ_IN_MEMORY_LIMITATION_WARNING: &str = "\n\ \tThe format '.7z' is limited and cannot be (de)compressed using encoding streams.\n\ \tWhen using '.7z' with other formats, (de)compression must be done in-memory\n\ \tCareful, you might run out of RAM if the archive is too large!"; - logger.warning(SEVENZ_IN_MEMORY_LIMITATION_WARNING.to_string()); + warning(SEVENZ_IN_MEMORY_LIMITATION_WARNING.to_string()); } /// This function checks what command needs to be run and performs A LOT of ahead-of-time checks @@ -272,7 +272,7 @@ pub fn run( // Drop our sender so when all threads are done, no clones are left. // This is needed, otherwise the logging thread will never exit since we would be keeping a // sender alive here. - drop(logger); + todo!(); // Prevent the main thread from exiting until the background thread handling the // logging has set `flushed` to true. diff --git a/src/extension.rs b/src/extension.rs index 9e532d7..980f381 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -5,7 +5,7 @@ use std::{ffi::OsStr, fmt, path::Path}; use bstr::ByteSlice; use self::CompressionFormat::*; -use crate::{error::Error, utils::logger::Logger}; +use crate::{error::Error, utils::logger::warning}; pub const SUPPORTED_EXTENSIONS: &[&str] = &[ "tar", @@ -184,7 +184,7 @@ pub fn separate_known_extensions_from_name(path: &Path) -> (&Path, Vec #[cfg(test)] mod tests { use super::*; - use crate::utils::logger::PrintMessage; #[test] fn test_extensions_from_path() { - let (log_sender, _log_receiver) = std::sync::mpsc::channel::(); - let logger = Logger::new(log_sender); - let path = Path::new("bolovo.tar.gz"); let extensions: Vec = extensions_from_path(path); diff --git a/src/utils/fs.rs b/src/utils/fs.rs index 0fe4807..c0eb385 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -9,7 +9,11 @@ use std::{ use fs_err as fs; use super::user_wants_to_overwrite; -use crate::{extension::Extension, utils::EscapedPathDisplay, QuestionPolicy}; +use crate::{ + extension::Extension, + utils::{logger::info_accessible, EscapedPathDisplay}, + QuestionPolicy, +}; /// Remove `path` asking the user to overwrite if necessary. /// diff --git a/src/utils/logger.rs b/src/utils/logger.rs index b5714fe..18119c3 100644 --- a/src/utils/logger.rs +++ b/src/utils/logger.rs @@ -1,21 +1,21 @@ -use std::sync::{ - mpsc::{channel, Receiver, Sender}, - OnceLock, -}; +use std::sync::{mpsc, OnceLock}; use super::colors::{ORANGE, RESET, YELLOW}; use crate::accessible::is_running_in_accessible_mode; -static SENDER: OnceLock> = OnceLock::new(); +type Receiver = mpsc::Receiver; +type Sender = mpsc::Sender; -pub fn setup_channel() -> Receiver { - let (tx, rx) = channel(); +static SENDER: OnceLock = OnceLock::new(); + +pub fn setup_channel() -> Receiver { + let (tx, rx) = mpsc::channel(); SENDER.set(tx).expect("`setup_channel` should only be called once"); rx } #[track_caller] -fn get_sender() -> &'static Sender { +fn get_sender() -> &'static Sender { SENDER.get().expect("No sender, you need to call `setup_channel` first") } @@ -75,77 +75,20 @@ pub fn info_accessible(contents: String) { } fn info_with_accessibility(contents: String, accessible: bool) { - get_sender() - .send(PrintMessage { - contents, - accessible, - level: MessageLevel::Info, - }) - .unwrap(); + send_log_message(PrintMessage { + contents, + accessible, + level: MessageLevel::Info, + }); } pub fn warning(contents: String) { - get_sender() - .send(PrintMessage { - contents, - // Warnings are important and unlikely to flood, so they should be displayed - accessible: true, - level: MessageLevel::Warning, - }) - .unwrap(); -} - -#[derive(Clone)] -pub struct Logger { - log_sender: Sender, -} - -impl Logger { - pub fn new(log_sender: Sender) -> Self { - Self { log_sender } - } - - /// An `[INFO]` log to be displayed if we're not running accessibility mode. - /// - /// Same as `.info_accessible()`, but only displayed if accessibility mode - /// is turned off, which is detected by the function - /// `is_running_in_accessible_mode`. - /// - /// Read more about accessibility mode in `accessible.rs`. - pub fn info(&self, contents: String) { - self.info_with_accessibility(contents, false); - } - - /// An `[INFO]` log to be displayed. - /// - /// Same as `.info()`, but also displays if `is_running_in_accessible_mode` - /// returns `true`. - /// - /// Read more about accessibility mode in `accessible.rs`. - pub fn info_accessible(&self, contents: String) { - self.info_with_accessibility(contents, true); - } - - fn info_with_accessibility(&self, contents: String, accessible: bool) { - self.log_sender - .send(PrintMessage { - contents, - accessible, - level: MessageLevel::Info, - }) - .unwrap(); - } - - pub fn warning(&self, contents: String) { - self.log_sender - .send(PrintMessage { - contents, - // Warnings are important and unlikely to flood, so they should be displayed - accessible: true, - level: MessageLevel::Warning, - }) - .unwrap(); - } + send_log_message(PrintMessage { + contents, + // Warnings are important and unlikely to flood, so they should be displayed + accessible: true, + level: MessageLevel::Warning, + }); } #[derive(Debug, PartialEq)] @@ -153,3 +96,7 @@ pub enum MessageLevel { Info, Warning, } + +fn send_log_message(msg: PrintMessage) { + get_sender().send(msg).expect("Failed to send internal message"); +}