use thiserror::Error;
use crate::exit;
#[derive(Debug, Error)]
pub enum AkmError {
#[error("{0}")]
BadInput(String),
#[error("{0}")]
NotFound(String),
#[error("{0}")]
KeychainUnavailable(String),
#[error("{0}")]
Internal(#[from] anyhow::Error),
}
impl AkmError {
pub fn exit_code(&self) -> u8 {
match self {
AkmError::BadInput(_) => exit::BAD_INPUT,
AkmError::NotFound(_) => exit::NOT_FOUND,
AkmError::Internal(_) | AkmError::KeychainUnavailable(_) => exit::TRANSIENT,
}
}
pub fn suggestion(&self) -> &'static str {
match self {
Self::BadInput(_) => "Use `akm <command> --help` or `akm agent-info --command <command>` for accepted arguments.",
Self::NotFound(_) => "Use `akm list` to find the stored name, or supply the value to `akm add NAME` through stdin.",
Self::KeychainUnavailable(_) => "Open Keychain Access and check that your existing login Keychain is available and unlocked. Keep HOME set to your macOS account home; do not reset the Keychain. After upgrading from an unsigned AKM, use `akm migrate --from /path/to/old/akm`.",
Self::Internal(_) => "Check the named resource, executable, or macOS Keychain access. Check the operation outcome before retrying a write.",
}
}
pub fn code_str(&self) -> &'static str {
match self {
AkmError::BadInput(_) => "bad_input",
AkmError::NotFound(_) => "not_found",
AkmError::KeychainUnavailable(_) => "keychain_unavailable",
AkmError::Internal(_) => "internal_error",
}
}
}
pub type Result<T> = std::result::Result<T, AkmError>;
impl From<std::io::Error> for AkmError {
fn from(e: std::io::Error) -> Self {
AkmError::Internal(anyhow::Error::from(e))
}
}