mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
Merge pull request #7207 from sylvestre/thiserror3
Move other programs to thiserror
This commit is contained in:
commit
dfd5885e37
11 changed files with 68 additions and 147 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -2678,6 +2678,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"glob",
|
"glob",
|
||||||
|
"thiserror 2.0.11",
|
||||||
"uucore",
|
"uucore",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
@ -2764,6 +2765,7 @@ name = "uu_groups"
|
||||||
version = "0.0.29"
|
version = "0.0.29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"thiserror 2.0.11",
|
||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2922,6 +2924,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"rand",
|
"rand",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"thiserror 2.0.11",
|
||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2973,6 +2976,7 @@ version = "0.0.29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"libc",
|
"libc",
|
||||||
|
"thiserror 2.0.11",
|
||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3346,6 +3350,7 @@ name = "uu_tsort"
|
||||||
version = "0.0.29"
|
version = "0.0.29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"thiserror 2.0.11",
|
||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ chrono = { workspace = true }
|
||||||
glob = { workspace = true }
|
glob = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
uucore = { workspace = true, features = ["format"] }
|
uucore = { workspace = true, features = ["format"] }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
windows-sys = { workspace = true, features = [
|
windows-sys = { workspace = true, features = [
|
||||||
|
|
|
@ -8,8 +8,6 @@ use clap::{builder::PossibleValue, crate_version, Arg, ArgAction, ArgMatches, Co
|
||||||
use glob::Pattern;
|
use glob::Pattern;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::Display;
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
use std::fs::Metadata;
|
use std::fs::Metadata;
|
||||||
use std::fs::{self, DirEntry, File};
|
use std::fs::{self, DirEntry, File};
|
||||||
|
@ -25,6 +23,7 @@ use std::str::FromStr;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
|
use thiserror::Error;
|
||||||
use uucore::display::{print_verbatim, Quotable};
|
use uucore::display::{print_verbatim, Quotable};
|
||||||
use uucore::error::{set_exit_code, FromIo, UError, UResult, USimpleError};
|
use uucore::error::{set_exit_code, FromIo, UError, UResult, USimpleError};
|
||||||
use uucore::line_ending::LineEnding;
|
use uucore::line_ending::LineEnding;
|
||||||
|
@ -409,48 +408,26 @@ fn du(
|
||||||
Ok(my_stat)
|
Ok(my_stat)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
enum DuError {
|
enum DuError {
|
||||||
|
#[error("invalid maximum depth {depth}", depth = .0.quote())]
|
||||||
InvalidMaxDepthArg(String),
|
InvalidMaxDepthArg(String),
|
||||||
|
|
||||||
|
#[error("summarizing conflicts with --max-depth={depth}", depth = .0.maybe_quote())]
|
||||||
SummarizeDepthConflict(String),
|
SummarizeDepthConflict(String),
|
||||||
|
|
||||||
|
#[error("invalid argument {style} for 'time style'\nValid arguments are:\n- 'full-iso'\n- 'long-iso'\n- 'iso'\nTry '{help}' for more information.",
|
||||||
|
style = .0.quote(),
|
||||||
|
help = uucore::execution_phrase())]
|
||||||
InvalidTimeStyleArg(String),
|
InvalidTimeStyleArg(String),
|
||||||
|
|
||||||
|
#[error("'birth' and 'creation' arguments for --time are not supported on this platform.")]
|
||||||
InvalidTimeArg,
|
InvalidTimeArg,
|
||||||
|
|
||||||
|
#[error("Invalid exclude syntax: {0}")]
|
||||||
InvalidGlob(String),
|
InvalidGlob(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for DuError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::InvalidMaxDepthArg(s) => write!(f, "invalid maximum depth {}", s.quote()),
|
|
||||||
Self::SummarizeDepthConflict(s) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"summarizing conflicts with --max-depth={}",
|
|
||||||
s.maybe_quote()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Self::InvalidTimeStyleArg(s) => write!(
|
|
||||||
f,
|
|
||||||
"invalid argument {} for 'time style'
|
|
||||||
Valid arguments are:
|
|
||||||
- 'full-iso'
|
|
||||||
- 'long-iso'
|
|
||||||
- 'iso'
|
|
||||||
Try '{} --help' for more information.",
|
|
||||||
s.quote(),
|
|
||||||
uucore::execution_phrase()
|
|
||||||
),
|
|
||||||
Self::InvalidTimeArg => write!(
|
|
||||||
f,
|
|
||||||
"'birth' and 'creation' arguments for --time are not supported on this platform.",
|
|
||||||
),
|
|
||||||
Self::InvalidGlob(s) => write!(f, "Invalid exclude syntax: {s}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for DuError {}
|
|
||||||
|
|
||||||
impl UError for DuError {
|
impl UError for DuError {
|
||||||
fn code(&self) -> i32 {
|
fn code(&self) -> i32 {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -18,6 +18,7 @@ path = "src/groups.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
uucore = { workspace = true, features = ["entries", "process"] }
|
uucore = { workspace = true, features = ["entries", "process"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -2,18 +2,10 @@
|
||||||
//
|
//
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
//
|
|
||||||
// ============================================================================
|
|
||||||
// Test suite summary for GNU coreutils 8.32.162-4eda
|
|
||||||
// ============================================================================
|
|
||||||
// PASS: tests/misc/groups-dash.sh
|
|
||||||
// PASS: tests/misc/groups-process-all.sh
|
|
||||||
// PASS: tests/misc/groups-version.sh
|
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) passwd
|
// spell-checker:ignore (ToDO) passwd
|
||||||
|
|
||||||
use std::error::Error;
|
use thiserror::Error;
|
||||||
use std::fmt::Display;
|
|
||||||
use uucore::{
|
use uucore::{
|
||||||
display::Quotable,
|
display::Quotable,
|
||||||
entries::{get_groups_gnu, gid2grp, Locate, Passwd},
|
entries::{get_groups_gnu, gid2grp, Locate, Passwd},
|
||||||
|
@ -29,26 +21,20 @@ mod options {
|
||||||
const ABOUT: &str = help_about!("groups.md");
|
const ABOUT: &str = help_about!("groups.md");
|
||||||
const USAGE: &str = help_usage!("groups.md");
|
const USAGE: &str = help_usage!("groups.md");
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
enum GroupsError {
|
enum GroupsError {
|
||||||
|
#[error("failed to fetch groups")]
|
||||||
GetGroupsFailed,
|
GetGroupsFailed,
|
||||||
|
|
||||||
|
#[error("cannot find name for group ID {0}")]
|
||||||
GroupNotFound(u32),
|
GroupNotFound(u32),
|
||||||
|
|
||||||
|
#[error("{user}: no such user", user = .0.quote())]
|
||||||
UserNotFound(String),
|
UserNotFound(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for GroupsError {}
|
|
||||||
impl UError for GroupsError {}
|
impl UError for GroupsError {}
|
||||||
|
|
||||||
impl Display for GroupsError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::GetGroupsFailed => write!(f, "failed to fetch groups"),
|
|
||||||
Self::GroupNotFound(gid) => write!(f, "cannot find name for group ID {gid}"),
|
|
||||||
Self::UserNotFound(user) => write!(f, "{}: no such user", user.quote()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn infallible_gid2grp(gid: &u32) -> String {
|
fn infallible_gid2grp(gid: &u32) -> String {
|
||||||
match gid2grp(*gid) {
|
match gid2grp(*gid) {
|
||||||
Ok(grp) => grp,
|
Ok(grp) => grp,
|
||||||
|
|
|
@ -20,6 +20,7 @@ path = "src/mktemp.rs"
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
uucore = { workspace = true }
|
uucore = { workspace = true }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -11,9 +11,7 @@ use uucore::error::{FromIo, UError, UResult, UUsageError};
|
||||||
use uucore::{format_usage, help_about, help_usage};
|
use uucore::{format_usage, help_about, help_usage};
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fmt::Display;
|
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
||||||
|
@ -25,6 +23,7 @@ use std::os::unix::prelude::PermissionsExt;
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use tempfile::Builder;
|
use tempfile::Builder;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
const ABOUT: &str = help_about!("mktemp.md");
|
const ABOUT: &str = help_about!("mktemp.md");
|
||||||
const USAGE: &str = help_usage!("mktemp.md");
|
const USAGE: &str = help_usage!("mktemp.md");
|
||||||
|
@ -46,21 +45,35 @@ const TMPDIR_ENV_VAR: &str = "TMPDIR";
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
const TMPDIR_ENV_VAR: &str = "TMP";
|
const TMPDIR_ENV_VAR: &str = "TMP";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
enum MkTempError {
|
enum MkTempError {
|
||||||
|
#[error("could not persist file {path}", path = .0.quote())]
|
||||||
PersistError(PathBuf),
|
PersistError(PathBuf),
|
||||||
|
|
||||||
|
#[error("with --suffix, template {template} must end in X", template = .0.quote())]
|
||||||
MustEndInX(String),
|
MustEndInX(String),
|
||||||
|
|
||||||
|
#[error("too few X's in template {template}", template = .0.quote())]
|
||||||
TooFewXs(String),
|
TooFewXs(String),
|
||||||
|
|
||||||
/// The template prefix contains a path separator (e.g. `"a/bXXX"`).
|
/// The template prefix contains a path separator (e.g. `"a/bXXX"`).
|
||||||
|
#[error("invalid template, {template}, contains directory separator", template = .0.quote())]
|
||||||
PrefixContainsDirSeparator(String),
|
PrefixContainsDirSeparator(String),
|
||||||
|
|
||||||
/// The template suffix contains a path separator (e.g. `"XXXa/b"`).
|
/// The template suffix contains a path separator (e.g. `"XXXa/b"`).
|
||||||
|
#[error("invalid suffix {suffix}, contains directory separator", suffix = .0.quote())]
|
||||||
SuffixContainsDirSeparator(String),
|
SuffixContainsDirSeparator(String),
|
||||||
|
|
||||||
|
#[error("invalid template, {template}; with --tmpdir, it may not be absolute", template = .0.quote())]
|
||||||
InvalidTemplate(String),
|
InvalidTemplate(String),
|
||||||
|
|
||||||
|
#[error("too many templates")]
|
||||||
TooManyTemplates,
|
TooManyTemplates,
|
||||||
|
|
||||||
/// When a specified temporary directory could not be found.
|
/// When a specified temporary directory could not be found.
|
||||||
|
#[error("failed to create {template_type} via template {template}: No such file or directory",
|
||||||
|
template_type = .0,
|
||||||
|
template = .1.quote())]
|
||||||
NotFound(String, String),
|
NotFound(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,47 +83,6 @@ impl UError for MkTempError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for MkTempError {}
|
|
||||||
|
|
||||||
impl Display for MkTempError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
use MkTempError::*;
|
|
||||||
match self {
|
|
||||||
PersistError(p) => write!(f, "could not persist file {}", p.quote()),
|
|
||||||
MustEndInX(s) => write!(f, "with --suffix, template {} must end in X", s.quote()),
|
|
||||||
TooFewXs(s) => write!(f, "too few X's in template {}", s.quote()),
|
|
||||||
PrefixContainsDirSeparator(s) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"invalid template, {}, contains directory separator",
|
|
||||||
s.quote()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SuffixContainsDirSeparator(s) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"invalid suffix {}, contains directory separator",
|
|
||||||
s.quote()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
InvalidTemplate(s) => write!(
|
|
||||||
f,
|
|
||||||
"invalid template, {}; with --tmpdir, it may not be absolute",
|
|
||||||
s.quote()
|
|
||||||
),
|
|
||||||
TooManyTemplates => {
|
|
||||||
write!(f, "too many templates")
|
|
||||||
}
|
|
||||||
NotFound(template_type, s) => write!(
|
|
||||||
f,
|
|
||||||
"failed to create {} via template {}: No such file or directory",
|
|
||||||
template_type,
|
|
||||||
s.quote()
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Options parsed from the command-line.
|
/// Options parsed from the command-line.
|
||||||
///
|
///
|
||||||
/// This provides a layer of indirection between the application logic
|
/// This provides a layer of indirection between the application logic
|
||||||
|
|
|
@ -20,6 +20,7 @@ path = "src/nohup.rs"
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
uucore = { workspace = true, features = ["fs"] }
|
uucore = { workspace = true, features = ["fs"] }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nohup"
|
name = "nohup"
|
||||||
|
|
|
@ -10,11 +10,11 @@ use libc::{c_char, dup2, execvp, signal};
|
||||||
use libc::{SIGHUP, SIG_IGN};
|
use libc::{SIGHUP, SIG_IGN};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{Error, IsTerminal};
|
use std::io::{Error, IsTerminal};
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use thiserror::Error;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{set_exit_code, UClapError, UError, UResult};
|
use uucore::error::{set_exit_code, UClapError, UError, UResult};
|
||||||
use uucore::{format_usage, help_about, help_section, help_usage, show_error};
|
use uucore::{format_usage, help_about, help_section, help_usage, show_error};
|
||||||
|
@ -33,15 +33,24 @@ mod options {
|
||||||
pub const CMD: &str = "cmd";
|
pub const CMD: &str = "cmd";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
enum NohupError {
|
enum NohupError {
|
||||||
|
#[error("Cannot detach from console")]
|
||||||
CannotDetach,
|
CannotDetach,
|
||||||
CannotReplace(&'static str, std::io::Error),
|
|
||||||
OpenFailed(i32, std::io::Error),
|
|
||||||
OpenFailed2(i32, std::io::Error, String, std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for NohupError {}
|
#[error("Cannot replace {name}: {err}", name = .0, err = .1)]
|
||||||
|
CannotReplace(&'static str, #[source] Error),
|
||||||
|
|
||||||
|
#[error("failed to open {path}: {err}", path = NOHUP_OUT.quote(), err = .1)]
|
||||||
|
OpenFailed(i32, #[source] Error),
|
||||||
|
|
||||||
|
#[error("failed to open {first_path}: {first_err}\nfailed to open {second_path}: {second_err}",
|
||||||
|
first_path = NOHUP_OUT.quote(),
|
||||||
|
first_err = .1,
|
||||||
|
second_path = .2.quote(),
|
||||||
|
second_err = .3)]
|
||||||
|
OpenFailed2(i32, #[source] Error, String, Error),
|
||||||
|
}
|
||||||
|
|
||||||
impl UError for NohupError {
|
impl UError for NohupError {
|
||||||
fn code(&self) -> i32 {
|
fn code(&self) -> i32 {
|
||||||
|
@ -52,26 +61,6 @@ impl UError for NohupError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for NohupError {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::CannotDetach => write!(f, "Cannot detach from console"),
|
|
||||||
Self::CannotReplace(s, e) => write!(f, "Cannot replace {s}: {e}"),
|
|
||||||
Self::OpenFailed(_, e) => {
|
|
||||||
write!(f, "failed to open {}: {}", NOHUP_OUT.quote(), e)
|
|
||||||
}
|
|
||||||
Self::OpenFailed2(_, e1, s, e2) => write!(
|
|
||||||
f,
|
|
||||||
"failed to open {}: {}\nfailed to open {}: {}",
|
|
||||||
NOHUP_OUT.quote(),
|
|
||||||
e1,
|
|
||||||
s.quote(),
|
|
||||||
e2
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
||||||
|
|
|
@ -18,6 +18,7 @@ path = "src/tsort.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
uucore = { workspace = true }
|
uucore = { workspace = true }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
//spell-checker:ignore TAOCP indegree
|
//spell-checker:ignore TAOCP indegree
|
||||||
use clap::{crate_version, Arg, Command};
|
use clap::{crate_version, Arg, Command};
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::fmt::Display;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use thiserror::Error;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{UError, UResult};
|
use uucore::error::{UError, UResult};
|
||||||
use uucore::{format_usage, help_about, help_usage, show};
|
use uucore::{format_usage, help_about, help_usage, show};
|
||||||
|
@ -18,43 +18,30 @@ mod options {
|
||||||
pub const FILE: &str = "file";
|
pub const FILE: &str = "file";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Error)]
|
||||||
enum TsortError {
|
enum TsortError {
|
||||||
/// The input file is actually a directory.
|
/// The input file is actually a directory.
|
||||||
|
#[error("{0}: read error: Is a directory")]
|
||||||
IsDir(String),
|
IsDir(String),
|
||||||
|
|
||||||
/// The number of tokens in the input data is odd.
|
/// The number of tokens in the input data is odd.
|
||||||
///
|
///
|
||||||
/// The list of edges must be even because each edge has two
|
/// The list of edges must be even because each edge has two
|
||||||
/// components: a source node and a target node.
|
/// components: a source node and a target node.
|
||||||
|
#[error("{input}: input contains an odd number of tokens", input = .0.maybe_quote())]
|
||||||
NumTokensOdd(String),
|
NumTokensOdd(String),
|
||||||
|
|
||||||
/// The graph contains a cycle.
|
/// The graph contains a cycle.
|
||||||
|
#[error("{0}: input contains a loop:")]
|
||||||
Loop(String),
|
Loop(String),
|
||||||
|
|
||||||
/// A particular node in a cycle. (This is mainly used for printing.)
|
/// A particular node in a cycle. (This is mainly used for printing.)
|
||||||
|
#[error("{0}")]
|
||||||
LoopNode(String),
|
LoopNode(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for TsortError {}
|
|
||||||
|
|
||||||
impl UError for TsortError {}
|
impl UError for TsortError {}
|
||||||
|
|
||||||
impl Display for TsortError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::IsDir(d) => write!(f, "{d}: read error: Is a directory"),
|
|
||||||
Self::NumTokensOdd(i) => write!(
|
|
||||||
f,
|
|
||||||
"{}: input contains an odd number of tokens",
|
|
||||||
i.maybe_quote()
|
|
||||||
),
|
|
||||||
Self::Loop(i) => write!(f, "{i}: input contains a loop:"),
|
|
||||||
Self::LoopNode(v) => write!(f, "{v}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let matches = uu_app().try_get_matches_from(args)?;
|
let matches = uu_app().try_get_matches_from(args)?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue