use octocrab::models::repos::Asset;
use std::path::PathBuf;
use tokio::io::AsyncWriteExt;
use super::ToolCache;
use crate::ToolCacheError;
impl ToolCache {
pub fn get_client(&self) -> &reqwest::Client {
self.client.get_or_init(reqwest::Client::new)
}
pub async fn download_asset(
&self,
asset: &Asset,
output: impl Into<PathBuf>,
) -> Result<(), ToolCacheError> {
let output = output.into();
log::debug!("Downloading asset to {:?}", output);
let url = asset.browser_download_url.clone();
let content_type = asset.content_type.clone();
log::debug!("Downloading asset from {:?}", url);
let mut file = tokio::fs::File::create(&output).await?;
let mut successful = false;
let mut counter = self.retry_count;
while counter > 0 {
log::debug!("Attempting download, retries left: {}", counter);
counter -= 1;
let mut resp = self
.get_client()
.get(url.clone())
.header(
http::header::ACCEPT,
http::header::HeaderValue::from_str(&content_type)?,
)
.header(
http::header::USER_AGENT,
http::header::HeaderValue::from_str("ghactions")?,
)
.send()
.await?;
if resp.status().is_server_error() {
log::warn!(
"Server error downloading asset: {:?}, retrying... {}",
resp.status(),
counter
);
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
continue;
}
while let Some(chunk) = resp.chunk().await? {
file.write_all(&chunk).await?;
}
log::debug!("Download complete");
successful = true;
break;
}
if !successful {
log::error!("Failed to download asset: {:?}", url);
return Err(ToolCacheError::DownloadError(format!(
"Failed to download asset: {:?}",
url
)));
}
Ok(())
}
}