From 306f7619731aec977d6370da8c0c8f32192fb77a Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Fri, 21 Jul 2023 15:41:09 +1000 Subject: [PATCH] Fix failure to send quickinstall report (#1224) Fixed #1222 by fetching lists of supported targets from quickinstall repository. Signed-off-by: Jiahao XU --- crates/binstalk/src/fetchers/quickinstall.rs | 104 ++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/crates/binstalk/src/fetchers/quickinstall.rs b/crates/binstalk/src/fetchers/quickinstall.rs index a6850f5f..273fd720 100644 --- a/crates/binstalk/src/fetchers/quickinstall.rs +++ b/crates/binstalk/src/fetchers/quickinstall.rs @@ -1,6 +1,7 @@ use std::{path::Path, sync::Arc}; use compact_str::CompactString; +use tokio::sync::OnceCell; use tracing::{debug, warn}; use url::Url; @@ -21,9 +22,39 @@ use super::{Data, TargetData}; const BASE_URL: &str = "https://github.com/cargo-bins/cargo-quickinstall/releases/download"; const STATS_URL: &str = "https://warehouse-clerk-tmp.vercel.app/api/crate"; +const QUICKINSTALL_SUPPORTED_TARGETS_URL: &str = + "https://raw.githubusercontent.com/cargo-bins/cargo-quickinstall/main/supported-targets"; + +async fn get_quickinstall_supported_targets( + client: &Client, +) -> Result<&'static [CompactString], BinstallError> { + static SUPPORTED_TARGETS: OnceCell> = OnceCell::const_new(); + + SUPPORTED_TARGETS + .get_or_try_init(|| async { + let bytes = client + .get(Url::parse(QUICKINSTALL_SUPPORTED_TARGETS_URL)?) + .send(true) + .await? + .bytes() + .await?; + + let mut v: Vec = String::from_utf8_lossy(&bytes) + .split_whitespace() + .map(CompactString::new) + .collect(); + v.sort_unstable(); + v.dedup(); + Ok(v.into()) + }) + .await + .map(Box::as_ref) +} + pub struct QuickInstall { client: Client, gh_api_client: GhApiClient, + is_supported_v: OnceCell, package: String, package_url: Url, @@ -32,6 +63,20 @@ pub struct QuickInstall { target_data: Arc, } +impl QuickInstall { + async fn is_supported(&self) -> Result { + self.is_supported_v + .get_or_try_init(|| async { + Ok(get_quickinstall_supported_targets(&self.client) + .await? + .binary_search(&CompactString::new(&self.target_data.target)) + .is_ok()) + }) + .await + .copied() + } +} + #[async_trait::async_trait] impl super::Fetcher for QuickInstall { fn new( @@ -49,6 +94,7 @@ impl super::Fetcher for QuickInstall { Arc::new(Self { client, gh_api_client, + is_supported_v: OnceCell::new(), package_url: Url::parse(&format!( "{BASE_URL}/{crate_name}-{version}/{package}.tar.gz", @@ -64,7 +110,7 @@ impl super::Fetcher for QuickInstall { fn find(self: Arc) -> AutoAbortJoinHandle> { AutoAbortJoinHandle::spawn(async move { - if is_universal_macos(&self.target_data.target) { + if !self.is_supported().await? { return Ok(false); } @@ -87,7 +133,7 @@ and universal2-apple-darwin. Quickinstall does not support these targets, it only supports targets supported by rust officially."#, ); - } else { + } else if self.is_supported_v.get().copied() != Some(false) { tokio::spawn(async move { if let Err(err) = self.report().await { warn!( @@ -141,6 +187,15 @@ by rust officially."#, impl QuickInstall { pub async fn report(&self) -> Result<(), BinstallError> { + if !self.is_supported().await? { + debug!( + "Not sending quickinstall report for {} since Quickinstall does not support these targets.", + self.target_data.target + ); + + return Ok(()); + } + let url = self.stats_url.clone(); debug!("Sending installation report to quickinstall ({url})"); @@ -149,3 +204,48 @@ impl QuickInstall { Ok(()) } } + +#[cfg(test)] +mod test { + use super::{get_quickinstall_supported_targets, Client, CompactString}; + use std::time::Duration; + + /// Mark this as an async fn so that you won't accidentally use it in + /// sync context. + async fn create_client() -> Client { + Client::new( + concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")), + None, + Duration::from_millis(10), + 1.try_into().unwrap(), + [], + ) + .unwrap() + } + + #[tokio::test] + async fn test_get_quickinstall_supported_targets() { + let supported_targets = get_quickinstall_supported_targets(&create_client().await) + .await + .unwrap(); + + [ + "x86_64-pc-windows-msvc", + "x86_64-apple-darwin", + "aarch64-apple-darwin", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", + "aarch64-pc-windows-msvc", + "armv7-unknown-linux-musleabihf", + "armv7-unknown-linux-gnueabihf", + ] + .into_iter() + .for_each(|known_supported_target| { + supported_targets + .binary_search(&CompactString::new(known_supported_target)) + .unwrap(); + }); + } +}