/ src / error.rs
error.rs
  1  use std::process::ExitStatus;
  2  
  3  use axum::http;
  4  use axum::response::{IntoResponse, Response};
  5  
  6  /// Errors relating to the Git backend.
  7  #[derive(Debug, thiserror::Error)]
  8  pub enum GitError {
  9      /// The entity was not found.
 10      #[error("not found")]
 11      NotFound,
 12  
 13      /// I/O error.
 14      #[error("i/o error: {0}")]
 15      Io(#[from] std::io::Error),
 16  
 17      /// The service is not available.
 18      #[error("service '{0}' not available")]
 19      ServiceUnavailable(&'static str),
 20  
 21      /// Invalid identifier.
 22      #[error("invalid radicle identifier: {0}")]
 23      Id(#[from] radicle::identity::IdError),
 24  
 25      /// Storage error.
 26      #[error("storage: {0}")]
 27      Storage(#[from] radicle::storage::Error),
 28  
 29      /// Repository error.
 30      #[error("repository: {0}")]
 31      Repository(#[from] radicle::storage::RepositoryError),
 32  
 33      /// Git backend error.
 34      #[error("git-http-backend: exited with code {0}")]
 35      BackendExited(ExitStatus),
 36  
 37      /// Git backend error.
 38      #[error("git-http-backend: invalid header returned: {0:?}")]
 39      BackendHeader(String),
 40  
 41      /// HeaderName error.
 42      #[error(transparent)]
 43      InvalidHeaderName(#[from] axum::http::header::InvalidHeaderName),
 44  
 45      /// HeaderValue error.
 46      #[error(transparent)]
 47      InvalidHeaderValue(#[from] axum::http::header::InvalidHeaderValue),
 48  }
 49  
 50  impl GitError {
 51      pub fn status(&self) -> http::StatusCode {
 52          match self {
 53              GitError::ServiceUnavailable(_) => http::StatusCode::SERVICE_UNAVAILABLE,
 54              GitError::Id(_) => http::StatusCode::NOT_FOUND,
 55              GitError::NotFound => http::StatusCode::NOT_FOUND,
 56              _ => http::StatusCode::INTERNAL_SERVER_ERROR,
 57          }
 58      }
 59  }
 60  
 61  impl IntoResponse for GitError {
 62      fn into_response(self) -> Response {
 63          tracing::error!("{}", self);
 64  
 65          self.status().into_response()
 66      }
 67  }
 68  
 69  /// Errors relating to the `/raw` route.
 70  #[derive(Debug, thiserror::Error)]
 71  pub enum RawError {
 72      /// Surf error.
 73      #[error(transparent)]
 74      Surf(#[from] radicle_surf::Error),
 75  
 76      /// Payload error.
 77      #[error(transparent)]
 78      ProjectPayload(#[from] radicle::identity::PayloadError),
 79  
 80      /// Io error.
 81      #[error(transparent)]
 82      Io(#[from] std::io::Error),
 83  
 84      /// Archive error.
 85      #[error("`git archive` exited with status {0}:\n{1}")]
 86      Archive(ExitStatus, String),
 87  
 88      /// Git error.
 89      #[error(transparent)]
 90      Git(#[from] radicle::git::raw::Error),
 91  
 92      /// Radicle Storage error.
 93      #[error(transparent)]
 94      Storage(#[from] radicle::storage::Error),
 95  
 96      /// Repository error.
 97      #[error(transparent)]
 98      Repository(#[from] radicle::storage::RepositoryError),
 99  
100      /// Http Headers error.
101      #[error(transparent)]
102      Headers(#[from] http::header::InvalidHeaderValue),
103  
104      /// Surf file error.
105      #[error(transparent)]
106      SurfFile(#[from] radicle_surf::fs::error::File),
107  
108      /// The entity was not found.
109      #[error("not found")]
110      NotFound,
111  }
112  
113  impl RawError {
114      pub fn status(&self) -> http::StatusCode {
115          match self {
116              RawError::SurfFile(_) | RawError::NotFound => http::StatusCode::NOT_FOUND,
117              _ => http::StatusCode::INTERNAL_SERVER_ERROR,
118          }
119      }
120  }
121  
122  impl IntoResponse for RawError {
123      fn into_response(self) -> Response {
124          tracing::error!("{}", self);
125  
126          self.status().into_response()
127      }
128  }