use async_recursion::async_recursion;
use sha1::Digest;
use std::error::Error;
use tokio::fs;
use tokio::io::AsyncWriteExt;
#[async_recursion]
pub(crate) async fn try_download_file(
url: &str,
path: &std::path::Path,
hash: &str,
retries: u32,
) -> Result<(), Box<dyn Error>> {
let url = url.replace(std::path::MAIN_SEPARATOR_STR, "/");
let url = url.as_str();
let response = reqwest::get(url).await?;
let data = response.bytes().await?;
let mut file = fs::File::create(path).await?;
file.write_all(&data).await?;
if hash.len() != 40 {
return Ok(());
}
let downloaded_hash = format!("{:x}", sha1::Sha1::digest(&fs::read(path).await?));
if downloaded_hash != hash {
if retries > 0 {
fs::remove_file(path).await?;
try_download_file(url, path, hash, retries - 1).await?;
} else {
return Err("Hash mismatch".into());
}
}
Ok(())
}
pub(crate) fn get_os() -> String {
match std::env::consts::OS {
"windows" => "windows".to_string(),
"macos" => "osx".to_string(),
"linux" => "linux".to_string(),
_ => std::env::consts::OS.to_string(),
}
}