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