1use axum::{
2 Json,
3 http::StatusCode,
4 response::{IntoResponse, Response},
5};
6use serde_json::json;
7use std::fmt;
8
9#[derive(Debug)]
10pub enum AppError {
11 BadRequest(String),
12 NotFound(String),
13 Forbidden(String),
14 Conflict(String),
15 Internal(String),
16}
17
18impl IntoResponse for AppError {
19 fn into_response(self) -> Response {
20 let (status, message) = match self {
21 AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
22 AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
23 AppError::Forbidden(msg) => (StatusCode::FORBIDDEN, msg),
24 AppError::Conflict(msg) => (StatusCode::CONFLICT, msg),
25 AppError::Internal(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg),
26 };
27 let body = Json(json!({ "error": message }));
28 (status, body).into_response()
29 }
30}
31
32impl From<git2::Error> for AppError {
34 fn from(e: git2::Error) -> Self {
35 let msg = e.message().to_string();
36 match e.class() {
37 git2::ErrorClass::Invalid => AppError::BadRequest(msg),
38 git2::ErrorClass::Reference => AppError::NotFound(msg), git2::ErrorClass::Callback => AppError::Forbidden(msg), git2::ErrorClass::Merge => AppError::Conflict(msg), _ => AppError::Internal(format!("Git operation failed: {}", msg)),
42 }
43 }
44}
45
46impl fmt::Display for AppError {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 match self {
49 AppError::BadRequest(msg) => write!(f, "Bad request: {}", msg),
50 AppError::NotFound(msg) => write!(f, "Not found: {}", msg),
51 AppError::Forbidden(msg) => write!(f, "Forbidden: {}", msg),
52 AppError::Conflict(msg) => write!(f, "Conflict: {}", msg),
53 AppError::Internal(msg) => write!(f, "Internal error: {}", msg),
54 }
55 }
56}
57
58pub type AppResult<T> = Result<T, AppError>;