use std::path::PathBuf; use super::{Package, Repository, arch::Architecture}; pub struct MirrorRepository { pub inner: Repository, } impl MirrorRepository { pub fn new(repo: &str) -> Self { std::fs::create_dir_all(format!("./data/{repo}")).unwrap(); Self { inner: Repository::new(repo).unwrap(), } } pub async fn download_file( &self, url: &str, file_path: PathBuf, mirrorlist: &[String], arch: Architecture, ) { log::info!("Downloading {url} to {}", file_path.to_str().unwrap()); for mirror in mirrorlist { let mirror = mirror .replace("$repo", &self.inner.name) .replace("$arch", &arch.to_string()); let url = format!("{mirror}/{url}"); log::info!("Trying mirror {url}"); let client = reqwest::Client::new(); if let Ok(resp) = client.get(url).send().await { if resp.status().is_success() { let data = resp.bytes().await.unwrap().to_vec(); let parent = file_path.parent().unwrap(); std::fs::create_dir_all(parent).unwrap(); std::fs::write(file_path, data).unwrap(); return; } else { log::warn!("Mirror {mirror} failed [{}]", resp.status().as_u16()); } } } } /// Get the `.db.tar.gz` content for the repository of `arch` pub async fn db_content(&self, arch: Architecture, mirrorlist: &[String]) -> Option> { if let Some(content) = self.inner.db_content(arch.clone()) { return Some(content); } self.download_file( &format!("{}.db.tar.gz", self.inner.name), self.inner .base_path(arch.clone()) .join(format!("{}.db.tar.gz", self.inner.name)), mirrorlist, arch.clone(), ) .await; self.inner.db_content(arch) } /// Get the `.db.tar.gz.sig` content for the repository of `arch` pub async fn sig_content(&self, arch: Architecture, mirrorlist: &[String]) -> Option> { if let Some(content) = self.inner.sig_content(arch.clone()) { return Some(content); } self.download_file( &format!("{}.db.tar.gz.sig", self.inner.name), self.inner .base_path(arch.clone()) .join(format!("{}.db.tar.gz.sig", self.inner.name)), mirrorlist, arch.clone(), ) .await; self.inner.sig_content(arch) } pub async fn get_pkg(&self, pkg_name: &str, mirrorlist: &[String]) -> Option { if let Some(pkg) = self.inner.get_pkg(pkg_name) { return Some(pkg); } // PKG let (name, _, _, arch) = Package::extract_pkg_name(pkg_name).unwrap(); self.download_file( pkg_name, self.inner .base_path(arch.clone()) .join(&name) .join(pkg_name), mirrorlist, arch.clone(), ) .await; // SIG self.download_file( &format!("{pkg_name}.sig"), self.inner .base_path(arch.clone()) .join(&name) .join(format!("{pkg_name}.sig")), mirrorlist, arch.clone(), ) .await; self.inner.get_pkg(pkg_name) } }