use std::path::PathBuf;
use std::time::Duration;
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ExitCode {
Ok = 0,
Failure = 1,
MissingDependency = 2,
UserCancelled = 3,
ConfirmationMismatch = 4,
InvalidArgument = 5,
}
impl From<ExitCode> for u8 {
fn from(e: ExitCode) -> Self {
e as u8
}
}
#[derive(Debug, Error)]
pub enum Error {
#[error("command `{cmd}` exited with status {status}: {stderr}")]
CommandFailed {
cmd: String,
status: i32,
stderr: String,
#[source]
io: Option<std::io::Error>,
},
#[error("command `{cmd}` timed out after {timeout:?}")]
CommandTimedOut { cmd: String, timeout: Duration },
#[error("missing dependency `{binary}`: {detail}")]
MissingDependency {
binary: String,
detail: String,
hint: Option<String>,
#[source]
io: Option<std::io::Error>,
},
#[error("config error: {0}")]
Config(#[from] ConfigError),
#[error("no matching NTFS volume for `{pattern}`")]
NoMatch { pattern: String },
#[error("confirmation mismatch: expected `{expected}`, got `{actual}`")]
ConfirmationMismatch { expected: String, actual: String },
#[error("user cancelled")]
Cancelled,
#[error("invalid argument: {0}")]
InvalidArgument(String),
#[error("i/o error: {0}")]
Io(#[from] std::io::Error),
#[error("serialization error: {0}")]
Serde(String),
}
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("failed to read config at {path}: {reason}")]
Read { path: PathBuf, reason: String },
#[error("failed to write config to {path}: {reason}")]
Write { path: PathBuf, reason: String },
#[error("config parse error at {path}: {reason}")]
Parse { path: PathBuf, reason: String },
}
impl From<ConfigError> for std::io::Error {
fn from(e: ConfigError) -> Self {
std::io::Error::other(e.to_string())
}
}
pub type Result<T> = std::result::Result<T, Error>;