diff --git a/crates/binstalk-fetchers/src/gh_crate_meta.rs b/crates/binstalk-fetchers/src/gh_crate_meta.rs index fdba68cc..d2d85f50 100644 --- a/crates/binstalk-fetchers/src/gh_crate_meta.rs +++ b/crates/binstalk-fetchers/src/gh_crate_meta.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, fmt, iter, path::Path, sync::Arc, time::Duration}; +use std::{borrow::Cow, fmt, iter, path::Path, sync::Arc}; use binstalk_git_repo_api::gh_api_client::{GhApiError, GhReleaseArtifact, GhReleaseArtifactUrl}; use compact_str::{CompactString, ToCompactString}; @@ -12,11 +12,9 @@ use url::Url; use crate::{ common::*, futures_resolver::FuturesResolver, Data, FetchError, InvalidPkgFmtError, RepoInfo, - SignaturePolicy, SignatureVerifier, TargetDataErased, + SignaturePolicy, SignatureVerifier, TargetDataErased, DEFAULT_GH_API_RETRY_DURATION, }; -static DEFAULT_GH_API_RETRY_DURATION: Duration = Duration::from_secs(1); - pub(crate) mod hosting; pub struct GhCrateMeta { diff --git a/crates/binstalk-fetchers/src/lib.rs b/crates/binstalk-fetchers/src/lib.rs index 4c1de54a..688bfbbb 100644 --- a/crates/binstalk-fetchers/src/lib.rs +++ b/crates/binstalk-fetchers/src/lib.rs @@ -1,12 +1,12 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] -use std::{path::Path, sync::Arc}; +use std::{path::Path, sync::Arc, time::Duration}; use binstalk_downloader::{download::DownloadError, remote::Error as RemoteError}; use binstalk_git_repo_api::gh_api_client::{GhApiError, GhRepo}; use binstalk_types::cargo_toml_binstall::SigningAlgorithm; use thiserror::Error as ThisError; -use tokio::sync::OnceCell; +use tokio::{sync::OnceCell, time::sleep}; pub use url::ParseError as UrlParseError; mod gh_crate_meta; @@ -27,6 +27,8 @@ mod futures_resolver; use gh_crate_meta::hosting::RepositoryHost; +static DEFAULT_GH_API_RETRY_DURATION: Duration = Duration::from_secs(1); + #[derive(Debug, ThisError)] #[error("Invalid pkg-url {pkg_url} for {crate_name}@{version} on {target}: {reason}")] pub struct InvalidPkgFmtError { @@ -204,11 +206,20 @@ impl Data { let mut is_private = false; if repository_host == RepositoryHost::GitHub && client.has_gh_token() { if let Some(gh_repo) = GhRepo::try_extract_from_url(&repo) { - let Some(gh_repo_info) = client.get_repo_info(&gh_repo).await? else { - return Err(GhApiError::NotFound.into()); - }; - - is_private = gh_repo_info.is_private(); + loop { + match client.get_repo_info(&gh_repo).await { + Ok(Some(gh_repo_info)) => { + is_private = gh_repo_info.is_private(); + break; + } + Ok(None) => return Err(GhApiError::NotFound.into()), + Err(GhApiError::RateLimit { retry_after }) => { + sleep(retry_after.unwrap_or(DEFAULT_GH_API_RETRY_DURATION)) + .await + } + Err(err) => return Err(err.into()), + } + } } }