use thiserror::Error;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[error("Generic error: {message}{}", source.as_ref().map(|e| format!(": {e}")).unwrap_or_default())]
Generic {
message: String,
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
},
#[error("I/O error: {message}: {source}")]
Io {
message: String,
#[source]
source: std::io::Error,
},
#[error("Task join error: {message}: {source}")]
Join {
message: String,
#[source]
source: tokio::task::JoinError,
},
#[error("Image pull error for '{image_ref}': {message}{}", source.as_ref().map(|e| format!(": {}", e)).unwrap_or_default())]
ImagePull {
image_ref: String,
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
},
#[error("Image configuration error: {message}{}", source.as_ref().map(|e| format!(": {}", e)).unwrap_or_default())]
ImageConfig {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
},
#[error("OCI archive build error: {message}{}", source.as_ref().map(|e| format!(": {}", e)).unwrap_or_default())]
OciArchive {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
},
#[error("Cache error: {message}{}", source.as_ref().map(|e| format!(": {}", e)).unwrap_or_default())]
Cache {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
},
#[error("Invalid path specified: {message}")]
InvalidPath { message: String },
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
impl Error {
pub fn is_manifest_not_found(&self) -> bool {
match self {
Error::ImagePull { source, .. } => {
if let Some(source) = source {
if let Some(oci_err) =
source.downcast_ref::<oci_client::errors::OciDistributionError>()
{
return is_oci_manifest_not_found(oci_err);
}
}
false
}
_ => false,
}
}
}
fn is_oci_manifest_not_found(error: &oci_client::errors::OciDistributionError) -> bool {
match error {
oci_client::errors::OciDistributionError::RegistryError { envelope, .. } => {
envelope
.errors
.iter()
.any(|e| matches!(e.code, oci_client::errors::OciErrorCode::ManifestUnknown))
}
oci_client::errors::OciDistributionError::ImageManifestNotFoundError(_) => true,
_ => false,
}
}