use std::path::PathBuf;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("storage error: {0}\n hint: check that the data directory is writable and not on a full disk")]
Storage(#[from] StorageError),
#[error("blob store error: {0}")]
Blob(#[from] BlobError),
#[error("config error: {0}")]
Config(#[from] ConfigError),
}
#[derive(Debug, Error)]
pub enum StorageError {
#[error("sqlite: {0}")]
Sqlite(#[from] rusqlite::Error),
#[error("cannot open database at {path:?}: {source}")]
Open {
path: PathBuf,
source: std::io::Error,
},
#[error("migration {version} failed: {source}")]
Migration {
version: i64,
source: rusqlite::Error,
},
#[error("session not resolvable: {0}")]
Resolve(#[from] ResolveError),
#[error("session {0} not found\n hint: run `hh list` to see recorded sessions")]
NotFound(String),
#[error("blob {0} referenced by event but missing from disk")]
MissingBlob(String),
#[error("the writer task is closed (it may have crashed; check stderr for prior errors)")]
WriterClosed,
#[error("the writer task panicked")]
WriterPanic,
}
#[derive(Debug, Error)]
pub enum ResolveError {
#[error("ambiguous session id `{prefix}` matches {count} sessions:\n{candidates}\n hint: use a longer prefix or the full id")]
Ambiguous {
prefix: String,
count: usize,
candidates: String,
},
#[error("no sessions recorded yet\n hint: run `hh run -- <command>` to record one")]
Empty,
}
#[derive(Debug, Error)]
pub enum BlobError {
#[error("blob io error at {path:?}: {source}")]
Io {
path: PathBuf,
source: std::io::Error,
},
#[error("zstd: {0}")]
Zstd(String),
#[error("blob hash mismatch: expected {expected}, got {actual}")]
HashMismatch {
expected: String,
actual: String,
},
}
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("cannot parse config file {path:?}: {source}")]
Parse {
path: PathBuf,
source: toml::de::Error,
},
#[error("invalid config value: {0}")]
Value(String),
#[error("cannot read config file {path:?}: {source}")]
Read {
path: PathBuf,
source: std::io::Error,
},
}
pub type Result<T> = std::result::Result<T, Error>;
impl From<rusqlite::Error> for Error {
fn from(e: rusqlite::Error) -> Self {
Self::Storage(StorageError::from(e))
}
}
impl From<ResolveError> for Error {
fn from(e: ResolveError) -> Self {
Self::Storage(StorageError::from(e))
}
}