use git_lfs_api::{ApiError, ObjectError};
use git_lfs_pointer::OidParseError;
use git_lfs_store::StoreError;
#[derive(Debug, thiserror::Error)]
pub enum TransferError {
#[error("server error for object: {} ({})", .0.message, .0.code)]
ServerObject(ObjectError),
#[error("server returned no download action for object")]
NoDownloadAction,
#[error("transfer action returned status {status}")]
ActionStatus { status: u16 },
#[error("http error: {0}")]
Http(#[from] reqwest::Error),
#[error("local io error: {0}")]
Io(#[from] std::io::Error),
#[error("store error: {0}")]
Store(#[from] StoreError),
#[error("invalid oid from server: {0}")]
InvalidOid(#[from] OidParseError),
}
impl TransferError {
pub fn is_retryable(&self) -> bool {
match self {
TransferError::Http(e) => {
!e.is_decode() && !e.is_builder()
}
TransferError::ActionStatus { status } => {
matches!(status, 408 | 429 | 500..=599)
}
TransferError::Io(_) => true,
TransferError::ServerObject(_)
| TransferError::NoDownloadAction
| TransferError::Store(_)
| TransferError::InvalidOid(_) => false,
}
}
}
impl From<ApiError> for TransferError {
fn from(value: ApiError) -> Self {
match value {
ApiError::Transport(e) => TransferError::Http(e),
other => {
TransferError::Io(std::io::Error::other(other.to_string()))
}
}
}
}
#[derive(Debug, Default)]
pub struct Report {
pub succeeded: Vec<String>,
pub failed: Vec<(String, TransferError)>,
}
impl Report {
pub fn is_complete_success(&self) -> bool {
self.failed.is_empty()
}
}