make logger channel static

This commit is contained in:
João Marcos P. Bezerra 2024-03-15 16:09:48 -03:00 committed by João Marcos
parent bed8ea0276
commit 28daa9e8c4
12 changed files with 76 additions and 120 deletions

View File

@ -4,7 +4,7 @@ use std::path::Path;
use unrar::Archive; 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`. /// Unpacks the archive given by `archive_path` into the folder given by `output_folder`.
/// Assumes that output_folder is empty /// 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(); let entry = header.entry();
archive = if entry.is_file() { archive = if entry.is_file() {
if !quiet { if !quiet {
logger.info(format!( info(format!(
"{} extracted. ({})", "{} extracted. ({})",
entry.filename.display(), entry.filename.display(),
entry.unpacked_size entry.unpacked_size

View File

@ -11,7 +11,11 @@ use same_file::Handle;
use crate::{ use crate::{
error::FinalError, 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<W>( pub fn compress_sevenz<W>(
@ -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 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 let Ok(handle) = &output_handle {
if matches!(Handle::from_path(path), Ok(x) if &x == 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...", "The output file and the input file are the same: `{}`, skipping...",
output_path.display() output_path.display()
)); ));
@ -55,7 +59,7 @@ where
// spoken text for users using screen readers, braille displays // spoken text for users using screen readers, braille displays
// and so on // and so on
if !quiet { if !quiet {
logger.info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); info(format!("Compressing '{}'.", EscapedPathDisplay::new(path)));
} }
let metadata = match path.metadata() { let metadata = match path.metadata() {
@ -108,7 +112,7 @@ where
if entry.is_directory() { if entry.is_directory() {
if !quiet { if !quiet {
logger.info(format!( info(format!(
"File {} extracted to \"{}\"", "File {} extracted to \"{}\"",
entry.name(), entry.name(),
file_path.display() file_path.display()
@ -119,7 +123,7 @@ where
} }
} else { } else {
if !quiet { if !quiet {
logger.info(format!( info(format!(
"{:?} extracted. ({})", "{:?} extracted. ({})",
file_path.display(), file_path.display(),
Bytes::new(entry.size()) Bytes::new(entry.size())

View File

@ -14,7 +14,11 @@ use same_file::Handle;
use crate::{ use crate::{
error::FinalError, error::FinalError,
list::FileInArchive, 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`. /// Unpacks the archive given by `archive` into the folder given by `into`.
@ -34,7 +38,7 @@ pub fn unpack_archive(reader: Box<dyn Read>, output_folder: &Path, quiet: bool)
// spoken text for users using screen readers, braille displays // spoken text for users using screen readers, braille displays
// and so on // and so on
if !quiet { if !quiet {
logger.info(format!( info(format!(
"{:?} extracted. ({})", "{:?} extracted. ({})",
utils::strip_cur_dir(&output_folder.join(file.path()?)), utils::strip_cur_dir(&output_folder.join(file.path()?)),
Bytes::new(file.size()), 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 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 let Ok(handle) = &output_handle {
if matches!(Handle::from_path(path), Ok(x) if &x == 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...", "The output file and the input file are the same: `{}`, skipping...",
output_path.display() output_path.display()
)); ));
@ -118,7 +122,7 @@ where
// spoken text for users using screen readers, braille displays // spoken text for users using screen readers, braille displays
// and so on // and so on
if !quiet { if !quiet {
logger.info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); info(format!("Compressing '{}'.", EscapedPathDisplay::new(path)));
} }
if path.is_dir() { if path.is_dir() {

View File

@ -20,8 +20,9 @@ use crate::{
error::FinalError, error::FinalError,
list::FileInArchive, list::FileInArchive,
utils::{ utils::{
self, cd_into_same_dir_as, get_invalid_utf8_paths, pretty_format_list_of_paths, strip_cur_dir, Bytes, self, cd_into_same_dir_as, get_invalid_utf8_paths,
EscapedPathDisplay, FileVisibilityPolicy, 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 // spoken text for users using screen readers, braille displays
// and so on // and so on
if !quiet { 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)?; fs::create_dir_all(&file_path)?;
} }
@ -67,7 +68,7 @@ where
// same reason is in _is_dir: long, often not needed text // same reason is in _is_dir: long, often not needed text
if !quiet { if !quiet {
logger.info(format!( info(format!(
"{:?} extracted. ({})", "{:?} extracted. ({})",
file_path.display(), file_path.display(),
Bytes::new(file.size()) 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 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 let Ok(handle) = &output_handle {
if matches!(Handle::from_path(path), Ok(x) if &x == 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...", "The output file and the input file are the same: `{}`, skipping...",
output_path.display() output_path.display()
)); ));
@ -187,7 +188,7 @@ where
// spoken text for users using screen readers, braille displays // spoken text for users using screen readers, braille displays
// and so on // and so on
if !quiet { if !quiet {
logger.info(format!("Compressing '{}'.", EscapedPathDisplay::new(path))); info(format!("Compressing '{}'.", EscapedPathDisplay::new(path)));
} }
let metadata = match path.metadata() { let metadata = match path.metadata() {

View File

@ -11,7 +11,10 @@ use std::{
use crate::{ use crate::{
error::FinalError, error::FinalError,
extension::{build_archive_file_suggestion, Extension, PRETTY_SUPPORTED_ALIASES, PRETTY_SUPPORTED_EXTENSIONS}, 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, QuestionAction, QuestionPolicy, Result,
}; };
@ -53,7 +56,7 @@ pub fn check_mime_type(
.compression_formats .compression_formats
.ends_with(detected_format.compression_formats) .ends_with(detected_format.compression_formats)
{ {
logger.warning(format!( warning(format!(
"The file extension: `{}` differ from the detected extension: `{}`", "The file extension: `{}` differ from the detected extension: `{}`",
outer_ext, detected_format outer_ext, detected_format
)); ));

View File

@ -104,7 +104,7 @@ pub fn compress_files(
} }
Zip => { Zip => {
if !formats.is_empty() { 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)? { if !user_wants_to_continue(output_path, question_policy, QuestionAction::Compression)? {
return Ok(false); return Ok(false);
@ -132,7 +132,7 @@ pub fn compress_files(
} }
SevenZip => { SevenZip => {
if !formats.is_empty() { 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)? { if !user_wants_to_continue(output_path, question_policy, QuestionAction::Compression)? {
return Ok(false); return Ok(false);

View File

@ -13,7 +13,7 @@ use crate::{
CompressionFormat::{self, *}, CompressionFormat::{self, *},
Extension, 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, QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
}; };
@ -122,7 +122,7 @@ pub fn decompress_file(
} }
Zip => { Zip => {
if formats.len() > 1 { 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)? { if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? {
return Ok(()); return Ok(());
@ -150,10 +150,7 @@ pub fn decompress_file(
let unpack_fn: Box<dyn FnOnce(&Path) -> UnpackResult> = if formats.len() > 1 { let unpack_fn: Box<dyn FnOnce(&Path) -> UnpackResult> = if formats.len() > 1 {
let mut temp_file = tempfile::NamedTempFile::new()?; let mut temp_file = tempfile::NamedTempFile::new()?;
io::copy(&mut reader, &mut temp_file)?; 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))
Box::new(move |output_dir| {
crate::archive::rar::unpack_archive(temp_file.path(), output_dir, quiet, logger_clone)
})
} else { } else {
Box::new(|output_dir| crate::archive::rar::unpack_archive(input_file_path, output_dir, quiet)) Box::new(|output_dir| crate::archive::rar::unpack_archive(input_file_path, output_dir, quiet))
}; };
@ -172,7 +169,7 @@ pub fn decompress_file(
} }
SevenZip => { SevenZip => {
if formats.len() > 1 { 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)? { if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? {
return Ok(()); return Ok(());

View File

@ -65,7 +65,7 @@ pub fn list_archive_contents(
Tar => Box::new(crate::archive::tar::list_archive(tar::Archive::new(reader))), Tar => Box::new(crate::archive::tar::list_archive(tar::Archive::new(reader))),
Zip => { Zip => {
if formats.len() > 1 { 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)? { if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? {
return Ok(()); return Ok(());
@ -94,7 +94,7 @@ pub fn list_archive_contents(
} }
SevenZip => { SevenZip => {
if formats.len() > 1 { 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)? { if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? {
return Ok(()); return Ok(());
} }

View File

@ -7,7 +7,7 @@ mod list;
use std::{ use std::{
ops::ControlFlow, ops::ControlFlow,
path::PathBuf, path::PathBuf,
sync::{mpsc, Arc, Condvar, Mutex, OnceLock}, sync::{Arc, Condvar, Mutex},
}; };
use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
@ -22,30 +22,30 @@ use crate::{
list::ListOptions, list::ListOptions,
utils::{ utils::{
self, self,
logger::{map_message, setup_channel, PrintMessage}, logger::{info_accessible, map_message, setup_channel, warning},
to_utf, EscapedPathDisplay, FileVisibilityPolicy, to_utf, EscapedPathDisplay, FileVisibilityPolicy,
}, },
CliArgs, QuestionPolicy, CliArgs, QuestionPolicy,
}; };
/// Warn the user that (de)compressing this .zip archive might freeze their system. /// 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\ const ZIP_IN_MEMORY_LIMITATION_WARNING: &str = "\n\
\tThe format '.zip' is limited and cannot be (de)compressed using encoding streams.\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\ \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!"; \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. /// 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\ const SEVENZ_IN_MEMORY_LIMITATION_WARNING: &str = "\n\
\tThe format '.7z' is limited and cannot be (de)compressed using encoding streams.\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\ \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!"; \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 /// 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. // 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 // This is needed, otherwise the logging thread will never exit since we would be keeping a
// sender alive here. // sender alive here.
drop(logger); todo!();
// Prevent the main thread from exiting until the background thread handling the // Prevent the main thread from exiting until the background thread handling the
// logging has set `flushed` to true. // logging has set `flushed` to true.

View File

@ -5,7 +5,7 @@ use std::{ffi::OsStr, fmt, path::Path};
use bstr::ByteSlice; use bstr::ByteSlice;
use self::CompressionFormat::*; use self::CompressionFormat::*;
use crate::{error::Error, utils::logger::Logger}; use crate::{error::Error, utils::logger::warning};
pub const SUPPORTED_EXTENSIONS: &[&str] = &[ pub const SUPPORTED_EXTENSIONS: &[&str] = &[
"tar", "tar",
@ -184,7 +184,7 @@ pub fn separate_known_extensions_from_name(path: &Path) -> (&Path, Vec<Extension
if let Ok(name) = name.to_str() { if let Ok(name) = name.to_str() {
let file_stem = name.trim_matches('.'); let file_stem = name.trim_matches('.');
if SUPPORTED_EXTENSIONS.contains(&file_stem) || SUPPORTED_ALIASES.contains(&file_stem) { if SUPPORTED_EXTENSIONS.contains(&file_stem) || SUPPORTED_ALIASES.contains(&file_stem) {
logger.warning(format!( warning(format!(
"Received a file with name '{file_stem}', but {file_stem} was expected as the extension." "Received a file with name '{file_stem}', but {file_stem} was expected as the extension."
)); ));
} }
@ -251,13 +251,9 @@ pub fn build_archive_file_suggestion(path: &Path, suggested_extension: &str) ->
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::utils::logger::PrintMessage;
#[test] #[test]
fn test_extensions_from_path() { fn test_extensions_from_path() {
let (log_sender, _log_receiver) = std::sync::mpsc::channel::<PrintMessage>();
let logger = Logger::new(log_sender);
let path = Path::new("bolovo.tar.gz"); let path = Path::new("bolovo.tar.gz");
let extensions: Vec<Extension> = extensions_from_path(path); let extensions: Vec<Extension> = extensions_from_path(path);

View File

@ -9,7 +9,11 @@ use std::{
use fs_err as fs; use fs_err as fs;
use super::user_wants_to_overwrite; 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. /// Remove `path` asking the user to overwrite if necessary.
/// ///

View File

@ -1,21 +1,21 @@
use std::sync::{ use std::sync::{mpsc, OnceLock};
mpsc::{channel, Receiver, Sender},
OnceLock,
};
use super::colors::{ORANGE, RESET, YELLOW}; use super::colors::{ORANGE, RESET, YELLOW};
use crate::accessible::is_running_in_accessible_mode; use crate::accessible::is_running_in_accessible_mode;
static SENDER: OnceLock<Sender<PrintMessage>> = OnceLock::new(); type Receiver = mpsc::Receiver<PrintMessage>;
type Sender = mpsc::Sender<PrintMessage>;
pub fn setup_channel() -> Receiver<PrintMessage> { static SENDER: OnceLock<Sender> = OnceLock::new();
let (tx, rx) = channel();
pub fn setup_channel() -> Receiver {
let (tx, rx) = mpsc::channel();
SENDER.set(tx).expect("`setup_channel` should only be called once"); SENDER.set(tx).expect("`setup_channel` should only be called once");
rx rx
} }
#[track_caller] #[track_caller]
fn get_sender() -> &'static Sender<PrintMessage> { fn get_sender() -> &'static Sender {
SENDER.get().expect("No sender, you need to call `setup_channel` first") 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) { fn info_with_accessibility(contents: String, accessible: bool) {
get_sender() send_log_message(PrintMessage {
.send(PrintMessage {
contents, contents,
accessible, accessible,
level: MessageLevel::Info, level: MessageLevel::Info,
}) });
.unwrap();
} }
pub fn warning(contents: String) { pub fn warning(contents: String) {
get_sender() send_log_message(PrintMessage {
.send(PrintMessage {
contents, contents,
// Warnings are important and unlikely to flood, so they should be displayed // Warnings are important and unlikely to flood, so they should be displayed
accessible: true, accessible: true,
level: MessageLevel::Warning, level: MessageLevel::Warning,
}) });
.unwrap();
}
#[derive(Clone)]
pub struct Logger {
log_sender: Sender<PrintMessage>,
}
impl Logger {
pub fn new(log_sender: Sender<PrintMessage>) -> 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();
}
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -153,3 +96,7 @@ pub enum MessageLevel {
Info, Info,
Warning, Warning,
} }
fn send_log_message(msg: PrintMessage) {
get_sender().send(msg).expect("Failed to send internal message");
}