use std::fmt;
use std::path::PathBuf;
#[derive(Debug)]
pub enum Error {
Store(omgbase_store::Error),
Io {
what: String,
path: PathBuf,
source: std::io::Error,
},
Json(serde_json::Error),
RepoNotFound {
message: String,
candidates: Vec<String>,
},
AdapterSpawn { command: String, message: String },
AdapterExited { command: String },
AdapterHandshake { command: String, line: String },
AdapterError { method: String, message: String },
Unsupported(String),
WriterLockTimeout {
lock_path: PathBuf,
holder_pid: Option<i64>,
},
Other(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Store(e) => write!(f, "store: {e}"),
Error::Io { what, path, source } => write!(f, "{what} {}: {source}", path.display()),
Error::Json(e) => write!(f, "json: {e}"),
Error::RepoNotFound { message, .. } => f.write_str(message),
Error::AdapterSpawn { command, message } => {
write!(f, "sync adapter '{command}' failed to spawn: {message}")
}
Error::AdapterExited { command } => {
write!(f, "sync adapter '{command}' exited early")
}
Error::AdapterHandshake { command, line } => {
let shown: String = line.chars().take(120).collect();
write!(
f,
"sync adapter '{command}' sent an invalid handshake: {shown}"
)
}
Error::AdapterError { method, message } => {
write!(f, "sync adapter error ({method}): {message}")
}
Error::Unsupported(what) => write!(f, "the source does not support {what}"),
Error::WriterLockTimeout {
lock_path,
holder_pid,
} => write!(
f,
"could not acquire writer lock {} (held by pid {})",
lock_path.display(),
holder_pid.map_or_else(|| "?".to_owned(), |p| p.to_string())
),
Error::Other(msg) => f.write_str(msg),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Store(e) => Some(e),
Error::Io { source, .. } => Some(source),
Error::Json(e) => Some(e),
_ => None,
}
}
}
impl From<omgbase_store::Error> for Error {
fn from(e: omgbase_store::Error) -> Self {
Error::Store(e)
}
}
impl From<rusqlite::Error> for Error {
fn from(e: rusqlite::Error) -> Self {
Error::Store(omgbase_store::Error::Sqlite(e))
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::Json(e)
}
}
impl Error {
pub(crate) fn io(what: &str, path: impl Into<PathBuf>, source: std::io::Error) -> Self {
Error::Io {
what: what.to_owned(),
path: path.into(),
source,
}
}
}
pub type Result<T> = std::result::Result<T, Error>;