From 9d123febb3a950414ff5c16fcae0d4e631e1f4aa Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 21 Mar 2025 16:31:55 +0100 Subject: [PATCH] install: move to thiserror --- src/uu/install/Cargo.toml | 1 + src/uu/install/src/install.rs | 97 +++++++++++++++-------------------- 2 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/uu/install/Cargo.toml b/src/uu/install/Cargo.toml index dd9a5c8ae..3b2724436 100644 --- a/src/uu/install/Cargo.toml +++ b/src/uu/install/Cargo.toml @@ -21,6 +21,7 @@ clap = { workspace = true } filetime = { workspace = true } file_diff = { workspace = true } libc = { workspace = true } +thiserror = { workspace = true } uucore = { workspace = true, features = [ "backup-control", "buf-copy", diff --git a/src/uu/install/src/install.rs b/src/uu/install/src/install.rs index bffc93974..42de1ef0c 100644 --- a/src/uu/install/src/install.rs +++ b/src/uu/install/src/install.rs @@ -10,22 +10,22 @@ mod mode; use clap::{Arg, ArgAction, ArgMatches, Command}; use file_diff::diff; use filetime::{set_file_times, FileTime}; -use std::error::Error; -use std::fmt::{Debug, Display}; +use std::fmt::Debug; use std::fs::File; use std::fs::{self, metadata}; use std::path::{Path, PathBuf, MAIN_SEPARATOR}; use std::process; +use thiserror::Error; use uucore::backup_control::{self, BackupMode}; use uucore::buf_copy::copy_stream; use uucore::display::Quotable; use uucore::entries::{grp2gid, usr2uid}; -use uucore::error::{FromIo, UError, UIoError, UResult, UUsageError}; +use uucore::error::{FromIo, UError, UResult, UUsageError}; use uucore::fs::dir_strip_dot_for_creation; use uucore::mode::get_umask; use uucore::perms::{wrap_chown, Verbosity, VerbosityLevel}; use uucore::process::{getegid, geteuid}; -use uucore::{format_usage, help_about, help_usage, show, show_error, show_if_err, uio_error}; +use uucore::{format_usage, help_about, help_usage, show, show_error, show_if_err}; #[cfg(unix)] use std::os::unix::fs::{FileTypeExt, MetadataExt}; @@ -52,22 +52,51 @@ pub struct Behavior { target_dir: Option, } -#[derive(Debug)] +#[derive(Error, Debug)] enum InstallError { + #[error("Unimplemented feature: {0}")] Unimplemented(String), - DirNeedsArg(), - CreateDirFailed(PathBuf, std::io::Error), + + #[error("{} with -d requires at least one argument.", uucore::util_name())] + DirNeedsArg, + + #[error("failed to create {0}")] + CreateDirFailed(PathBuf, #[source] std::io::Error), + + #[error("failed to chmod {}", .0.quote())] ChmodFailed(PathBuf), + + #[error("failed to chown {}: {}", .0.quote(), .1)] ChownFailed(PathBuf, String), + + #[error("invalid target {}: No such file or directory", .0.quote())] InvalidTarget(PathBuf), + + #[error("target {} is not a directory", .0.quote())] TargetDirIsntDir(PathBuf), - BackupFailed(PathBuf, PathBuf, std::io::Error), - InstallFailed(PathBuf, PathBuf, std::io::Error), + + #[error("cannot backup {0} to {1}")] + BackupFailed(PathBuf, PathBuf, #[source] std::io::Error), + + #[error("cannot install {0} to {1}")] + InstallFailed(PathBuf, PathBuf, #[source] std::io::Error), + + #[error("strip program failed: {0}")] StripProgramFailed(String), - MetadataFailed(std::io::Error), + + #[error("metadata error")] + MetadataFailed(#[source] std::io::Error), + + #[error("invalid user: {}", .0.quote())] InvalidUser(String), + + #[error("invalid group: {}", .0.quote())] InvalidGroup(String), + + #[error("omitting directory {}", .0.quote())] OmittingDirectory(PathBuf), + + #[error("failed to access {}: Not a directory", .0.quote())] NotADirectory(PathBuf), } @@ -84,52 +113,6 @@ impl UError for InstallError { } } -impl Error for InstallError {} - -impl Display for InstallError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Unimplemented(opt) => write!(f, "Unimplemented feature: {opt}"), - Self::DirNeedsArg() => { - write!( - f, - "{} with -d requires at least one argument.", - uucore::util_name() - ) - } - Self::CreateDirFailed(dir, e) => { - Display::fmt(&uio_error!(e, "failed to create {}", dir.quote()), f) - } - Self::ChmodFailed(file) => write!(f, "failed to chmod {}", file.quote()), - Self::ChownFailed(file, msg) => write!(f, "failed to chown {}: {}", file.quote(), msg), - Self::InvalidTarget(target) => write!( - f, - "invalid target {}: No such file or directory", - target.quote() - ), - Self::TargetDirIsntDir(target) => { - write!(f, "target {} is not a directory", target.quote()) - } - Self::BackupFailed(from, to, e) => Display::fmt( - &uio_error!(e, "cannot backup {} to {}", from.quote(), to.quote()), - f, - ), - Self::InstallFailed(from, to, e) => Display::fmt( - &uio_error!(e, "cannot install {} to {}", from.quote(), to.quote()), - f, - ), - Self::StripProgramFailed(msg) => write!(f, "strip program failed: {msg}"), - Self::MetadataFailed(e) => Display::fmt(&uio_error!(e, ""), f), - Self::InvalidUser(user) => write!(f, "invalid user: {}", user.quote()), - Self::InvalidGroup(group) => write!(f, "invalid group: {}", group.quote()), - Self::OmittingDirectory(dir) => write!(f, "omitting directory {}", dir.quote()), - Self::NotADirectory(dir) => { - write!(f, "failed to access {}: Not a directory", dir.quote()) - } - } - } -} - #[derive(Clone, Eq, PartialEq)] pub enum MainFunction { /// Create directories @@ -456,7 +439,7 @@ fn behavior(matches: &ArgMatches) -> UResult { /// fn directory(paths: &[String], b: &Behavior) -> UResult<()> { if paths.is_empty() { - Err(InstallError::DirNeedsArg().into()) + Err(InstallError::DirNeedsArg.into()) } else { for path in paths.iter().map(Path::new) { // if the path already exist, don't try to create it again