use thiserror::Error;
#[derive(Debug, Error)]
pub enum RemoteError {
#[error("Git clone failed for {url}: {message}")]
CloneFailed { url: String, message: String },
#[error("Invalid repository URL: {0}")]
InvalidUrl(String),
#[error("Repository not found: {0}")]
NotFound(String),
#[error("Authentication required for private repository: {0}")]
AuthRequired(String),
#[error("GitHub rate limit exceeded, retry after {reset_at}")]
RateLimitExceeded { reset_at: String },
#[error("Network error: {0}")]
Network(#[from] std::io::Error),
#[error("HTTP error {status}: {message}")]
Http { status: u16, message: String },
#[error("Failed to parse awesome-claude-code: {0}")]
ParseError(String),
#[error("Temporary directory error: {0}")]
TempDir(String),
#[error("Git command not found. Please install git.")]
GitNotFound,
#[error("Clone timeout exceeded for {url} (timeout: {timeout_secs}s)")]
CloneTimeout { url: String, timeout_secs: u64 },
#[error("Repository too large: {url} (size: {size_mb}MB, limit: {limit_mb}MB)")]
RepositoryTooLarge {
url: String,
size_mb: u64,
limit_mb: u64,
},
}
impl RemoteError {
pub fn is_retryable(&self) -> bool {
matches!(
self,
RemoteError::RateLimitExceeded { .. }
| RemoteError::Network(_)
| RemoteError::CloneTimeout { .. }
)
}
pub fn is_auth_error(&self) -> bool {
matches!(self, RemoteError::AuthRequired(_))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clone_failed_error() {
let err = RemoteError::CloneFailed {
url: "https://github.com/user/repo".to_string(),
message: "Connection refused".to_string(),
};
assert!(err.to_string().contains("github.com/user/repo"));
assert!(err.to_string().contains("Connection refused"));
}
#[test]
fn test_is_retryable() {
assert!(
RemoteError::RateLimitExceeded {
reset_at: "2026-01-25T12:00:00Z".to_string()
}
.is_retryable()
);
assert!(
RemoteError::CloneTimeout {
url: "https://github.com/user/repo".to_string(),
timeout_secs: 60
}
.is_retryable()
);
assert!(!RemoteError::InvalidUrl("bad".to_string()).is_retryable());
assert!(!RemoteError::NotFound("repo".to_string()).is_retryable());
}
#[test]
fn test_is_auth_error() {
assert!(
RemoteError::AuthRequired("https://github.com/private/repo".to_string())
.is_auth_error()
);
assert!(!RemoteError::NotFound("repo".to_string()).is_auth_error());
}
}