diff --git a/crates/binstalk-fetchers/src/common.rs b/crates/binstalk-fetchers/src/common.rs index b3a491ae..10272f10 100644 --- a/crates/binstalk-fetchers/src/common.rs +++ b/crates/binstalk-fetchers/src/common.rs @@ -1,6 +1,11 @@ -use std::sync::{ - atomic::{AtomicBool, Ordering::Relaxed}, - Once, +#![allow(unused)] + +use std::{ + future::Future, + sync::{ + atomic::{AtomicBool, Ordering::Relaxed}, + Once, + }, }; pub(super) use binstalk_downloader::{ @@ -76,3 +81,33 @@ pub(super) async fn does_url_exist( Ok(Box::pin(client.remote_gettable(url.clone())).await?) } + +#[derive(Debug)] +pub(super) struct AutoAbortJoinHandle(JoinHandle); + +impl AutoAbortJoinHandle +where + T: Send + 'static, +{ + pub(super) fn spawn(future: F) -> Self + where + F: Future + Send + 'static, + { + Self(tokio::spawn(future)) + } +} + +impl Drop for AutoAbortJoinHandle { + fn drop(&mut self) { + self.0.abort(); + } +} + +impl AutoAbortJoinHandle> +where + E: Into, +{ + pub(super) async fn flattened_join(mut self) -> Result { + (&mut self.0).await?.map_err(Into::into) + } +} diff --git a/crates/binstalk-fetchers/src/lib.rs b/crates/binstalk-fetchers/src/lib.rs index 33e50944..f589e5fc 100644 --- a/crates/binstalk-fetchers/src/lib.rs +++ b/crates/binstalk-fetchers/src/lib.rs @@ -6,7 +6,7 @@ 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, time::sleep}; +use tokio::{sync::OnceCell, task::JoinError, time::sleep}; pub use url::ParseError as UrlParseError; mod gh_crate_meta; @@ -70,6 +70,9 @@ pub enum FetchError { #[error("Failed to verify signature")] InvalidSignature, + + #[error("Failed to wait for task: {0}")] + TaskJoinError(#[from] JoinError), } impl From for FetchError { diff --git a/crates/binstalk-fetchers/src/quickinstall.rs b/crates/binstalk-fetchers/src/quickinstall.rs index aa9b402a..a4625443 100644 --- a/crates/binstalk-fetchers/src/quickinstall.rs +++ b/crates/binstalk-fetchers/src/quickinstall.rs @@ -118,22 +118,35 @@ impl super::Fetcher for QuickInstall { return Ok(false); } - if self.signature_policy == SignaturePolicy::Require { + let check_signature_policy_task = (self.signature_policy == SignaturePolicy::Require) + .then(|| { + let client = self.client.clone(); + let gh_api_client = self.gh_api_client.clone(); + let signature_url = self.signature_url.clone(); + + AutoAbortJoinHandle::spawn(async move { + match does_url_exist(client, gh_api_client, &signature_url).await { + Ok(true) => Ok(()), + _ => Err(FetchError::MissingSignature), + } + }) + }); + + tokio::try_join!( + async { + if let Some(task) = check_signature_policy_task { + task.flattened_join().await + } else { + Ok(()) + } + }, does_url_exist( self.client.clone(), self.gh_api_client.clone(), - &self.signature_url, - ) - .await - .map_err(|_| FetchError::MissingSignature)?; - } - - does_url_exist( - self.client.clone(), - self.gh_api_client.clone(), - &self.package_url, + &self.package_url, + ), ) - .await + .map(|(_, res)| res) }) }