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:
commit
efb781f59a
3 changed files with 52 additions and 40 deletions
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue