mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-07 12:05:46 +00:00
remove progress feature
This commit is contained in:
parent
f610ff596b
commit
13fab6d241
54
Cargo.lock
generated
54
Cargo.lock
generated
@ -189,20 +189,6 @@ dependencies = [
|
|||||||
"roff",
|
"roff",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "console"
|
|
||||||
version = "0.15.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c"
|
|
||||||
dependencies = [
|
|
||||||
"encode_unicode",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"terminal_size",
|
|
||||||
"unicode-width",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -239,12 +225,6 @@ version = "1.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encode_unicode"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@ -355,17 +335,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indicatif"
|
|
||||||
version = "0.17.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bfddc9561e8baf264e0e45e197fd7696320026eb10a8180340debc27b18f535b"
|
|
||||||
dependencies = [
|
|
||||||
"console",
|
|
||||||
"number_prefix",
|
|
||||||
"unicode-width",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "infer"
|
name = "infer"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -514,12 +483,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "number_prefix"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
@ -547,7 +510,6 @@ dependencies = [
|
|||||||
"fs-err",
|
"fs-err",
|
||||||
"humansize",
|
"humansize",
|
||||||
"ignore",
|
"ignore",
|
||||||
"indicatif",
|
|
||||||
"infer",
|
"infer",
|
||||||
"is_executable",
|
"is_executable",
|
||||||
"libc",
|
"libc",
|
||||||
@ -894,16 +856,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "terminal_size"
|
|
||||||
version = "0.1.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termtree"
|
name = "termtree"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
@ -955,12 +907,6 @@ version = "1.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -16,9 +16,11 @@ description = "A command-line utility for easily compressing and decompressing f
|
|||||||
atty = "0.2.14"
|
atty = "0.2.14"
|
||||||
bzip2 = "0.4.3"
|
bzip2 = "0.4.3"
|
||||||
clap = { version = "4.0.13", features = ["derive", "env"] }
|
clap = { version = "4.0.13", features = ["derive", "env"] }
|
||||||
|
filetime = "0.2.17"
|
||||||
flate2 = { version = "1.0.24", default-features = false }
|
flate2 = { version = "1.0.24", default-features = false }
|
||||||
fs-err = "2.8.1"
|
fs-err = "2.8.1"
|
||||||
humansize = "2.1.0"
|
humansize = "2.1.0"
|
||||||
|
ignore = "0.4.18"
|
||||||
libc = "0.2.135"
|
libc = "0.2.135"
|
||||||
linked-hash-map = "0.5.6"
|
linked-hash-map = "0.5.6"
|
||||||
lzzzz = "1.0.3"
|
lzzzz = "1.0.3"
|
||||||
@ -26,13 +28,10 @@ once_cell = "1.15.0"
|
|||||||
same-file = "1.0.6"
|
same-file = "1.0.6"
|
||||||
snap = "1.0.5"
|
snap = "1.0.5"
|
||||||
tar = "0.4.38"
|
tar = "0.4.38"
|
||||||
|
tempfile = "3.3.0"
|
||||||
xz2 = "0.1.7"
|
xz2 = "0.1.7"
|
||||||
zip = { version = "0.6.2", default-features = false, features = ["time"] }
|
zip = { version = "0.6.2", default-features = false, features = ["time"] }
|
||||||
zstd = { version = "0.11.2", default-features = false }
|
zstd = { version = "0.11.2", default-features = false }
|
||||||
tempfile = "3.3.0"
|
|
||||||
ignore = "0.4.18"
|
|
||||||
indicatif = "0.17.1"
|
|
||||||
filetime = "0.2.17"
|
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
time = { version = "0.3.15", default-features = false }
|
time = { version = "0.3.15", default-features = false }
|
||||||
|
@ -2,7 +2,6 @@ use once_cell::sync::OnceCell;
|
|||||||
|
|
||||||
/// Whether to enable accessible output (removes info output and reduces other
|
/// Whether to enable accessible output (removes info output and reduces other
|
||||||
/// output, removes visual markers like '[' and ']').
|
/// output, removes visual markers like '[' and ']').
|
||||||
/// Removes th progress bar as well
|
|
||||||
pub static ACCESSIBLE: OnceCell<bool> = OnceCell::new();
|
pub static ACCESSIBLE: OnceCell<bool> = OnceCell::new();
|
||||||
|
|
||||||
pub fn is_running_in_accessible_mode() -> bool {
|
pub fn is_running_in_accessible_mode() -> bool {
|
||||||
|
@ -16,18 +16,13 @@ use crate::{
|
|||||||
error::FinalError,
|
error::FinalError,
|
||||||
info,
|
info,
|
||||||
list::FileInArchive,
|
list::FileInArchive,
|
||||||
progress::OutputLine,
|
|
||||||
utils::{self, FileVisibilityPolicy},
|
utils::{self, FileVisibilityPolicy},
|
||||||
warning,
|
warning,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Unpacks the archive given by `archive` into the folder given by `into`.
|
/// Unpacks the archive given by `archive` into the folder given by `into`.
|
||||||
/// Assumes that output_folder is empty
|
/// Assumes that output_folder is empty
|
||||||
pub fn unpack_archive(
|
pub fn unpack_archive(reader: Box<dyn Read>, output_folder: &Path) -> crate::Result<Vec<PathBuf>> {
|
||||||
reader: Box<dyn Read>,
|
|
||||||
output_folder: &Path,
|
|
||||||
mut log_out: impl OutputLine,
|
|
||||||
) -> crate::Result<Vec<PathBuf>> {
|
|
||||||
assert!(output_folder.read_dir().expect("dir exists").count() == 0);
|
assert!(output_folder.read_dir().expect("dir exists").count() == 0);
|
||||||
let mut archive = tar::Archive::new(reader);
|
let mut archive = tar::Archive::new(reader);
|
||||||
|
|
||||||
@ -44,7 +39,6 @@ pub fn unpack_archive(
|
|||||||
// and so on
|
// and so on
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
@log_out,
|
|
||||||
inaccessible,
|
inaccessible,
|
||||||
"{:?} extracted. ({})",
|
"{:?} extracted. ({})",
|
||||||
utils::strip_cur_dir(&output_folder.join(file.path()?)),
|
utils::strip_cur_dir(&output_folder.join(file.path()?)),
|
||||||
@ -87,16 +81,14 @@ pub fn list_archive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`.
|
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`.
|
||||||
pub fn build_archive_from_paths<W, D>(
|
pub fn build_archive_from_paths<W>(
|
||||||
input_filenames: &[PathBuf],
|
input_filenames: &[PathBuf],
|
||||||
output_path: &Path,
|
output_path: &Path,
|
||||||
writer: W,
|
writer: W,
|
||||||
file_visibility_policy: FileVisibilityPolicy,
|
file_visibility_policy: FileVisibilityPolicy,
|
||||||
mut log_out: D,
|
|
||||||
) -> crate::Result<W>
|
) -> crate::Result<W>
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
D: OutputLine,
|
|
||||||
{
|
{
|
||||||
let mut builder = tar::Builder::new(writer);
|
let mut builder = tar::Builder::new(writer);
|
||||||
let output_handle = Handle::from_path(output_path);
|
let output_handle = Handle::from_path(output_path);
|
||||||
@ -115,7 +107,6 @@ where
|
|||||||
if let Ok(ref handle) = output_handle {
|
if let Ok(ref 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) {
|
||||||
warning!(
|
warning!(
|
||||||
@log_out,
|
|
||||||
"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()
|
||||||
);
|
);
|
||||||
@ -127,7 +118,7 @@ where
|
|||||||
// little importance for most users, but would generate lots of
|
// little importance for most users, but would generate lots of
|
||||||
// spoken text for users using screen readers, braille displays
|
// spoken text for users using screen readers, braille displays
|
||||||
// and so on
|
// and so on
|
||||||
info!(@log_out, inaccessible, "Compressing '{}'.", utils::to_utf(path));
|
info!(inaccessible, "Compressing '{}'.", utils::to_utf(path));
|
||||||
|
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
builder.append_dir(path, path)?;
|
builder.append_dir(path, path)?;
|
||||||
|
@ -20,7 +20,6 @@ use crate::{
|
|||||||
error::FinalError,
|
error::FinalError,
|
||||||
info,
|
info,
|
||||||
list::FileInArchive,
|
list::FileInArchive,
|
||||||
progress::OutputLine,
|
|
||||||
utils::{
|
utils::{
|
||||||
self, cd_into_same_dir_as, get_invalid_utf8_paths, pretty_format_list_of_paths, strip_cur_dir, to_utf,
|
self, cd_into_same_dir_as, get_invalid_utf8_paths, pretty_format_list_of_paths, strip_cur_dir, to_utf,
|
||||||
FileVisibilityPolicy,
|
FileVisibilityPolicy,
|
||||||
@ -30,14 +29,9 @@ use crate::{
|
|||||||
|
|
||||||
/// Unpacks the archive given by `archive` into the folder given by `output_folder`.
|
/// Unpacks the archive given by `archive` into the folder given by `output_folder`.
|
||||||
/// Assumes that output_folder is empty
|
/// Assumes that output_folder is empty
|
||||||
pub fn unpack_archive<R, D>(
|
pub fn unpack_archive<R>(mut archive: ZipArchive<R>, output_folder: &Path) -> crate::Result<Vec<PathBuf>>
|
||||||
mut archive: ZipArchive<R>,
|
|
||||||
output_folder: &Path,
|
|
||||||
mut log_out: D,
|
|
||||||
) -> crate::Result<Vec<PathBuf>>
|
|
||||||
where
|
where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
D: OutputLine,
|
|
||||||
{
|
{
|
||||||
assert!(output_folder.read_dir().expect("dir exists").count() == 0);
|
assert!(output_folder.read_dir().expect("dir exists").count() == 0);
|
||||||
|
|
||||||
@ -60,7 +54,7 @@ where
|
|||||||
// importance for most users, but would generate lots of
|
// importance for most users, but would generate lots of
|
||||||
// spoken text for users using screen readers, braille displays
|
// spoken text for users using screen readers, braille displays
|
||||||
// and so on
|
// and so on
|
||||||
info!(@log_out, inaccessible, "File {} extracted to \"{}\"", idx, file_path.display());
|
info!(inaccessible, "File {} extracted to \"{}\"", idx, file_path.display());
|
||||||
fs::create_dir_all(&file_path)?;
|
fs::create_dir_all(&file_path)?;
|
||||||
}
|
}
|
||||||
_is_file @ false => {
|
_is_file @ false => {
|
||||||
@ -73,7 +67,6 @@ where
|
|||||||
|
|
||||||
// same reason is in _is_dir: long, often not needed text
|
// same reason is in _is_dir: long, often not needed text
|
||||||
info!(
|
info!(
|
||||||
@log_out,
|
|
||||||
inaccessible,
|
inaccessible,
|
||||||
"{:?} extracted. ({})",
|
"{:?} extracted. ({})",
|
||||||
file_path.display(),
|
file_path.display(),
|
||||||
@ -137,16 +130,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`.
|
/// Compresses the archives given by `input_filenames` into the file given previously to `writer`.
|
||||||
pub fn build_archive_from_paths<W, D>(
|
pub fn build_archive_from_paths<W>(
|
||||||
input_filenames: &[PathBuf],
|
input_filenames: &[PathBuf],
|
||||||
output_path: &Path,
|
output_path: &Path,
|
||||||
writer: W,
|
writer: W,
|
||||||
file_visibility_policy: FileVisibilityPolicy,
|
file_visibility_policy: FileVisibilityPolicy,
|
||||||
mut log_out: D,
|
|
||||||
) -> crate::Result<W>
|
) -> crate::Result<W>
|
||||||
where
|
where
|
||||||
W: Write + Seek,
|
W: Write + Seek,
|
||||||
D: OutputLine,
|
|
||||||
{
|
{
|
||||||
let mut writer = zip::ZipWriter::new(writer);
|
let mut writer = zip::ZipWriter::new(writer);
|
||||||
let options = zip::write::FileOptions::default();
|
let options = zip::write::FileOptions::default();
|
||||||
@ -183,7 +174,6 @@ where
|
|||||||
if let Ok(ref handle) = output_handle {
|
if let Ok(ref 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) {
|
||||||
warning!(
|
warning!(
|
||||||
@log_out,
|
|
||||||
"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()
|
||||||
);
|
);
|
||||||
@ -195,7 +185,7 @@ where
|
|||||||
// little importance for most users, but would generate lots of
|
// little importance for most users, but would generate lots of
|
||||||
// spoken text for users using screen readers, braille displays
|
// spoken text for users using screen readers, braille displays
|
||||||
// and so on
|
// and so on
|
||||||
info!(@log_out, inaccessible, "Compressing '{}'.", to_utf(path));
|
info!(inaccessible, "Compressing '{}'.", to_utf(path));
|
||||||
|
|
||||||
let metadata = match path.metadata() {
|
let metadata = match path.metadata() {
|
||||||
Ok(metadata) => metadata,
|
Ok(metadata) => metadata,
|
||||||
|
@ -6,7 +6,6 @@ use std::{
|
|||||||
use fs_err as fs;
|
use fs_err as fs;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
accessible::is_running_in_accessible_mode,
|
|
||||||
archive,
|
archive,
|
||||||
commands::warn_user_about_loading_zip_in_memory,
|
commands::warn_user_about_loading_zip_in_memory,
|
||||||
extension::{
|
extension::{
|
||||||
@ -14,7 +13,6 @@ use crate::{
|
|||||||
CompressionFormat::{self, *},
|
CompressionFormat::{self, *},
|
||||||
Extension,
|
Extension,
|
||||||
},
|
},
|
||||||
progress::Progress,
|
|
||||||
utils::{user_wants_to_continue, FileVisibilityPolicy},
|
utils::{user_wants_to_continue, FileVisibilityPolicy},
|
||||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||||
};
|
};
|
||||||
@ -37,15 +35,7 @@ pub fn compress_files(
|
|||||||
question_policy: QuestionPolicy,
|
question_policy: QuestionPolicy,
|
||||||
file_visibility_policy: FileVisibilityPolicy,
|
file_visibility_policy: FileVisibilityPolicy,
|
||||||
) -> crate::Result<bool> {
|
) -> crate::Result<bool> {
|
||||||
// The next lines are for displaying the progress bar
|
|
||||||
// If the input files contain a directory, then the total size will be underestimated
|
// If the input files contain a directory, then the total size will be underestimated
|
||||||
let (total_input_size, precise) = files
|
|
||||||
.iter()
|
|
||||||
.map(|f| (f.metadata().expect("file exists").len(), f.is_file()))
|
|
||||||
.fold((0, true), |(total_size, and_precise), (size, precise)| {
|
|
||||||
(total_size + size, and_precise & precise)
|
|
||||||
});
|
|
||||||
|
|
||||||
let file_writer = BufWriter::with_capacity(BUFFER_CAPACITY, output_file);
|
let file_writer = BufWriter::with_capacity(BUFFER_CAPACITY, output_file);
|
||||||
|
|
||||||
let mut writer: Box<dyn Write> = Box::new(file_writer);
|
let mut writer: Box<dyn Write> = Box::new(file_writer);
|
||||||
@ -81,37 +71,11 @@ pub fn compress_files(
|
|||||||
writer = chain_writer_encoder(&first_format, writer)?;
|
writer = chain_writer_encoder(&first_format, writer)?;
|
||||||
let mut reader = fs::File::open(&files[0]).unwrap();
|
let mut reader = fs::File::open(&files[0]).unwrap();
|
||||||
|
|
||||||
if is_running_in_accessible_mode() {
|
io::copy(&mut reader, &mut writer)?;
|
||||||
io::copy(&mut reader, &mut writer)?;
|
|
||||||
} else {
|
|
||||||
io::copy(
|
|
||||||
&mut Progress::new(total_input_size, precise, true).wrap_read(reader),
|
|
||||||
&mut writer,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Tar => {
|
Tar => {
|
||||||
if is_running_in_accessible_mode() {
|
archive::tar::build_archive_from_paths(&files, output_path, &mut writer, file_visibility_policy)?;
|
||||||
archive::tar::build_archive_from_paths(
|
writer.flush()?;
|
||||||
&files,
|
|
||||||
output_path,
|
|
||||||
&mut writer,
|
|
||||||
file_visibility_policy,
|
|
||||||
io::stderr(),
|
|
||||||
)?;
|
|
||||||
writer.flush()?;
|
|
||||||
} else {
|
|
||||||
let mut progress = Progress::new(total_input_size, precise, true);
|
|
||||||
let mut writer = progress.wrap_write(writer);
|
|
||||||
archive::tar::build_archive_from_paths(
|
|
||||||
&files,
|
|
||||||
output_path,
|
|
||||||
&mut writer,
|
|
||||||
file_visibility_policy,
|
|
||||||
&mut progress,
|
|
||||||
)?;
|
|
||||||
writer.flush()?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Zip => {
|
Zip => {
|
||||||
if !formats.is_empty() {
|
if !formats.is_empty() {
|
||||||
@ -124,28 +88,9 @@ pub fn compress_files(
|
|||||||
|
|
||||||
let mut vec_buffer = Cursor::new(vec![]);
|
let mut vec_buffer = Cursor::new(vec![]);
|
||||||
|
|
||||||
if is_running_in_accessible_mode() {
|
archive::zip::build_archive_from_paths(&files, output_path, &mut vec_buffer, file_visibility_policy)?;
|
||||||
archive::zip::build_archive_from_paths(
|
vec_buffer.rewind()?;
|
||||||
&files,
|
io::copy(&mut vec_buffer, &mut writer)?;
|
||||||
output_path,
|
|
||||||
&mut vec_buffer,
|
|
||||||
file_visibility_policy,
|
|
||||||
io::stderr(),
|
|
||||||
)?;
|
|
||||||
vec_buffer.rewind()?;
|
|
||||||
io::copy(&mut vec_buffer, &mut writer)?;
|
|
||||||
} else {
|
|
||||||
let mut progress = Progress::new(total_input_size, precise, true);
|
|
||||||
archive::zip::build_archive_from_paths(
|
|
||||||
&files,
|
|
||||||
output_path,
|
|
||||||
&mut vec_buffer,
|
|
||||||
file_visibility_policy,
|
|
||||||
&mut progress,
|
|
||||||
)?;
|
|
||||||
vec_buffer.rewind()?;
|
|
||||||
io::copy(&mut progress.wrap_read(vec_buffer), &mut writer)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ use std::{
|
|||||||
use fs_err as fs;
|
use fs_err as fs;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
accessible::is_running_in_accessible_mode,
|
|
||||||
commands::warn_user_about_loading_zip_in_memory,
|
commands::warn_user_about_loading_zip_in_memory,
|
||||||
extension::{
|
extension::{
|
||||||
split_first_compression_format,
|
split_first_compression_format,
|
||||||
@ -15,7 +14,6 @@ use crate::{
|
|||||||
Extension,
|
Extension,
|
||||||
},
|
},
|
||||||
info,
|
info,
|
||||||
progress::{OutputLine, Progress},
|
|
||||||
utils::{self, nice_directory_display, user_wants_to_continue},
|
utils::{self, nice_directory_display, user_wants_to_continue},
|
||||||
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
QuestionAction, QuestionPolicy, BUFFER_CAPACITY,
|
||||||
};
|
};
|
||||||
@ -34,7 +32,6 @@ pub fn decompress_file(
|
|||||||
question_policy: QuestionPolicy,
|
question_policy: QuestionPolicy,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
assert!(output_dir.exists());
|
assert!(output_dir.exists());
|
||||||
let total_input_size = input_file_path.metadata().expect("file exists").len();
|
|
||||||
let reader = fs::File::open(input_file_path)?;
|
let reader = fs::File::open(input_file_path)?;
|
||||||
|
|
||||||
// Zip archives are special, because they require io::Seek, so it requires it's logic separated
|
// Zip archives are special, because they require io::Seek, so it requires it's logic separated
|
||||||
@ -51,8 +48,7 @@ pub fn decompress_file(
|
|||||||
{
|
{
|
||||||
let zip_archive = zip::ZipArchive::new(reader)?;
|
let zip_archive = zip::ZipArchive::new(reader)?;
|
||||||
let files = if let ControlFlow::Continue(files) = smart_unpack(
|
let files = if let ControlFlow::Continue(files) = smart_unpack(
|
||||||
|output_dir, progress| crate::archive::zip::unpack_archive(zip_archive, output_dir, progress),
|
|output_dir| crate::archive::zip::unpack_archive(zip_archive, output_dir),
|
||||||
total_input_size,
|
|
||||||
output_dir,
|
output_dir,
|
||||||
&output_file_path,
|
&output_file_path,
|
||||||
question_policy,
|
question_policy,
|
||||||
@ -109,21 +105,13 @@ pub fn decompress_file(
|
|||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_running_in_accessible_mode() {
|
io::copy(&mut reader, &mut writer)?;
|
||||||
io::copy(&mut reader, &mut writer)?;
|
|
||||||
} else {
|
|
||||||
io::copy(
|
|
||||||
&mut Progress::new(total_input_size, true, true).wrap_read(reader),
|
|
||||||
&mut writer,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec![output_file_path]
|
vec![output_file_path]
|
||||||
}
|
}
|
||||||
Tar => {
|
Tar => {
|
||||||
if let ControlFlow::Continue(files) = smart_unpack(
|
if let ControlFlow::Continue(files) = smart_unpack(
|
||||||
|output_dir, progress| crate::archive::tar::unpack_archive(reader, output_dir, progress),
|
|output_dir| crate::archive::tar::unpack_archive(reader, output_dir),
|
||||||
total_input_size,
|
|
||||||
output_dir,
|
output_dir,
|
||||||
&output_file_path,
|
&output_file_path,
|
||||||
question_policy,
|
question_policy,
|
||||||
@ -147,8 +135,7 @@ pub fn decompress_file(
|
|||||||
let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?;
|
let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?;
|
||||||
|
|
||||||
if let ControlFlow::Continue(files) = smart_unpack(
|
if let ControlFlow::Continue(files) = smart_unpack(
|
||||||
|output_dir, progress| crate::archive::zip::unpack_archive(zip_archive, output_dir, progress),
|
|output_dir| crate::archive::zip::unpack_archive(zip_archive, output_dir),
|
||||||
total_input_size,
|
|
||||||
output_dir,
|
output_dir,
|
||||||
&output_file_path,
|
&output_file_path,
|
||||||
question_policy,
|
question_policy,
|
||||||
@ -180,8 +167,7 @@ pub fn decompress_file(
|
|||||||
/// output_dir named after the archive (given by `output_file_path`)
|
/// output_dir named after the archive (given by `output_file_path`)
|
||||||
/// Note: This functions assumes that `output_dir` exists
|
/// Note: This functions assumes that `output_dir` exists
|
||||||
fn smart_unpack(
|
fn smart_unpack(
|
||||||
unpack_fn: impl FnOnce(&Path, &mut dyn OutputLine) -> crate::Result<Vec<PathBuf>>,
|
unpack_fn: impl FnOnce(&Path) -> crate::Result<Vec<PathBuf>>,
|
||||||
total_input_size: u64,
|
|
||||||
output_dir: &Path,
|
output_dir: &Path,
|
||||||
output_file_path: &Path,
|
output_file_path: &Path,
|
||||||
question_policy: QuestionPolicy,
|
question_policy: QuestionPolicy,
|
||||||
@ -195,12 +181,7 @@ fn smart_unpack(
|
|||||||
nice_directory_display(temp_dir_path)
|
nice_directory_display(temp_dir_path)
|
||||||
);
|
);
|
||||||
|
|
||||||
// unpack the files
|
let files = unpack_fn(temp_dir_path)?;
|
||||||
let files = if is_running_in_accessible_mode() {
|
|
||||||
unpack_fn(temp_dir_path, &mut io::stderr())
|
|
||||||
} else {
|
|
||||||
unpack_fn(temp_dir_path, &mut Progress::new(total_input_size, true, false))
|
|
||||||
}?;
|
|
||||||
|
|
||||||
let root_contains_only_one_element = fs::read_dir(temp_dir_path)?.count() == 1;
|
let root_contains_only_one_element = fs::read_dir(temp_dir_path)?.count() == 1;
|
||||||
if root_contains_only_one_element {
|
if root_contains_only_one_element {
|
||||||
@ -237,5 +218,6 @@ fn smart_unpack(
|
|||||||
nice_directory_display(output_file_path)
|
nice_directory_display(output_file_path)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ControlFlow::Continue(files))
|
Ok(ControlFlow::Continue(files))
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ use crate::{
|
|||||||
extension::{self, flatten_compression_formats, Extension, SUPPORTED_EXTENSIONS},
|
extension::{self, flatten_compression_formats, Extension, SUPPORTED_EXTENSIONS},
|
||||||
info,
|
info,
|
||||||
list::ListOptions,
|
list::ListOptions,
|
||||||
progress::OutputLine,
|
|
||||||
utils::{
|
utils::{
|
||||||
self, dir_is_empty, pretty_format_list_of_paths, to_utf, try_infer_extension, user_wants_to_continue,
|
self, dir_is_empty, pretty_format_list_of_paths, to_utf, try_infer_extension, user_wants_to_continue,
|
||||||
FileVisibilityPolicy,
|
FileVisibilityPolicy,
|
||||||
|
@ -7,8 +7,6 @@ use std::{
|
|||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
};
|
};
|
||||||
|
|
||||||
use indicatif::style::TemplateError;
|
|
||||||
|
|
||||||
use crate::{accessible::is_running_in_accessible_mode, utils::colors::*};
|
use crate::{accessible::is_running_in_accessible_mode, utils::colors::*};
|
||||||
|
|
||||||
/// All errors that can be generated by `ouch`
|
/// All errors that can be generated by `ouch`
|
||||||
@ -32,8 +30,6 @@ pub enum Error {
|
|||||||
CompressingRootFolder,
|
CompressingRootFolder,
|
||||||
/// Specialized walkdir's io::Error wrapper with additional information on the error
|
/// Specialized walkdir's io::Error wrapper with additional information on the error
|
||||||
WalkdirError { reason: String },
|
WalkdirError { reason: String },
|
||||||
/// TemplateError from
|
|
||||||
TemplateError(TemplateError),
|
|
||||||
/// Custom and unique errors are reported in this variant
|
/// Custom and unique errors are reported in this variant
|
||||||
Custom { reason: FinalError },
|
Custom { reason: FinalError },
|
||||||
}
|
}
|
||||||
@ -139,9 +135,6 @@ impl fmt::Display for Error {
|
|||||||
FinalError::with_title(error_title.to_string()).detail("Permission denied")
|
FinalError::with_title(error_title.to_string()).detail("Permission denied")
|
||||||
}
|
}
|
||||||
Error::UnsupportedZipArchive(reason) => FinalError::with_title("Unsupported zip archive").detail(*reason),
|
Error::UnsupportedZipArchive(reason) => FinalError::with_title("Unsupported zip archive").detail(*reason),
|
||||||
Error::TemplateError(reason) => {
|
|
||||||
FinalError::with_title(reason.to_string()).detail("Progress bar template error")
|
|
||||||
}
|
|
||||||
Error::Custom { reason } => reason.clone(),
|
Error::Custom { reason } => reason.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
16
src/list.rs
16
src/list.rs
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
|
||||||
|
|
||||||
use self::tree::Tree;
|
use self::tree::Tree;
|
||||||
use crate::accessible::is_running_in_accessible_mode;
|
use crate::accessible::is_running_in_accessible_mode;
|
||||||
|
|
||||||
@ -34,27 +32,13 @@ pub fn list_files(
|
|||||||
println!("Archive: {}", archive.display());
|
println!("Archive: {}", archive.display());
|
||||||
|
|
||||||
if list_options.tree {
|
if list_options.tree {
|
||||||
let pb = if !is_running_in_accessible_mode() {
|
|
||||||
let template = "{wide_msg} [{elapsed_precise}] {spinner:.green}";
|
|
||||||
let style = ProgressStyle::with_template(template).map_err(crate::Error::TemplateError)?;
|
|
||||||
Some(ProgressBar::new_spinner().with_style(style))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let tree: Tree = files
|
let tree: Tree = files
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|file| {
|
.map(|file| {
|
||||||
let file = file?;
|
let file = file?;
|
||||||
if !is_running_in_accessible_mode() {
|
|
||||||
pb.as_ref()
|
|
||||||
.expect("exists")
|
|
||||||
.set_message(format!("Processing: {}", file.path.display()));
|
|
||||||
}
|
|
||||||
Ok(file)
|
Ok(file)
|
||||||
})
|
})
|
||||||
.collect::<crate::Result<Tree>>()?;
|
.collect::<crate::Result<Tree>>()?;
|
||||||
drop(pb);
|
|
||||||
tree.print();
|
tree.print();
|
||||||
} else {
|
} else {
|
||||||
for file in files {
|
for file in files {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
//! Macros used on ouch.
|
//! Macros used on ouch.
|
||||||
|
|
||||||
use crate::accessible::is_running_in_accessible_mode;
|
/// Macro that prints \[INFO\] messages, wraps [`eprintln`].
|
||||||
|
|
||||||
/// Macro that prints \[INFO\] messages, wraps [`println`].
|
|
||||||
///
|
///
|
||||||
/// There are essentially two different versions of the `info!()` macro:
|
/// There are essentially two different versions of the `info!()` macro:
|
||||||
/// - `info!(accessible, ...)` should only be used for short, important
|
/// - `info!(accessible, ...)` should only be used for short, important
|
||||||
@ -16,58 +14,45 @@ use crate::accessible::is_running_in_accessible_mode;
|
|||||||
/// while it would generate long and hard to navigate text for blind people
|
/// while it would generate long and hard to navigate text for blind people
|
||||||
/// who have to have each line of output read to them aloud, whithout to
|
/// who have to have each line of output read to them aloud, whithout to
|
||||||
/// ability to skip some lines deemed not important like a seeing person would.
|
/// ability to skip some lines deemed not important like a seeing person would.
|
||||||
///
|
|
||||||
/// By default `info` outputs to Stdout, if you want to specify the output you can use
|
|
||||||
/// `@log_out` modifier
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! info {
|
macro_rules! info {
|
||||||
// Accessible (short/important) info message.
|
// Accessible (short/important) info message.
|
||||||
// Show info message even in ACCESSIBLE mode
|
// Show info message even in ACCESSIBLE mode
|
||||||
(accessible, $($arg:tt)*) => {
|
(accessible, $($arg:tt)*) => {{
|
||||||
info!(@::std::io::stderr(), accessible, $($arg)*);
|
use $crate::utils::colors::{YELLOW, RESET};
|
||||||
};
|
|
||||||
(@$log_out: expr, accessible, $($arg:tt)*) => {{
|
if $crate::accessible::is_running_in_accessible_mode() {
|
||||||
// if in ACCESSIBLE mode, suppress the "[INFO]" and just print the message
|
eprint!("{}Info:{} ", *YELLOW, *RESET);
|
||||||
if !$crate::accessible::is_running_in_accessible_mode() {
|
|
||||||
$log_out.output_line_info(format_args!($($arg)*));
|
|
||||||
} else {
|
} else {
|
||||||
$log_out.output_line(format_args!($($arg)*));
|
eprint!("{}[INFO]{} ", *YELLOW, *RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eprintln!($($arg)*);
|
||||||
}};
|
}};
|
||||||
// Inccessible (long/no important) info message.
|
// Inccessible (long/no important) info message.
|
||||||
// Print info message if ACCESSIBLE is not turned on
|
// Print info message if ACCESSIBLE is not turned on
|
||||||
(inaccessible, $($arg:tt)*) => {
|
(inaccessible, $($arg:tt)*) => {{
|
||||||
info!(@::std::io::stderr(), inaccessible, $($arg)*);
|
use $crate::utils::colors::{YELLOW, RESET};
|
||||||
};
|
|
||||||
(@$log_out: expr, inaccessible, $($arg:tt)*) => {{
|
|
||||||
if !$crate::accessible::is_running_in_accessible_mode() {
|
if !$crate::accessible::is_running_in_accessible_mode() {
|
||||||
$log_out.output_line_info(format_args!($($arg)*));
|
eprint!("{}[INFO]{} ", *YELLOW, *RESET);
|
||||||
|
eprintln!($($arg)*);
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro that prints \[WARNING\] messages, wraps [`eprintln`].
|
/// Macro that prints WARNING messages, wraps [`eprintln`].
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! warning {
|
macro_rules! warning {
|
||||||
(@$log_out: expr, $($arg:tt)*) => {
|
($($arg:tt)*) => {{
|
||||||
if !$crate::accessible::is_running_in_accessible_mode() {
|
use $crate::utils::colors::{ORANGE, RESET};
|
||||||
$log_out.output_line_warning(format_args!($($arg)*));
|
|
||||||
|
if $crate::accessible::is_running_in_accessible_mode() {
|
||||||
|
eprint!("{}Warning:{} ", *ORANGE, *RESET);
|
||||||
|
} else {
|
||||||
|
eprint!("{}[WARNING]{} ", *ORANGE, *RESET);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
($($arg:tt)*) => {
|
|
||||||
$crate::macros::_warning_helper();
|
|
||||||
eprintln!($($arg)*);
|
eprintln!($($arg)*);
|
||||||
};
|
}};
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper to display "\[WARNING\]", colored orange
|
|
||||||
pub fn _warning_helper() {
|
|
||||||
use crate::utils::colors::{ORANGE, RESET};
|
|
||||||
|
|
||||||
if is_running_in_accessible_mode() {
|
|
||||||
eprint!("{}Warning:{} ", *ORANGE, *RESET);
|
|
||||||
} else {
|
|
||||||
eprint!("{}[WARNING]{} ", *ORANGE, *RESET);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ pub mod commands;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod extension;
|
pub mod extension;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod progress;
|
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
/// CLI argparsing definitions, using `clap`.
|
/// CLI argparsing definitions, using `clap`.
|
||||||
|
100
src/progress.rs
100
src/progress.rs
@ -1,100 +0,0 @@
|
|||||||
//! Module that provides functions to display progress bars for compressing and decompressing files.
|
|
||||||
use std::{
|
|
||||||
fmt::Arguments,
|
|
||||||
io::{Read, Stderr, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use indicatif::{ProgressBar, ProgressBarIter, ProgressStyle};
|
|
||||||
|
|
||||||
use crate::utils::colors::{ORANGE, RESET, YELLOW};
|
|
||||||
|
|
||||||
/// Draw a ProgressBar using a function that checks periodically for the progress
|
|
||||||
pub struct Progress {
|
|
||||||
bar: ProgressBar,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait OutputLine {
|
|
||||||
fn output_line(&mut self, args: Arguments);
|
|
||||||
fn output_line_info(&mut self, args: Arguments);
|
|
||||||
fn output_line_warning(&mut self, args: Arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OutputLine for Progress {
|
|
||||||
fn output_line(&mut self, args: Arguments) {
|
|
||||||
self.bar.set_message(args.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_line_info(&mut self, args: Arguments) {
|
|
||||||
self.bar.set_message(format!("{}[INFO]{} {args}", *YELLOW, *RESET));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_line_warning(&mut self, args: Arguments) {
|
|
||||||
self.bar.println(format!("{}[WARNING]{} {args}", *ORANGE, *RESET));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OutputLine for Stderr {
|
|
||||||
fn output_line(&mut self, args: Arguments) {
|
|
||||||
self.write_fmt(args).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_line_info(&mut self, args: Arguments) {
|
|
||||||
write!(self, "{}[INFO]{} ", *YELLOW, *RESET).unwrap();
|
|
||||||
self.write_fmt(args).unwrap();
|
|
||||||
self.write_all(b"\n").unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_line_warning(&mut self, args: Arguments) {
|
|
||||||
write!(self, "{}[WARNING]{}", *ORANGE, *RESET).unwrap();
|
|
||||||
self.write_fmt(args).unwrap();
|
|
||||||
self.write_all(b"\n").unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: OutputLine + ?Sized> OutputLine for &mut T {
|
|
||||||
fn output_line(&mut self, args: Arguments) {
|
|
||||||
(*self).output_line(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_line_info(&mut self, args: Arguments) {
|
|
||||||
(*self).output_line_info(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_line_warning(&mut self, args: Arguments) {
|
|
||||||
(*self).output_line_warning(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Progress {
|
|
||||||
pub(crate) fn new(total_input_size: u64, precise: bool, position_updates: bool) -> Self {
|
|
||||||
let template = {
|
|
||||||
let mut t = String::new();
|
|
||||||
t += "{wide_msg} [{elapsed_precise}] ";
|
|
||||||
if precise && position_updates {
|
|
||||||
t += "[{bar:.cyan/blue}] ";
|
|
||||||
} else {
|
|
||||||
t += "{spinner:.green} ";
|
|
||||||
}
|
|
||||||
if position_updates {
|
|
||||||
t += "{bytes}/ ";
|
|
||||||
}
|
|
||||||
if precise {
|
|
||||||
t += "{total_bytes} ";
|
|
||||||
}
|
|
||||||
t += "({bytes_per_sec}, {eta}) {path}";
|
|
||||||
t
|
|
||||||
};
|
|
||||||
let bar = ProgressBar::new(total_input_size)
|
|
||||||
.with_style(ProgressStyle::with_template(&template).unwrap().progress_chars("#>-"));
|
|
||||||
|
|
||||||
Progress { bar }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn wrap_read<R: Read>(&self, read: R) -> ProgressBarIter<R> {
|
|
||||||
self.bar.wrap_read(read)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn wrap_write<W: Write>(&self, write: W) -> ProgressBarIter<W> {
|
|
||||||
self.bar.wrap_write(write)
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ use std::{
|
|||||||
use fs_err as fs;
|
use fs_err as fs;
|
||||||
|
|
||||||
use super::{to_utf, user_wants_to_overwrite};
|
use super::{to_utf, user_wants_to_overwrite};
|
||||||
use crate::{extension::Extension, info, progress::OutputLine, QuestionPolicy};
|
use crate::{extension::Extension, info, QuestionPolicy};
|
||||||
|
|
||||||
/// Checks if given path points to an empty directory.
|
/// Checks if given path points to an empty directory.
|
||||||
pub fn dir_is_empty(dir_path: &Path) -> bool {
|
pub fn dir_is_empty(dir_path: &Path) -> bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user