Fix failure to send quickinstall report (#1224)

Fixed #1222 by fetching lists of supported targets from quickinstall
repository.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2023-07-21 15:41:09 +10:00 committed by GitHub
parent af9a574738
commit 306f761973
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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<Box<[CompactString]>> = 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<CompactString> = 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<bool>,
package: String,
package_url: Url,
@ -32,6 +63,20 @@ pub struct QuickInstall {
target_data: Arc<TargetData>,
}
impl QuickInstall {
async fn is_supported(&self) -> Result<bool, BinstallError> {
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<Self>) -> AutoAbortJoinHandle<Result<bool, BinstallError>> {
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();
});
}
}