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