use std::time::Duration;
#[derive(Debug, thiserror::Error)]
pub enum RegistryError {
#[error("pack not found: {name}@{version}")]
NotFound { name: String, version: String },
#[error("unauthorized: {message}")]
Unauthorized { message: String },
#[error("rate limited: retry after {retry_after:?}")]
RateLimited { retry_after: Option<Duration> },
#[error("pack revoked: {name}@{version} - {reason}")]
Revoked {
name: String,
version: String,
reason: String,
safe_version: Option<String>,
},
#[error("digest mismatch for {name}@{version}: expected {expected}, got {actual}")]
DigestMismatch {
name: String,
version: String,
expected: String,
actual: String,
},
#[error("signature verification failed: {reason}")]
SignatureInvalid { reason: String },
#[error("key not trusted: {key_id}")]
KeyNotTrusted { key_id: String },
#[error("pack is unsigned: {name}@{version}")]
Unsigned { name: String, version: String },
#[error("invalid pack reference: {reference} - {reason}")]
InvalidReference { reference: String, reason: String },
#[error("network error: {message}")]
Network { message: String },
#[error("cache error: {message}")]
Cache { message: String },
#[error("invalid response: {message}")]
InvalidResponse { message: String },
#[error("configuration error: {message}")]
Config { message: String },
#[error("lockfile error: {message}")]
Lockfile { message: String },
}
impl RegistryError {
pub fn exit_code(&self) -> i32 {
match self {
Self::NotFound { .. } => 1,
Self::Config { .. } => 1,
Self::InvalidReference { .. } => 1,
Self::Unauthorized { .. } => 2,
Self::Revoked { .. } => 3,
Self::DigestMismatch { .. } => 4,
Self::SignatureInvalid { .. } => 4,
Self::KeyNotTrusted { .. } => 4,
Self::Unsigned { .. } => 4,
Self::RateLimited { .. } => 5,
Self::Network { .. } => 5,
Self::Cache { .. } => 6,
Self::InvalidResponse { .. } => 6,
Self::Lockfile { .. } => 7,
}
}
pub fn is_retryable(&self) -> bool {
matches!(self, Self::RateLimited { .. } | Self::Network { .. })
}
}
impl From<reqwest::Error> for RegistryError {
fn from(err: reqwest::Error) -> Self {
Self::Network {
message: err.to_string(),
}
}
}
pub type RegistryResult<T> = Result<T, RegistryError>;