2019-05-24 10:25:55 +02:00
|
|
|
use crate::common::*;
|
|
|
|
|
|
|
|
#[derive(Debug, Snafu)]
|
|
|
|
#[snafu(visibility(pub(crate)))]
|
|
|
|
pub(crate) enum Error {
|
2020-01-30 14:54:08 +01:00
|
|
|
#[snafu(display("Failed to parse announce URL: {}", source))]
|
|
|
|
AnnounceUrlParse { source: url::ParseError },
|
2020-02-01 21:30:35 +01:00
|
|
|
#[snafu(display("Failed to parse byte count `{}`: {}", text, source))]
|
|
|
|
ByteParse {
|
|
|
|
text: String,
|
|
|
|
source: ParseFloatError,
|
|
|
|
},
|
|
|
|
#[snafu(display("Failed to parse byte count `{}`, invalid suffix: `{}`", text, suffix))]
|
|
|
|
ByteSuffix { text: String, suffix: String },
|
2019-05-24 10:25:55 +02:00
|
|
|
#[snafu(display("{}", source))]
|
|
|
|
Clap { source: clap::Error },
|
2020-10-10 12:29:27 +02:00
|
|
|
#[snafu(display("Failed to invoke command `{}`: {}", command, source))]
|
2020-01-30 14:54:08 +01:00
|
|
|
CommandInvoke { command: String, source: io::Error },
|
|
|
|
#[snafu(display("Command `{}` returned bad exit status: {}", command, status))]
|
|
|
|
CommandStatus { command: String, status: ExitStatus },
|
2020-10-10 12:29:27 +02:00
|
|
|
#[snafu(display("Failed to get current directory: {}", source))]
|
|
|
|
CurrentDirectoryGet { source: io::Error },
|
2020-04-06 18:11:17 +02:00
|
|
|
#[snafu(display("Filename was not valid unicode: `{}`", filename.display()))]
|
2020-02-14 11:16:19 +01:00
|
|
|
FilenameDecode { filename: PathBuf },
|
2020-04-06 18:11:17 +02:00
|
|
|
#[snafu(display("Path had no file name: `{}`", path.display()))]
|
2020-01-30 14:54:08 +01:00
|
|
|
FilenameExtract { path: PathBuf },
|
2020-04-06 18:11:17 +02:00
|
|
|
#[snafu(display("Unknown file ordering: `{}`", text))]
|
2020-03-26 02:08:55 +01:00
|
|
|
FileOrderUnknown { text: String },
|
2019-05-24 10:25:55 +02:00
|
|
|
#[snafu(display("I/O error at `{}`: {}", path.display(), source))]
|
|
|
|
Filesystem { source: io::Error, path: PathBuf },
|
2020-04-16 05:17:40 +02:00
|
|
|
#[snafu(display("Error searching for files: {}", source))]
|
|
|
|
FileSearch { source: ignore::Error },
|
2020-02-06 06:47:12 +01:00
|
|
|
#[snafu(display("Invalid glob: {}", source))]
|
|
|
|
GlobParse { source: globset::Error },
|
2020-03-17 11:02:02 +01:00
|
|
|
#[snafu(display("Failed to serialize torrent info dictionary: {}", source))]
|
|
|
|
InfoSerialize { source: bendy::serde::Error },
|
2020-04-06 03:17:38 +02:00
|
|
|
#[snafu(display("Input target empty"))]
|
|
|
|
InputTargetEmpty,
|
2020-02-06 06:47:12 +01:00
|
|
|
#[snafu(display(
|
2020-03-06 07:51:00 +01:00
|
|
|
"Interal error, this may indicate a bug in intermodal: {}\n\
|
|
|
|
Consider filing an issue: https://github.com/casey/imdl/issues/new",
|
2020-02-06 06:47:12 +01:00
|
|
|
message,
|
|
|
|
))]
|
|
|
|
Internal { message: String },
|
2020-03-20 22:55:42 +01:00
|
|
|
#[snafu(display("Unknown lint: {}", text))]
|
|
|
|
LintUnknown { text: String },
|
2020-10-03 05:28:17 +02:00
|
|
|
#[snafu(display("Failed to parse magnet link `{}`: {}", text, source))]
|
|
|
|
MagnetLinkParse {
|
|
|
|
text: String,
|
|
|
|
source: MagnetLinkParseError,
|
|
|
|
},
|
2020-03-20 22:55:42 +01:00
|
|
|
#[snafu(display("Failed to deserialize torrent metainfo from {}: {}", input, source))]
|
|
|
|
MetainfoDeserialize {
|
|
|
|
source: bendy::serde::Error,
|
|
|
|
input: InputTarget,
|
|
|
|
},
|
|
|
|
#[snafu(display("Failed to serialize torrent metainfo: {}", source))]
|
|
|
|
MetainfoSerialize { source: bendy::serde::Error },
|
|
|
|
#[snafu(display("Failed to decode torrent metainfo from {}: {}", input, error))]
|
|
|
|
MetainfoDecode {
|
|
|
|
input: InputTarget,
|
|
|
|
error: bendy::decoding::Error,
|
|
|
|
},
|
|
|
|
#[snafu(display("Metainfo from {} failed to validate: {}", input, source))]
|
|
|
|
MetainfoValidate {
|
|
|
|
input: InputTarget,
|
|
|
|
source: MetainfoError,
|
|
|
|
},
|
|
|
|
#[snafu(display("Failed to invoke opener: {}", source))]
|
|
|
|
OpenerInvoke { source: io::Error },
|
|
|
|
#[snafu(display("Opener failed: {}", exit_status))]
|
|
|
|
OpenerExitStatus { exit_status: ExitStatus },
|
2020-03-17 11:02:02 +01:00
|
|
|
#[snafu(display("Output path already exists: `{}`", path.display()))]
|
|
|
|
OutputExists { path: PathBuf },
|
2020-04-06 03:17:38 +02:00
|
|
|
#[snafu(display("Output target empty"))]
|
|
|
|
OutputTargetEmpty,
|
2020-02-06 01:01:44 +01:00
|
|
|
#[snafu(display(
|
|
|
|
"Path `{}` contains non-normal component: {}",
|
|
|
|
path.display(),
|
|
|
|
component.display(),
|
|
|
|
))]
|
|
|
|
PathComponent { component: PathBuf, path: PathBuf },
|
|
|
|
#[snafu(display(
|
|
|
|
"Path `{}` contains non-unicode component: {}",
|
|
|
|
path.display(),
|
|
|
|
component.display(),
|
|
|
|
))]
|
|
|
|
PathDecode { path: PathBuf, component: PathBuf },
|
|
|
|
#[snafu(display(
|
|
|
|
"Path `{}` empty after stripping prefix `{}`",
|
|
|
|
path.display(),
|
|
|
|
prefix.display(),
|
|
|
|
))]
|
|
|
|
PathStripEmpty { path: PathBuf, prefix: PathBuf },
|
|
|
|
#[snafu(display(
|
|
|
|
"Failed to strip prefix `{}` from path `{}`: {}",
|
|
|
|
prefix.display(),
|
|
|
|
path.display(),
|
|
|
|
source
|
|
|
|
))]
|
|
|
|
PathStripPrefix {
|
|
|
|
path: PathBuf,
|
|
|
|
prefix: PathBuf,
|
|
|
|
source: path::StripPrefixError,
|
|
|
|
},
|
2020-02-01 21:30:35 +01:00
|
|
|
#[snafu(display(
|
|
|
|
"Piece length `{}` too large. The maximum supported piece length is {}.",
|
|
|
|
bytes,
|
|
|
|
Bytes(u32::max_value().into())
|
|
|
|
))]
|
2020-02-14 09:12:49 +01:00
|
|
|
PieceLengthTooLarge {
|
|
|
|
bytes: Bytes,
|
|
|
|
source: TryFromIntError,
|
|
|
|
},
|
2020-02-03 13:39:48 +01:00
|
|
|
#[snafu(display("Piece length `{}` is not an even power of two", bytes))]
|
|
|
|
PieceLengthUneven { bytes: Bytes },
|
|
|
|
#[snafu(display("Piece length must be at least 16 KiB"))]
|
|
|
|
PieceLengthSmall,
|
|
|
|
#[snafu(display("Piece length cannot be zero"))]
|
|
|
|
PieceLengthZero,
|
2020-03-17 11:02:02 +01:00
|
|
|
#[snafu(display("Private torrents must have tracker"))]
|
|
|
|
PrivateTrackerless,
|
2020-04-16 13:16:40 +02:00
|
|
|
#[snafu(display("Completion script for shell `{}` not UTF-8: {}", shell.name(), source))]
|
|
|
|
ShellDecode { shell: Shell, source: FromUtf8Error },
|
2020-01-14 09:52:27 +01:00
|
|
|
#[snafu(display("Failed to write to standard error: {}", source))]
|
2020-01-05 03:58:42 +01:00
|
|
|
Stderr { source: io::Error },
|
2020-03-18 10:48:57 +01:00
|
|
|
#[snafu(display("Failed to read from standard input: {}", source))]
|
|
|
|
Stdin { source: io::Error },
|
2020-01-14 09:52:27 +01:00
|
|
|
#[snafu(display("Failed to write to standard output: {}", source))]
|
|
|
|
Stdout { source: io::Error },
|
2020-02-06 03:32:09 +01:00
|
|
|
#[snafu(display(
|
2020-03-06 07:51:00 +01:00
|
|
|
"Attempted to create torrent from symlink `{}`. To override, pass the \
|
|
|
|
`--follow-symlinks` flag.",
|
2020-02-06 03:32:09 +01:00
|
|
|
root.display()
|
|
|
|
))]
|
|
|
|
SymlinkRoot { root: PathBuf },
|
2019-05-24 10:25:55 +02:00
|
|
|
#[snafu(display("Failed to retrieve system time: {}", source))]
|
|
|
|
SystemTime { source: SystemTimeError },
|
|
|
|
#[snafu(display(
|
|
|
|
"Feature `{}` cannot be used without passing the `--unstable` flag",
|
|
|
|
feature
|
|
|
|
))]
|
|
|
|
Unstable { feature: &'static str },
|
2020-03-15 11:22:33 +01:00
|
|
|
#[snafu(display("Torrent verification failed."))]
|
2020-03-16 06:41:47 +01:00
|
|
|
Verify,
|
2020-09-19 04:57:46 +02:00
|
|
|
#[snafu(display("Failed to serialize JSON: {}", source))]
|
|
|
|
JsonSerialize { source: serde_json::Error },
|
2020-02-03 13:39:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Error {
|
|
|
|
pub(crate) fn lint(&self) -> Option<Lint> {
|
|
|
|
match self {
|
|
|
|
Self::PieceLengthUneven { .. } => Some(Lint::UnevenPieceLength),
|
|
|
|
Self::PieceLengthSmall { .. } => Some(Lint::SmallPieceLength),
|
2020-03-17 11:02:02 +01:00
|
|
|
Self::PrivateTrackerless => Some(Lint::PrivateTrackerless),
|
2020-02-03 13:39:48 +01:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2020-02-06 06:47:12 +01:00
|
|
|
|
|
|
|
pub(crate) fn internal(message: impl Into<String>) -> Error {
|
2020-03-15 11:22:33 +01:00
|
|
|
Self::Internal {
|
2020-02-06 06:47:12 +01:00
|
|
|
message: message.into(),
|
|
|
|
}
|
|
|
|
}
|
2019-05-24 10:25:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<clap::Error> for Error {
|
2020-01-05 03:58:42 +01:00
|
|
|
fn from(source: clap::Error) -> Self {
|
|
|
|
Self::Clap { source }
|
2019-05-24 10:25:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-06 06:47:12 +01:00
|
|
|
impl From<globset::Error> for Error {
|
|
|
|
fn from(source: globset::Error) -> Self {
|
|
|
|
Self::GlobParse { source }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 10:25:55 +02:00
|
|
|
impl From<SystemTimeError> for Error {
|
2020-01-05 03:58:42 +01:00
|
|
|
fn from(source: SystemTimeError) -> Self {
|
|
|
|
Self::SystemTime { source }
|
2019-05-24 10:25:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 05:17:40 +02:00
|
|
|
impl From<ignore::Error> for Error {
|
|
|
|
fn from(ignore_error: ignore::Error) -> Self {
|
|
|
|
Self::FileSearch {
|
|
|
|
source: ignore_error,
|
2019-05-24 10:25:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|