mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-05 02:55:31 +00:00
Make all info logs use the new system
This commit is contained in:
parent
e989db7a3a
commit
e2ac5c4c9b
@ -1,14 +1,19 @@
|
||||
//! Contains RAR-specific building and unpacking functions
|
||||
|
||||
use std::path::Path;
|
||||
use std::{path::Path, sync::mpsc::Sender};
|
||||
|
||||
use unrar::{self, Archive};
|
||||
use unrar::Archive;
|
||||
|
||||
use crate::{error::Error, info, list::FileInArchive};
|
||||
use crate::{error::Error, list::FileInArchive, utils::message::PrintMessage};
|
||||
|
||||
/// Unpacks the archive given by `archive_path` into the folder given by `output_folder`.
|
||||
/// Assumes that output_folder is empty
|
||||
pub fn unpack_archive(archive_path: &Path, output_folder: &Path, quiet: bool) -> crate::Result<usize> {
|
||||
pub fn unpack_archive(
|
||||
archive_path: &Path,
|
||||
output_folder: &Path,
|
||||
quiet: bool,
|
||||
log_sender: Sender<PrintMessage>,
|
||||
) -> crate::Result<usize> {
|
||||
assert!(output_folder.read_dir().expect("dir exists").count() == 0);
|
||||
|
||||
let mut archive = Archive::new(archive_path).open_for_processing()?;
|
||||
@ -18,12 +23,12 @@ pub fn unpack_archive(archive_path: &Path, output_folder: &Path, quiet: bool) ->
|
||||
let entry = header.entry();
|
||||
archive = if entry.is_file() {
|
||||
if !quiet {
|
||||
info!(
|
||||
inaccessible,
|
||||
"{} extracted. ({})",
|
||||
entry.filename.display(),
|
||||
entry.unpacked_size
|
||||
);
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("{} extracted. ({})", entry.filename.display(), entry.unpacked_size),
|
||||
accessible: false,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
unpacked += 1;
|
||||
header.extract_with_base(output_folder)?
|
||||
|
@ -1,9 +1,10 @@
|
||||
//! SevenZip archive format compress function
|
||||
|
||||
use std::{
|
||||
env, io,
|
||||
io::{Read, Seek, Write},
|
||||
env,
|
||||
io::{self, Read, Seek, Write},
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc::Sender,
|
||||
};
|
||||
|
||||
use fs_err as fs;
|
||||
@ -11,8 +12,7 @@ use same_file::Handle;
|
||||
|
||||
use crate::{
|
||||
error::FinalError,
|
||||
info,
|
||||
utils::{self, cd_into_same_dir_as, Bytes, EscapedPathDisplay, FileVisibilityPolicy},
|
||||
utils::{self, cd_into_same_dir_as, message::PrintMessage, Bytes, EscapedPathDisplay, FileVisibilityPolicy},
|
||||
warning,
|
||||
};
|
||||
|
||||
@ -22,6 +22,7 @@ pub fn compress_sevenz<W>(
|
||||
writer: W,
|
||||
file_visibility_policy: FileVisibilityPolicy,
|
||||
quiet: bool,
|
||||
log_sender: Sender<PrintMessage>,
|
||||
) -> crate::Result<W>
|
||||
where
|
||||
W: Write + Seek,
|
||||
@ -56,7 +57,12 @@ where
|
||||
// spoken text for users using screen readers, braille displays
|
||||
// and so on
|
||||
if !quiet {
|
||||
info!(inaccessible, "Compressing '{}'.", EscapedPathDisplay::new(path));
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("Compressing '{}'.", EscapedPathDisplay::new(path)),
|
||||
accessible: false,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let metadata = match path.metadata() {
|
||||
@ -93,7 +99,12 @@ where
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
pub fn decompress_sevenz<R>(reader: R, output_path: &Path, quiet: bool) -> crate::Result<usize>
|
||||
pub fn decompress_sevenz<R>(
|
||||
reader: R,
|
||||
output_path: &Path,
|
||||
quiet: bool,
|
||||
log_sender: Sender<PrintMessage>,
|
||||
) -> crate::Result<usize>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
@ -109,24 +120,24 @@ where
|
||||
|
||||
if entry.is_directory() {
|
||||
if !quiet {
|
||||
info!(
|
||||
inaccessible,
|
||||
"File {} extracted to \"{}\"",
|
||||
entry.name(),
|
||||
file_path.display()
|
||||
);
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("File {} extracted to \"{}\"", entry.name(), file_path.display()),
|
||||
accessible: false,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
if !path.exists() {
|
||||
fs::create_dir_all(path)?;
|
||||
}
|
||||
} else {
|
||||
if !quiet {
|
||||
info!(
|
||||
inaccessible,
|
||||
"{:?} extracted. ({})",
|
||||
file_path.display(),
|
||||
Bytes::new(entry.size()),
|
||||
);
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("{:?} extracted. ({})", file_path.display(), Bytes::new(entry.size()),),
|
||||
accessible: false,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if let Some(parent) = path.parent() {
|
||||
|
@ -13,9 +13,8 @@ use same_file::Handle;
|
||||
|
||||
use crate::{
|
||||
error::FinalError,
|
||||
info,
|
||||
list::FileInArchive,
|
||||
utils::{self, io::PrintMessage, Bytes, EscapedPathDisplay, FileVisibilityPolicy},
|
||||
utils::{self, message::PrintMessage, Bytes, EscapedPathDisplay, FileVisibilityPolicy},
|
||||
warning,
|
||||
};
|
||||
|
||||
@ -95,6 +94,7 @@ pub fn build_archive_from_paths<W>(
|
||||
writer: W,
|
||||
file_visibility_policy: FileVisibilityPolicy,
|
||||
quiet: bool,
|
||||
log_sender: Sender<PrintMessage>,
|
||||
) -> crate::Result<W>
|
||||
where
|
||||
W: Write,
|
||||
@ -129,7 +129,12 @@ where
|
||||
// spoken text for users using screen readers, braille displays
|
||||
// and so on
|
||||
if !quiet {
|
||||
info!(inaccessible, "Compressing '{}'.", EscapedPathDisplay::new(path));
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("Compressing '{}'.", EscapedPathDisplay::new(path)),
|
||||
accessible: false,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if path.is_dir() {
|
||||
|
@ -14,15 +14,13 @@ use filetime_creation::{set_file_mtime, FileTime};
|
||||
use fs_err as fs;
|
||||
use same_file::Handle;
|
||||
use time::OffsetDateTime;
|
||||
use zip::{self, read::ZipFile, DateTime, ZipArchive};
|
||||
use zip::{read::ZipFile, DateTime, ZipArchive};
|
||||
|
||||
use crate::{
|
||||
error::FinalError,
|
||||
info,
|
||||
list::FileInArchive,
|
||||
utils::{
|
||||
self, cd_into_same_dir_as, get_invalid_utf8_paths, io::PrintMessage, pretty_format_list_of_paths,
|
||||
strip_cur_dir, Bytes, EscapedPathDisplay, FileVisibilityPolicy,
|
||||
self, cd_into_same_dir_as, get_invalid_utf8_paths, message::PrintMessage, pretty_format_list_of_paths, strip_cur_dir, Bytes, EscapedPathDisplay, FileVisibilityPolicy
|
||||
},
|
||||
warning,
|
||||
};
|
||||
@ -51,7 +49,7 @@ where
|
||||
|
||||
let file_path = output_folder.join(file_path);
|
||||
|
||||
display_zip_comment_if_exists(&file);
|
||||
display_zip_comment_if_exists(&file, log_sender.clone());
|
||||
|
||||
match file.name().ends_with('/') {
|
||||
_is_dir @ true => {
|
||||
@ -147,6 +145,7 @@ pub fn build_archive_from_paths<W>(
|
||||
writer: W,
|
||||
file_visibility_policy: FileVisibilityPolicy,
|
||||
quiet: bool,
|
||||
log_sender: Sender<PrintMessage>
|
||||
) -> crate::Result<W>
|
||||
where
|
||||
W: Write + Seek,
|
||||
@ -201,7 +200,14 @@ where
|
||||
// spoken text for users using screen readers, braille displays
|
||||
// and so on
|
||||
if !quiet {
|
||||
info!(inaccessible, "Compressing '{}'.", EscapedPathDisplay::new(path));
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!(
|
||||
"Compressing '{}'.",
|
||||
EscapedPathDisplay::new(path)
|
||||
),
|
||||
accessible: false,
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
let metadata = match path.metadata() {
|
||||
@ -251,7 +257,7 @@ where
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
fn display_zip_comment_if_exists(file: &ZipFile) {
|
||||
fn display_zip_comment_if_exists(file: &ZipFile, log_sender: Sender<PrintMessage>) {
|
||||
let comment = file.comment();
|
||||
if !comment.is_empty() {
|
||||
// Zip file comments seem to be pretty rare, but if they are used,
|
||||
@ -264,7 +270,12 @@ fn display_zip_comment_if_exists(file: &ZipFile) {
|
||||
// the future, maybe asking the user if he wants to display the comment
|
||||
// (informing him of its size) would be sensible for both normal and
|
||||
// accessibility mode..
|
||||
info!(accessible, "Found comment in {}: {}", file.name(), comment);
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("Found comment in {}: {}", file.name(), comment),
|
||||
accessible: true,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
34
src/check.rs
34
src/check.rs
@ -5,14 +5,13 @@
|
||||
use std::{
|
||||
ffi::OsString,
|
||||
ops::ControlFlow,
|
||||
path::{Path, PathBuf},
|
||||
path::{Path, PathBuf}, sync::mpsc::Sender,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::FinalError,
|
||||
extension::{build_archive_file_suggestion, Extension, PRETTY_SUPPORTED_ALIASES, PRETTY_SUPPORTED_EXTENSIONS},
|
||||
info,
|
||||
utils::{pretty_format_list_of_paths, try_infer_extension, user_wants_to_continue, EscapedPathDisplay},
|
||||
utils::{message::PrintMessage, pretty_format_list_of_paths, try_infer_extension, user_wants_to_continue, EscapedPathDisplay},
|
||||
warning, QuestionAction, QuestionPolicy, Result,
|
||||
};
|
||||
|
||||
@ -26,6 +25,7 @@ pub fn check_mime_type(
|
||||
path: &Path,
|
||||
formats: &mut Vec<Extension>,
|
||||
question_policy: QuestionPolicy,
|
||||
log_sender: Sender<PrintMessage>
|
||||
) -> Result<ControlFlow<()>> {
|
||||
if formats.is_empty() {
|
||||
// File with no extension
|
||||
@ -33,12 +33,15 @@ pub fn check_mime_type(
|
||||
if let Some(detected_format) = try_infer_extension(path) {
|
||||
// Inferring the file extension can have unpredicted consequences (e.g. the user just
|
||||
// mistyped, ...) which we should always inform the user about.
|
||||
info!(
|
||||
accessible,
|
||||
"Detected file: `{}` extension as `{}`",
|
||||
path.display(),
|
||||
detected_format
|
||||
);
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!(
|
||||
"Detected file: `{}` extension as `{}`",
|
||||
path.display(),
|
||||
detected_format
|
||||
),
|
||||
accessible: true,
|
||||
}).unwrap();
|
||||
if user_wants_to_continue(path, question_policy, QuestionAction::Decompression)? {
|
||||
formats.push(detected_format);
|
||||
} else {
|
||||
@ -66,11 +69,14 @@ pub fn check_mime_type(
|
||||
} else {
|
||||
// NOTE: If this actually produces no false positives, we can upgrade it in the future
|
||||
// to a warning and ask the user if he wants to continue decompressing.
|
||||
info!(
|
||||
accessible,
|
||||
"Failed to confirm the format of `{}` by sniffing the contents, file might be misnamed",
|
||||
path.display()
|
||||
);
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!(
|
||||
"Failed to confirm the format of `{}` by sniffing the contents, file might be misnamed",
|
||||
path.display()
|
||||
),
|
||||
accessible: true,
|
||||
}).unwrap();
|
||||
}
|
||||
Ok(ControlFlow::Continue(()))
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ mod args;
|
||||
use std::{
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
io::{self, BufWriter, Cursor, Seek, Write},
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc::Sender,
|
||||
};
|
||||
|
||||
use fs_err as fs;
|
||||
@ -10,7 +11,7 @@ use crate::{
|
||||
archive,
|
||||
commands::warn_user_about_loading_zip_in_memory,
|
||||
extension::{split_first_compression_format, CompressionFormat::*, Extension},
|
||||
utils::{user_wants_to_continue, FileVisibilityPolicy},
|
||||
utils::{message::PrintMessage, user_wants_to_continue, FileVisibilityPolicy},
|
||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||
};
|
||||
|
||||
@ -34,6 +35,7 @@ pub fn compress_files(
|
||||
question_policy: QuestionPolicy,
|
||||
file_visibility_policy: FileVisibilityPolicy,
|
||||
level: Option<i16>,
|
||||
log_sender: Sender<PrintMessage>,
|
||||
) -> crate::Result<bool> {
|
||||
// If the input files contain a directory, then the total size will be underestimated
|
||||
let file_writer = BufWriter::with_capacity(BUFFER_CAPACITY, output_file);
|
||||
@ -99,7 +101,14 @@ pub fn compress_files(
|
||||
io::copy(&mut reader, &mut writer)?;
|
||||
}
|
||||
Tar => {
|
||||
archive::tar::build_archive_from_paths(&files, output_path, &mut writer, file_visibility_policy, quiet)?;
|
||||
archive::tar::build_archive_from_paths(
|
||||
&files,
|
||||
output_path,
|
||||
&mut writer,
|
||||
file_visibility_policy,
|
||||
quiet,
|
||||
log_sender.clone(),
|
||||
)?;
|
||||
writer.flush()?;
|
||||
}
|
||||
Zip => {
|
||||
@ -119,6 +128,7 @@ pub fn compress_files(
|
||||
&mut vec_buffer,
|
||||
file_visibility_policy,
|
||||
quiet,
|
||||
log_sender.clone()
|
||||
)?;
|
||||
vec_buffer.rewind()?;
|
||||
io::copy(&mut vec_buffer, &mut writer)?;
|
||||
@ -140,7 +150,14 @@ pub fn compress_files(
|
||||
}
|
||||
|
||||
let mut vec_buffer = Cursor::new(vec![]);
|
||||
archive::sevenz::compress_sevenz(&files, output_path, &mut vec_buffer, file_visibility_policy, quiet)?;
|
||||
archive::sevenz::compress_sevenz(
|
||||
&files,
|
||||
output_path,
|
||||
&mut vec_buffer,
|
||||
file_visibility_policy,
|
||||
quiet,
|
||||
log_sender.clone(),
|
||||
)?;
|
||||
vec_buffer.rewind()?;
|
||||
io::copy(&mut vec_buffer, &mut writer)?;
|
||||
}
|
||||
|
@ -14,8 +14,7 @@ use crate::{
|
||||
CompressionFormat::{self, *},
|
||||
Extension,
|
||||
},
|
||||
info,
|
||||
utils::{self, io::PrintMessage, nice_directory_display, user_wants_to_continue},
|
||||
utils::{self, message::PrintMessage, nice_directory_display, user_wants_to_continue},
|
||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||
};
|
||||
|
||||
@ -161,9 +160,14 @@ pub fn decompress_file(
|
||||
let unpack_fn: Box<dyn FnOnce(&Path) -> UnpackResult> = if formats.len() > 1 {
|
||||
let mut temp_file = tempfile::NamedTempFile::new()?;
|
||||
io::copy(&mut reader, &mut temp_file)?;
|
||||
Box::new(move |output_dir| crate::archive::rar::unpack_archive(temp_file.path(), output_dir, quiet))
|
||||
let log_sender_clone = log_sender.clone();
|
||||
Box::new(move |output_dir| {
|
||||
crate::archive::rar::unpack_archive(temp_file.path(), output_dir, quiet, log_sender_clone)
|
||||
})
|
||||
} 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, log_sender.clone())
|
||||
})
|
||||
};
|
||||
|
||||
if let ControlFlow::Continue(files) = smart_unpack(
|
||||
@ -195,7 +199,14 @@ pub fn decompress_file(
|
||||
io::copy(&mut reader, &mut vec)?;
|
||||
|
||||
if let ControlFlow::Continue(files) = smart_unpack(
|
||||
|output_dir| crate::archive::sevenz::decompress_sevenz(io::Cursor::new(vec), output_dir, quiet),
|
||||
|output_dir| {
|
||||
crate::archive::sevenz::decompress_sevenz(
|
||||
io::Cursor::new(vec),
|
||||
output_dir,
|
||||
quiet,
|
||||
log_sender.clone(),
|
||||
)
|
||||
},
|
||||
output_dir,
|
||||
&output_file_path,
|
||||
question_policy,
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
extension::{self, parse_format},
|
||||
info,
|
||||
list::ListOptions,
|
||||
utils::{self, io::PrintMessage, to_utf, EscapedPathDisplay, FileVisibilityPolicy},
|
||||
utils::{self, message::PrintMessage, to_utf, EscapedPathDisplay, FileVisibilityPolicy},
|
||||
warning, CliArgs, QuestionPolicy,
|
||||
};
|
||||
|
||||
@ -54,6 +54,45 @@ pub fn run(
|
||||
question_policy: QuestionPolicy,
|
||||
file_visibility_policy: FileVisibilityPolicy,
|
||||
) -> crate::Result<()> {
|
||||
let (log_sender, log_receiver) = channel::<PrintMessage>();
|
||||
|
||||
let pair = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let pair2 = Arc::clone(&pair);
|
||||
|
||||
// Log received messages until all senders are dropped
|
||||
rayon::spawn(move || {
|
||||
const BUFFER_SIZE: usize = 10;
|
||||
let mut buffer = Vec::<String>::with_capacity(BUFFER_SIZE);
|
||||
|
||||
loop {
|
||||
let msg = log_receiver.recv();
|
||||
|
||||
// Senders are still active
|
||||
if let Ok(msg) = msg {
|
||||
// Print messages if buffer is full otherwise append to it
|
||||
if buffer.len() == BUFFER_SIZE {
|
||||
let mut tmp = buffer.join("\n");
|
||||
tmp.push_str(&msg.contents);
|
||||
|
||||
println!("{}", tmp);
|
||||
buffer.clear();
|
||||
} else {
|
||||
buffer.push(msg.contents);
|
||||
}
|
||||
} else {
|
||||
// All senders have been dropped
|
||||
println!("{}", buffer.join("\n"));
|
||||
|
||||
// Wake up the main thread
|
||||
let (lock, cvar) = &*pair2;
|
||||
let mut flushed = lock.lock().unwrap();
|
||||
*flushed = true;
|
||||
cvar.notify_one();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
match args.cmd {
|
||||
Subcommand::Compress {
|
||||
files,
|
||||
@ -106,6 +145,7 @@ pub fn run(
|
||||
question_policy,
|
||||
file_visibility_policy,
|
||||
level,
|
||||
log_sender.clone(),
|
||||
);
|
||||
|
||||
if let Ok(true) = compress_result {
|
||||
@ -113,7 +153,12 @@ pub fn run(
|
||||
// having a final status message is important especially in an accessibility context
|
||||
// as screen readers may not read a commands exit code, making it hard to reason
|
||||
// about whether the command succeeded without such a message
|
||||
info!(accessible, "Successfully compressed '{}'.", to_utf(&output_path));
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("Successfully compressed '{}'.", to_utf(&output_path)),
|
||||
accessible: true,
|
||||
})
|
||||
.unwrap();
|
||||
} else {
|
||||
// If Ok(false) or Err() occurred, delete incomplete file at `output_path`
|
||||
//
|
||||
@ -153,7 +198,7 @@ pub fn run(
|
||||
for path in files.iter() {
|
||||
let (pathbase, mut file_formats) = extension::separate_known_extensions_from_name(path);
|
||||
|
||||
if let ControlFlow::Break(_) = check::check_mime_type(path, &mut file_formats, question_policy)? {
|
||||
if let ControlFlow::Break(_) = check::check_mime_type(path, &mut file_formats, question_policy, log_sender.clone())? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -167,43 +212,12 @@ pub fn run(
|
||||
// The directory that will contain the output files
|
||||
// We default to the current directory if the user didn't specify an output directory with --dir
|
||||
let output_dir = if let Some(dir) = output_dir {
|
||||
utils::create_dir_if_non_existent(&dir)?;
|
||||
utils::create_dir_if_non_existent(&dir, log_sender.clone())?;
|
||||
dir
|
||||
} else {
|
||||
PathBuf::from(".")
|
||||
};
|
||||
|
||||
let (log_sender, log_receiver) = channel::<PrintMessage>();
|
||||
|
||||
let pair = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let pair2 = Arc::clone(&pair);
|
||||
|
||||
// Log received messages until all senders are dropped
|
||||
rayon::spawn(move || {
|
||||
let mut buffer = Vec::<String>::with_capacity(10);
|
||||
|
||||
loop {
|
||||
let msg = log_receiver.recv();
|
||||
if let Ok(msg) = msg {
|
||||
if buffer.len() == 10 {
|
||||
let mut tmp = buffer.join("\n");
|
||||
tmp.push_str(&msg.contents);
|
||||
println!("{}", tmp);
|
||||
buffer.clear();
|
||||
} else {
|
||||
buffer.push(msg.contents);
|
||||
}
|
||||
} else {
|
||||
println!("{}", buffer.join("\n"));
|
||||
let (lock, cvar) = &*pair2;
|
||||
let mut flushed = lock.lock().unwrap();
|
||||
*flushed = true;
|
||||
cvar.notify_one();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
files
|
||||
.par_iter()
|
||||
.zip(formats)
|
||||
@ -220,17 +234,6 @@ pub fn run(
|
||||
log_sender.clone(),
|
||||
)
|
||||
})?;
|
||||
|
||||
// Drop our sender clones so when all threads are done, no clones are left
|
||||
drop(log_sender);
|
||||
|
||||
// Prevent the main thread from exiting until the background thread handling the
|
||||
// logging has set `flushed` to true.
|
||||
let (lock, cvar) = &*pair;
|
||||
let mut flushed = lock.lock().unwrap();
|
||||
while !*flushed {
|
||||
flushed = cvar.wait(flushed).unwrap();
|
||||
}
|
||||
}
|
||||
Subcommand::List { archives: files, tree } => {
|
||||
let mut formats = vec![];
|
||||
@ -244,7 +247,7 @@ pub fn run(
|
||||
for path in files.iter() {
|
||||
let mut file_formats = extension::extensions_from_path(path);
|
||||
|
||||
if let ControlFlow::Break(_) = check::check_mime_type(path, &mut file_formats, question_policy)? {
|
||||
if let ControlFlow::Break(_) = check::check_mime_type(path, &mut file_formats, question_policy, log_sender.clone())? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -266,5 +269,15 @@ pub fn run(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop our sender so when all threads are done, no clones are left
|
||||
drop(log_sender);
|
||||
|
||||
// Prevent the main thread from exiting until the background thread handling the
|
||||
// logging has set `flushed` to true.
|
||||
let (lock, cvar) = &*pair;
|
||||
let guard = lock.lock().unwrap();
|
||||
let _flushed = cvar.wait(guard).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -248,8 +248,6 @@ pub fn build_archive_file_suggestion(path: &Path, suggested_extension: &str) ->
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -78,7 +78,6 @@ mod tree {
|
||||
use std::{
|
||||
ffi::{OsStr, OsString},
|
||||
io::Write,
|
||||
iter::FromIterator,
|
||||
path,
|
||||
};
|
||||
|
||||
|
@ -4,12 +4,13 @@ use std::{
|
||||
env,
|
||||
io::Read,
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc::Sender,
|
||||
};
|
||||
|
||||
use fs_err as fs;
|
||||
|
||||
use super::user_wants_to_overwrite;
|
||||
use crate::{extension::Extension, info, utils::EscapedPathDisplay, QuestionPolicy};
|
||||
use super::{message::PrintMessage, user_wants_to_overwrite};
|
||||
use crate::{extension::Extension, utils::EscapedPathDisplay, QuestionPolicy};
|
||||
|
||||
/// Remove `path` asking the user to overwrite if necessary.
|
||||
///
|
||||
@ -36,12 +37,17 @@ pub fn remove_file_or_dir(path: &Path) -> crate::Result<()> {
|
||||
}
|
||||
|
||||
/// Creates a directory at the path, if there is nothing there.
|
||||
pub fn create_dir_if_non_existent(path: &Path) -> crate::Result<()> {
|
||||
pub fn create_dir_if_non_existent(path: &Path, log_sender: Sender<PrintMessage>) -> crate::Result<()> {
|
||||
if !path.exists() {
|
||||
fs::create_dir_all(path)?;
|
||||
// creating a directory is an important change to the file system we
|
||||
// should always inform the user about
|
||||
info!(accessible, "directory {} created.", EscapedPathDisplay::new(path));
|
||||
log_sender
|
||||
.send(PrintMessage {
|
||||
contents: format!("Directory {} created.", EscapedPathDisplay::new(path)),
|
||||
accessible: true,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
#[derive(Debug)]
|
||||
pub struct PrintMessage {
|
||||
pub contents: String,
|
||||
pub accessible: bool,
|
||||
}
|
22
src/utils/message.rs
Normal file
22
src/utils/message.rs
Normal file
@ -0,0 +1,22 @@
|
||||
/// Message object used for sending logs from worker threads to a logging thread via channels.
|
||||
/// See <https://github.com/ouch-org/ouch/issues/632>
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rs
|
||||
/// // This is already done in the main thread in src/commands/mod.rs
|
||||
/// // Functions that want to log anything just need to have
|
||||
/// // `log_sender: Sender<PrintMessage>` as an argument.
|
||||
/// let (log_sender, log_receiver) = channel::<PrintMessage>();
|
||||
///
|
||||
/// log_sender
|
||||
/// .send(PrintMessage {
|
||||
/// contents: "Hello, world!".to_string(),
|
||||
/// accessible: true,
|
||||
/// }).unwrap();
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct PrintMessage {
|
||||
pub contents: String,
|
||||
pub accessible: bool,
|
||||
}
|
@ -7,7 +7,7 @@ pub mod colors;
|
||||
mod file_visibility;
|
||||
mod formatting;
|
||||
mod fs;
|
||||
pub mod io;
|
||||
pub mod message;
|
||||
mod question;
|
||||
|
||||
pub use file_visibility::FileVisibilityPolicy;
|
||||
|
Loading…
x
Reference in New Issue
Block a user