mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-06-16 23:56:37 +00:00
Refactor: Return 'static
future
Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
f9008d7c93
commit
f90eea4235
2 changed files with 91 additions and 70 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::{sync::OnceLock, time::Duration};
|
||||
use std::{future::Future, sync::OnceLock, time::Duration};
|
||||
|
||||
use binstalk_downloader::remote::{self, header::HeaderMap, StatusCode, Url};
|
||||
use compact_str::CompactString;
|
||||
|
@ -61,28 +61,34 @@ fn check_http_status_and_header(status: StatusCode, headers: &HeaderMap) -> Resu
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) async fn issue_restful_api<T>(
|
||||
pub(super) fn issue_restful_api<T>(
|
||||
client: &remote::Client,
|
||||
path: String,
|
||||
auth_token: Option<&str>,
|
||||
) -> Result<T, GhApiError>
|
||||
) -> impl Future<Output = Result<T, GhApiError>> + Send + Sync + 'static
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let mut request_builder = client
|
||||
.get(Url::parse(&format!("https://api.github.com/{path}"))?)
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.header("X-GitHub-Api-Version", "2022-11-28");
|
||||
let res = Url::parse(&format!("https://api.github.com/{path}")).map(|url| {
|
||||
let mut request_builder = client
|
||||
.get(url)
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.header("X-GitHub-Api-Version", "2022-11-28");
|
||||
|
||||
if let Some(auth_token) = auth_token {
|
||||
request_builder = request_builder.bearer_auth(&auth_token);
|
||||
if let Some(auth_token) = auth_token {
|
||||
request_builder = request_builder.bearer_auth(&auth_token);
|
||||
}
|
||||
|
||||
request_builder.send(false)
|
||||
});
|
||||
|
||||
async move {
|
||||
let response = res?.await?;
|
||||
|
||||
check_http_status_and_header(response.status(), response.headers())?;
|
||||
|
||||
Ok(response.json().await?)
|
||||
}
|
||||
|
||||
let response = request_builder.send(false).await?;
|
||||
|
||||
check_http_status_and_header(response.status(), response.headers())?;
|
||||
|
||||
Ok(response.json().await?)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -107,35 +113,41 @@ fn get_graphql_endpoint() -> &'static Url {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) async fn issue_graphql_query<T>(
|
||||
pub(super) fn issue_graphql_query<T>(
|
||||
client: &remote::Client,
|
||||
query: String,
|
||||
auth_token: &str,
|
||||
) -> Result<T, GhApiError>
|
||||
) -> impl Future<Output = Result<T, GhApiError>> + Send + Sync + 'static
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let graphql_endpoint = get_graphql_endpoint();
|
||||
|
||||
let graphql_query = to_json_string(&GraphQLQuery { query }).map_err(remote::Error::from)?;
|
||||
let res = to_json_string(&GraphQLQuery { query })
|
||||
.map_err(remote::Error::from)
|
||||
.map(|graphql_query| {
|
||||
debug!("Sending graphql query to {graphql_endpoint}: '{graphql_query}'");
|
||||
|
||||
debug!("Sending graphql query to {graphql_endpoint}: '{graphql_query}'");
|
||||
let request_builder = client
|
||||
.post(graphql_endpoint.clone(), graphql_query)
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.bearer_auth(&auth_token);
|
||||
|
||||
let request_builder = client
|
||||
.post(graphql_endpoint.clone(), graphql_query)
|
||||
.header("Accept", "application/vnd.github+json")
|
||||
.bearer_auth(&auth_token);
|
||||
request_builder.send(false)
|
||||
});
|
||||
|
||||
let response = request_builder.send(false).await?;
|
||||
check_http_status_and_header(response.status(), response.headers())?;
|
||||
async move {
|
||||
let response = res?.await?;
|
||||
check_http_status_and_header(response.status(), response.headers())?;
|
||||
|
||||
let response: GraphQLResponse<T> = response.json().await?;
|
||||
let response: GraphQLResponse<T> = response.json().await?;
|
||||
|
||||
match response {
|
||||
GraphQLResponse::Data(data) => Ok(data),
|
||||
GraphQLResponse::Errors(errors) if errors.is_rate_limited() => {
|
||||
Err(GhApiError::RateLimit { retry_after: None })
|
||||
match response {
|
||||
GraphQLResponse::Data(data) => Ok(data),
|
||||
GraphQLResponse::Errors(errors) if errors.is_rate_limited() => {
|
||||
Err(GhApiError::RateLimit { retry_after: None })
|
||||
}
|
||||
GraphQLResponse::Errors(errors) => Err(errors.into()),
|
||||
}
|
||||
GraphQLResponse::Errors(errors) => Err(errors.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ use std::{
|
|||
borrow::Borrow,
|
||||
collections::HashSet,
|
||||
fmt,
|
||||
future::Future,
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
use binstalk_downloader::remote::{self};
|
||||
use compact_str::CompactString;
|
||||
use compact_str::{CompactString, ToCompactString};
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{
|
||||
|
@ -65,14 +66,14 @@ impl Artifacts {
|
|||
}
|
||||
}
|
||||
|
||||
async fn fetch_release_artifacts_restful_api(
|
||||
fn fetch_release_artifacts_restful_api(
|
||||
client: &remote::Client,
|
||||
GhRelease {
|
||||
repo: GhRepo { owner, repo },
|
||||
tag,
|
||||
}: &GhRelease,
|
||||
auth_token: Option<&str>,
|
||||
) -> Result<Artifacts, GhApiError> {
|
||||
) -> impl Future<Output = Result<Artifacts, GhApiError>> + Send + Sync + 'static {
|
||||
issue_restful_api(
|
||||
client,
|
||||
format!(
|
||||
|
@ -83,7 +84,6 @@ async fn fetch_release_artifacts_restful_api(
|
|||
),
|
||||
auth_token,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -132,56 +132,65 @@ impl fmt::Display for FilterCondition {
|
|||
}
|
||||
}
|
||||
|
||||
async fn fetch_release_artifacts_graphql_api(
|
||||
fn fetch_release_artifacts_graphql_api(
|
||||
client: &remote::Client,
|
||||
GhRelease {
|
||||
repo: GhRepo { owner, repo },
|
||||
tag,
|
||||
}: &GhRelease,
|
||||
auth_token: &str,
|
||||
) -> Result<Artifacts, GhApiError> {
|
||||
let mut artifacts = Artifacts::default();
|
||||
let mut cond = FilterCondition::Init;
|
||||
) -> impl Future<Output = Result<Artifacts, GhApiError>> + Send + Sync + 'static {
|
||||
let client = client.clone();
|
||||
let auth_token = auth_token.to_compact_string();
|
||||
|
||||
loop {
|
||||
let query = format!(
|
||||
r#"
|
||||
let base_query_prefix = format!(
|
||||
r#"
|
||||
query {{
|
||||
repository(owner:"{owner}",name:"{repo}") {{
|
||||
release(tagName:"{tag}") {{
|
||||
releaseAssets({cond}) {{
|
||||
nodes {{
|
||||
name
|
||||
url
|
||||
}}
|
||||
pageInfo {{ endCursor hasNextPage }}
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
}}"#
|
||||
);
|
||||
release(tagName:"{tag}") {{"#
|
||||
);
|
||||
|
||||
let data: GraphQLData = issue_graphql_query(client, query, auth_token).await?;
|
||||
let base_query_suffix = r#"
|
||||
nodes { name url }
|
||||
pageInfo { endCursor hasNextPage }
|
||||
}}}}"#
|
||||
.trim();
|
||||
|
||||
let assets = data
|
||||
.repository
|
||||
.and_then(|repository| repository.release)
|
||||
.map(|release| release.assets);
|
||||
async move {
|
||||
let mut artifacts = Artifacts::default();
|
||||
let mut cond = FilterCondition::Init;
|
||||
let base_query_prefix = base_query_prefix.trim();
|
||||
|
||||
if let Some(assets) = assets {
|
||||
artifacts.assets.extend(assets.nodes);
|
||||
loop {
|
||||
let query = format!(
|
||||
r#"
|
||||
{base_query_prefix}
|
||||
releaseAssets({cond}) {{
|
||||
{base_query_suffix}"#
|
||||
);
|
||||
|
||||
match assets.page_info {
|
||||
GraphQLPageInfo {
|
||||
end_cursor: Some(end_cursor),
|
||||
has_next_page: true,
|
||||
} => {
|
||||
cond = FilterCondition::After(end_cursor);
|
||||
let data: GraphQLData = issue_graphql_query(&client, query, &auth_token).await?;
|
||||
|
||||
let assets = data
|
||||
.repository
|
||||
.and_then(|repository| repository.release)
|
||||
.map(|release| release.assets);
|
||||
|
||||
if let Some(assets) = assets {
|
||||
artifacts.assets.extend(assets.nodes);
|
||||
|
||||
match assets.page_info {
|
||||
GraphQLPageInfo {
|
||||
end_cursor: Some(end_cursor),
|
||||
has_next_page: true,
|
||||
} => {
|
||||
cond = FilterCondition::After(end_cursor);
|
||||
}
|
||||
_ => break Ok(artifacts),
|
||||
}
|
||||
_ => break Ok(artifacts),
|
||||
} else {
|
||||
break Err(GhApiError::NotFound);
|
||||
}
|
||||
} else {
|
||||
break Err(GhApiError::NotFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue