Map a non-2xx response to an `anyhow::Error`, attaching a typed [`RemoteGitConflict`] when the server returned a recoverable code under 409 or 422. Synchronous and takes the pre-fetched response body so it can be shared between callers that hold a `reqwest::Response` and callers that have already streamed the body into a `Vec ` (for size-capped paths).
(op: &'static str, status: StatusCode, body: &str)
| 739 | /// between callers that hold a `reqwest::Response` and callers that have |
| 740 | /// already streamed the body into a `Vec<u8>` (for size-capped paths). |
| 741 | fn map_error_response(op: &'static str, status: StatusCode, body: &str) -> anyhow::Error { |
| 742 | let parsed: Option<RemoteErrorBody> = serde_json::from_str(body).ok(); |
| 743 | |
| 744 | let (code, message) = match parsed { |
| 745 | Some(b) => (b.error.code, b.error.message), |
| 746 | None => (format!("HTTP_{}", status.as_u16()), body.to_string()), |
| 747 | }; |
| 748 | |
| 749 | let status_u16 = status.as_u16(); |
| 750 | if status_u16 == 409 || status_u16 == 422 { |
| 751 | return anyhow::Error::new(RemoteGitConflict { code, message }); |
| 752 | } |
| 753 | |
| 754 | match status_u16 { |
| 755 | 400 => anyhow!("remote git '{}' bad request: {}: {}", op, code, message), |
| 756 | 401 | 403 => anyhow!("remote git '{}' auth failed: {}: {}", op, code, message), |
| 757 | 404 => anyhow!("remote git '{}' not found: {}: {}", op, code, message), |
| 758 | 500..=599 => anyhow!( |
| 759 | "remote git '{}' server error ({}): {}: {}", |
| 760 | op, |
| 761 | status_u16, |
| 762 | code, |
| 763 | message |
| 764 | ), |
| 765 | _ => anyhow!( |
| 766 | "remote git '{}' unexpected status {}: {}: {}", |
| 767 | op, |
| 768 | status_u16, |
| 769 | code, |
| 770 | message |
| 771 | ), |
| 772 | } |
| 773 | } |
| 774 | |
| 775 | #[derive(Deserialize)] |
| 776 | struct RemoteErrorBody { |
no outgoing calls
no test coverage detected