mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-05 02:55:31 +00:00
fix STDIN syncrhonization problems
This commit is contained in:
parent
ccbdceac34
commit
a3e5bac438
@ -10,7 +10,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::{io::lock_and_flush_output_stdio, user_wants_to_continue, FileVisibilityPolicy},
|
||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||
};
|
||||
|
||||
@ -104,8 +104,11 @@ pub fn compress_files(
|
||||
}
|
||||
Zip => {
|
||||
if !formats.is_empty() {
|
||||
warn_user_about_loading_zip_in_memory();
|
||||
// Locking necessary to guarantee that warning and question
|
||||
// messages stay adjacent
|
||||
let _locks = lock_and_flush_output_stdio();
|
||||
|
||||
warn_user_about_loading_zip_in_memory();
|
||||
if !user_wants_to_continue(output_path, question_policy, QuestionAction::Compression)? {
|
||||
return Ok(false);
|
||||
}
|
||||
@ -132,8 +135,11 @@ pub fn compress_files(
|
||||
}
|
||||
SevenZip => {
|
||||
if !formats.is_empty() {
|
||||
warn_user_about_loading_sevenz_in_memory();
|
||||
// Locking necessary to guarantee that warning and question
|
||||
// messages stay adjacent
|
||||
let _locks = lock_and_flush_output_stdio();
|
||||
|
||||
warn_user_about_loading_sevenz_in_memory();
|
||||
if !user_wants_to_continue(output_path, question_policy, QuestionAction::Compression)? {
|
||||
return Ok(false);
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ use crate::{
|
||||
CompressionFormat::{self, *},
|
||||
Extension,
|
||||
},
|
||||
utils::{self, logger::info_accessible, nice_directory_display, user_wants_to_continue},
|
||||
utils::{
|
||||
self, io::lock_and_flush_output_stdio, logger::info_accessible, nice_directory_display, user_wants_to_continue,
|
||||
},
|
||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||
};
|
||||
|
||||
@ -122,8 +124,11 @@ pub fn decompress_file(
|
||||
}
|
||||
Zip => {
|
||||
if formats.len() > 1 {
|
||||
warn_user_about_loading_zip_in_memory();
|
||||
// Locking necessary to guarantee that warning and question
|
||||
// messages stay adjacent
|
||||
let _locks = lock_and_flush_output_stdio();
|
||||
|
||||
warn_user_about_loading_zip_in_memory();
|
||||
if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? {
|
||||
return Ok(());
|
||||
}
|
||||
@ -169,8 +174,11 @@ pub fn decompress_file(
|
||||
}
|
||||
SevenZip => {
|
||||
if formats.len() > 1 {
|
||||
warn_user_about_loading_sevenz_in_memory();
|
||||
// Locking necessary to guarantee that warning and question
|
||||
// messages stay adjacent
|
||||
let _locks = lock_and_flush_output_stdio();
|
||||
|
||||
warn_user_about_loading_sevenz_in_memory();
|
||||
if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
commands::warn_user_about_loading_zip_in_memory,
|
||||
extension::CompressionFormat::{self, *},
|
||||
list::{self, FileInArchive, ListOptions},
|
||||
utils::user_wants_to_continue,
|
||||
utils::{io::lock_and_flush_output_stdio, user_wants_to_continue},
|
||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||
};
|
||||
|
||||
@ -65,8 +65,11 @@ 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();
|
||||
// Locking necessary to guarantee that warning and question
|
||||
// messages stay adjacent
|
||||
let _locks = lock_and_flush_output_stdio();
|
||||
|
||||
warn_user_about_loading_zip_in_memory();
|
||||
if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? {
|
||||
return Ok(());
|
||||
}
|
||||
@ -94,6 +97,10 @@ pub fn list_archive_contents(
|
||||
}
|
||||
SevenZip => {
|
||||
if formats.len() > 1 {
|
||||
// Locking necessary to guarantee that warning and question
|
||||
// messages stay adjacent
|
||||
let _locks = lock_and_flush_output_stdio();
|
||||
|
||||
warn_user_about_loading_zip_in_memory();
|
||||
if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? {
|
||||
return Ok(());
|
||||
|
@ -16,32 +16,28 @@ use crate::{
|
||||
error::{Error, FinalError},
|
||||
extension::{self, parse_format},
|
||||
list::ListOptions,
|
||||
utils::{
|
||||
self,
|
||||
logger::{info_accessible, warning},
|
||||
to_utf, EscapedPathDisplay, FileVisibilityPolicy,
|
||||
},
|
||||
utils::{self, colors::*, logger::info_accessible, 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() {
|
||||
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!";
|
||||
const ZIP_IN_MEMORY_LIMITATION_WARNING: &str = "\n \
|
||||
The format '.zip' is limited by design and cannot be (de)compressed with encoding streams.\n \
|
||||
When chaining '.zip' with other formats, all (de)compression needs to be done in-memory\n \
|
||||
Careful, you might run out of RAM if the archive is too large!";
|
||||
|
||||
warning(ZIP_IN_MEMORY_LIMITATION_WARNING.to_string());
|
||||
eprintln!("{}[WARNING]{}: {ZIP_IN_MEMORY_LIMITATION_WARNING}", *ORANGE, *RESET);
|
||||
}
|
||||
|
||||
/// Warn the user that (de)compressing this .7z archive might freeze their system.
|
||||
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!";
|
||||
const SEVENZ_IN_MEMORY_LIMITATION_WARNING: &str = "\n \
|
||||
The format '.7z' is limited by design and cannot be (de)compressed with encoding streams.\n \
|
||||
When chaining '.7z' with other formats, all (de)compression needs to be done in-memory\n \
|
||||
Careful, you might run out of RAM if the archive is too large!";
|
||||
|
||||
warning(SEVENZ_IN_MEMORY_LIMITATION_WARNING.to_string());
|
||||
eprintln!("{}[WARNING]{}: {SEVENZ_IN_MEMORY_LIMITATION_WARNING}", *ORANGE, *RESET);
|
||||
}
|
||||
|
||||
/// This function checks what command needs to be run and performs A LOT of ahead-of-time checks
|
||||
|
12
src/utils/io.rs
Normal file
12
src/utils/io.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use std::io::{self, stderr, stdout, StderrLock, StdoutLock, Write};
|
||||
|
||||
type StdioOutputLocks = (StdoutLock<'static>, StderrLock<'static>);
|
||||
|
||||
pub fn lock_and_flush_output_stdio() -> io::Result<StdioOutputLocks> {
|
||||
let mut stdout = stdout().lock();
|
||||
stdout.flush()?;
|
||||
let mut stderr = stderr().lock();
|
||||
stderr.flush()?;
|
||||
|
||||
Ok((stdout, stderr))
|
||||
}
|
@ -7,6 +7,7 @@ pub mod colors;
|
||||
mod file_visibility;
|
||||
mod formatting;
|
||||
mod fs;
|
||||
pub mod io;
|
||||
pub mod logger;
|
||||
mod question;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
io::{self, Write},
|
||||
io::{stdin, BufRead},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
@ -15,7 +15,7 @@ use super::{strip_cur_dir, to_utf};
|
||||
use crate::{
|
||||
accessible::is_running_in_accessible_mode,
|
||||
error::{Error, FinalError, Result},
|
||||
utils::{self, colors},
|
||||
utils::{self, colors, io::lock_and_flush_output_stdio},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
@ -121,10 +121,13 @@ impl<'a> Confirmation<'a> {
|
||||
(Some(placeholder), Some(subs)) => Cow::Owned(self.prompt.replace(placeholder, subs)),
|
||||
};
|
||||
|
||||
let _locks = lock_and_flush_output_stdio()?;
|
||||
let mut stdin_lock = stdin().lock();
|
||||
|
||||
// Ask the same question to end while no valid answers are given
|
||||
loop {
|
||||
if is_running_in_accessible_mode() {
|
||||
print!(
|
||||
eprintln!(
|
||||
"{} {}yes{}/{}no{}: ",
|
||||
message,
|
||||
*colors::GREEN,
|
||||
@ -133,7 +136,7 @@ impl<'a> Confirmation<'a> {
|
||||
*colors::RESET
|
||||
);
|
||||
} else {
|
||||
print!(
|
||||
eprintln!(
|
||||
"{} [{}Y{}/{}n{}] ",
|
||||
message,
|
||||
*colors::GREEN,
|
||||
@ -142,11 +145,9 @@ impl<'a> Confirmation<'a> {
|
||||
*colors::RESET
|
||||
);
|
||||
}
|
||||
let _stdout_lock = io::stdout().lock();
|
||||
io::stdout().flush()?;
|
||||
|
||||
let mut answer = String::new();
|
||||
let bytes_read = io::stdin().read_line(&mut answer)?;
|
||||
let bytes_read = stdin_lock.read_line(&mut answer)?;
|
||||
|
||||
if bytes_read == 0 {
|
||||
let error = FinalError::with_title("Unexpected EOF when asking question.")
|
||||
|
Loading…
x
Reference in New Issue
Block a user