1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

ls: adapt to standardized error handling

This commit is contained in:
Terts Diepraam 2021-06-28 13:44:39 +02:00
parent 60e4621c3b
commit e4eac825fb

View file

@ -26,10 +26,11 @@ use quoting_style::{escape_name, QuotingStyle};
use std::os::windows::fs::MetadataExt;
use std::{
cmp::Reverse,
error::Error,
fmt::Display,
fs::{self, DirEntry, FileType, Metadata},
io::{stdout, BufWriter, Stdout, Write},
path::{Path, PathBuf},
process::exit,
time::{SystemTime, UNIX_EPOCH},
};
#[cfg(unix)]
@ -38,8 +39,8 @@ use std::{
os::unix::fs::{FileTypeExt, MetadataExt},
time::Duration,
};
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
use uucore::error::{set_exit_code, FromIo, UCustomError, UResult};
use unicode_width::UnicodeWidthStr;
#[cfg(unix)]
@ -125,6 +126,32 @@ pub mod options {
pub static IGNORE: &str = "ignore";
}
#[derive(Debug)]
enum LsError {
InvalidLineWidth(String),
NoMetadata(PathBuf),
}
impl UCustomError for LsError {
fn code(&self) -> i32 {
match self {
LsError::InvalidLineWidth(_) => 2,
LsError::NoMetadata(_) => 1,
}
}
}
impl Error for LsError {}
impl Display for LsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LsError::InvalidLineWidth(s) => write!(f, "invalid line width: '{}'", s),
LsError::NoMetadata(p) => write!(f, "could not open file: '{}'", p.display()),
}
}
}
#[derive(PartialEq, Eq)]
enum Format {
Columns,
@ -218,7 +245,7 @@ struct LongFormat {
impl Config {
#[allow(clippy::cognitive_complexity)]
fn from(options: clap::ArgMatches) -> Config {
fn from(options: clap::ArgMatches) -> UResult<Config> {
let (mut format, opt) = if let Some(format_) = options.value_of(options::FORMAT) {
(
match format_ {
@ -369,15 +396,13 @@ impl Config {
}
};
let width = options
.value_of(options::WIDTH)
.map(|x| {
x.parse::<u16>().unwrap_or_else(|_e| {
show_error!("invalid line width: '{}'", x);
exit(2);
})
})
.or_else(|| termsize::get().map(|s| s.cols));
let width = match options.value_of(options::WIDTH) {
Some(x) => match x.parse::<u16>() {
Ok(u) => Some(u),
Err(_) => return Err(LsError::InvalidLineWidth(x.into()).into()),
},
None => termsize::get().map(|s| s.cols),
};
#[allow(clippy::needless_bool)]
let show_control = if options.is_present(options::HIDE_CONTROL_CHARS) {
@ -528,7 +553,7 @@ impl Config {
Dereference::DirArgs
};
Config {
Ok(Config {
format,
files,
sort,
@ -547,11 +572,12 @@ impl Config {
quoting_style,
indicator_style,
time_style,
}
})
}
}
pub fn uumain(args: impl uucore::Args) -> i32 {
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = args
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
@ -567,7 +593,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_else(|| vec![String::from(".")]);
list(locs, Config::from(matches))
list(locs, Config::from(matches)?)
}
pub fn uu_app() -> App<'static, 'static> {
@ -1190,10 +1216,9 @@ impl PathData {
}
}
fn list(locs: Vec<String>, config: Config) -> i32 {
fn list(locs: Vec<String>, config: Config) -> UResult<()> {
let mut files = Vec::<PathData>::new();
let mut dirs = Vec::<PathData>::new();
let mut has_failed = false;
let mut out = BufWriter::new(stdout());
@ -1202,19 +1227,16 @@ fn list(locs: Vec<String>, config: Config) -> i32 {
let path_data = PathData::new(p, None, None, &config, true);
if path_data.md().is_none() {
show_error!("'{}': {}", &loc, "No such file or directory");
/*
We found an error, the return code of ls should not be 0
And no need to continue the execution
*/
has_failed = true;
show!(std::io::ErrorKind::NotFound
.map_err_context(|| format!("cannot access '{}'", path_data.p_buf.display())));
// We found an error, no need to continue the execution
continue;
}
let show_dir_contents = match path_data.file_type() {
Some(ft) => !config.directory && ft.is_dir(),
None => {
has_failed = true;
set_exit_code(1);
false
}
};
@ -1235,11 +1257,8 @@ fn list(locs: Vec<String>, config: Config) -> i32 {
}
enter_directory(&dir, &config, &mut out);
}
if has_failed {
1
} else {
0
}
Ok(())
}
fn sort_entries(entries: &mut Vec<PathData>, config: &Config) {
@ -1478,7 +1497,7 @@ fn display_item_long(
) {
let md = match item.md() {
None => {
show_error!("could not show file: {}", &item.p_buf.display());
show!(LsError::NoMetadata(item.p_buf.clone()));
return;
}
Some(md) => md,