Construct the response to listing the tree in gitea.

This commit is contained in:
Tom Alexander 2024-09-28 14:00:00 -04:00
parent 71f9e10600
commit 201709c360
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 57 additions and 11 deletions

25
src/gitea_client/error.rs Normal file
View File

@ -0,0 +1,25 @@
use std::error::Error;
#[derive(Debug, Clone)]
pub(crate) enum GiteaClientError {
Static(#[allow(dead_code)] &'static str),
String(#[allow(dead_code)] String),
NoTotalCountHeaderInResponse,
}
impl std::fmt::Display for GiteaClientError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
GiteaClientError::Static(s) => write!(f, "GiteaClientError: {}", s),
GiteaClientError::String(s) => write!(f, "GiteaClientError: {}", s),
GiteaClientError::NoTotalCountHeaderInResponse => {
write!(
f,
"GiteaClientError: No x-total-count header returned in gitea response.",
)
}
}
}
}
impl Error for GiteaClientError {}

View File

@ -1,5 +1,7 @@
use serde::Deserialize; use serde::Deserialize;
use tracing::debug;
use self::error::GiteaClientError;
pub(crate) mod error;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct GiteaClient { pub(crate) struct GiteaClient {
@ -25,6 +27,7 @@ impl GiteaClient {
) -> Result<Tree, Box<dyn std::error::Error>> { ) -> Result<Tree, Box<dyn std::error::Error>> {
let mut files = Vec::new(); let mut files = Vec::new();
let mut page: Option<u64> = None; let mut page: Option<u64> = None;
let mut num_responses: u64 = 0;
loop { loop {
let url = format!( let url = format!(
"{api_root}/v1/repos/{owner}/{repo}/git/trees/{commit}?recursive=true&per_page=10{page}", "{api_root}/v1/repos/{owner}/{repo}/git/trees/{commit}?recursive=true&per_page=10{page}",
@ -41,16 +44,28 @@ impl GiteaClient {
.send() .send()
.await?; .await?;
let response = response.error_for_status()?; let response = response.error_for_status()?;
let body = response.text().await?; let total_count = response
debug!("Response: {}", body); .headers()
let parsed_body: ResponseGetTree = serde_json::from_str(body.as_str())?; .get("x-total-count")
println!("Response: {:#?}", parsed_body); .ok_or(GiteaClientError::NoTotalCountHeaderInResponse)?
// TODO: Read response objects .to_str()?
.parse::<u64>()?;
if num_responses == 0 {
files.reserve(total_count as usize);
}
if !parsed_body.truncated { let body = response.text().await?;
let parsed_body: ResponseGetTree = serde_json::from_str(body.as_str())?;
num_responses += parsed_body.tree.len() as u64;
files.extend(parsed_body.tree.into_iter().map(|response_object| {
TreeFileReference::new(response_object.path, response_object.url)
}));
if num_responses >= total_count {
break; break;
} }
// TODO: Switch to using response headers instead of response body.
page = Some(parsed_body.page + 1); page = Some(parsed_body.page + 1);
} }
Ok(Tree::new(files)) Ok(Tree::new(files))
@ -85,7 +100,10 @@ pub(crate) struct Tree {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct TreeFileReference {} pub(crate) struct TreeFileReference {
path: String,
url: String,
}
impl Tree { impl Tree {
pub(crate) fn new(files: Vec<TreeFileReference>) -> Tree { pub(crate) fn new(files: Vec<TreeFileReference>) -> Tree {
@ -94,7 +112,10 @@ impl Tree {
} }
impl TreeFileReference { impl TreeFileReference {
pub(crate) fn new() -> TreeFileReference { pub(crate) fn new<P: Into<String>, U: Into<String>>(path: P, url: U) -> TreeFileReference {
TreeFileReference {} TreeFileReference {
path: path.into(),
url: url.into(),
}
} }
} }