1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge pull request #2221 from jfinkels/head-display-multiple-errors-2

head: display errors for each input file instead of terminating at the first error
This commit is contained in:
Sylvestre Ledru 2021-05-20 23:24:35 +02:00 committed by GitHub
commit efb781f59a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 40 deletions

View file

@ -2,7 +2,7 @@ use clap::{App, Arg};
use std::convert::TryFrom;
use std::ffi::OsString;
use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write};
use uucore::{crash, executable, show_error};
use uucore::{crash, executable, show_error, show_error_custom_description};
const EXIT_FAILURE: i32 = 1;
const EXIT_SUCCESS: i32 = 0;
@ -400,7 +400,8 @@ fn head_file(input: &mut std::fs::File, options: &HeadOptions) -> std::io::Resul
}
}
fn uu_head(options: &HeadOptions) {
fn uu_head(options: &HeadOptions) -> Result<(), u32> {
let mut error_count = 0;
let mut first = true;
for fname in &options.files {
let res = match fname.as_str() {
@ -433,30 +434,22 @@ fn uu_head(options: &HeadOptions) {
name => {
let mut file = match std::fs::File::open(name) {
Ok(f) => f,
Err(err) => match err.kind() {
ErrorKind::NotFound => {
crash!(
EXIT_FAILURE,
"head: cannot open '{}' for reading: No such file or directory",
name
);
Err(err) => {
let prefix = format!("cannot open '{}' for reading", name);
match err.kind() {
ErrorKind::NotFound => {
show_error_custom_description!(prefix, "No such file or directory");
}
ErrorKind::PermissionDenied => {
show_error_custom_description!(prefix, "Permission denied");
}
_ => {
show_error_custom_description!(prefix, "{}", err);
}
}
ErrorKind::PermissionDenied => {
crash!(
EXIT_FAILURE,
"head: cannot open '{}' for reading: Permission denied",
name
);
}
_ => {
crash!(
EXIT_FAILURE,
"head: cannot open '{}' for reading: {}",
name,
err
);
}
},
error_count += 1;
continue;
}
};
if (options.files.len() > 1 && !options.quiet) || options.verbose {
if !first {
@ -468,21 +461,22 @@ fn uu_head(options: &HeadOptions) {
}
};
if res.is_err() {
if fname.as_str() == "-" {
crash!(
EXIT_FAILURE,
"head: error reading standard input: Input/output error"
);
let name = if fname.as_str() == "-" {
"standard input"
} else {
crash!(
EXIT_FAILURE,
"head: error reading {}: Input/output error",
fname
);
}
fname
};
let prefix = format!("error reading {}", name);
show_error_custom_description!(prefix, "Input/output error");
error_count += 1;
}
first = false;
}
if error_count > 0 {
Err(error_count)
} else {
Ok(())
}
}
pub fn uumain(args: impl uucore::Args) -> i32 {
@ -492,9 +486,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
crash!(EXIT_FAILURE, "head: {}", s);
}
};
uu_head(&args);
EXIT_SUCCESS
match uu_head(&args) {
Ok(_) => EXIT_SUCCESS,
Err(_) => EXIT_FAILURE,
}
}
#[cfg(test)]

View file

@ -162,6 +162,18 @@ fn test_no_such_file_or_directory() {
.stderr_contains("cannot open 'no_such_file.toml' for reading: No such file or directory");
}
/// Test that each non-existent files gets its own error message printed.
#[test]
fn test_multiple_nonexistent_files() {
new_ucmd!()
.args(&["bogusfile1", "bogusfile2"])
.fails()
.stdout_does_not_contain("==> bogusfile1 <==")
.stderr_contains("cannot open 'bogusfile1' for reading: No such file or directory")
.stdout_does_not_contain("==> bogusfile2 <==")
.stderr_contains("cannot open 'bogusfile2' for reading: No such file or directory");
}
// there was a bug not caught by previous tests
// where for negative n > 3, the total amount of lines
// was correct, but it would eat from the second line

View file

@ -315,7 +315,12 @@ impl CmdResult {
}
pub fn stdout_does_not_contain<T: AsRef<str>>(&self, cmp: T) -> &CmdResult {
assert!(!self.stdout_str().contains(cmp.as_ref()));
assert!(
!self.stdout_str().contains(cmp.as_ref()),
"'{}' contains '{}' but should not",
self.stdout_str(),
cmp.as_ref(),
);
self
}