use anyhow::Error;
use chrono::format::ParseErrorKind;
use directories::ProjectDirs;
use sha2::{Digest, Sha256};
use tokio::time::Instant;
use crate::registry::schema::registry::{Registry, root_as_registry};
use crate::registry::search::{LoadedRegistry, SearchEngine};
use std::fs;
use std::path::PathBuf;
impl SearchEngine {
fn get_tmp_path_for_ref(&self, reference: String) -> PathBuf {
let proj_dirs = ProjectDirs::from("dev", "mercurpkg", "mercur")
.expect("could not determine cache directory");
let mut hasher = Sha256::new();
hasher.update(reference.as_bytes());
let hash = hex::encode(hasher.finalize());
let mut path = proj_dirs.cache_dir().to_path_buf();
path.push("registries");
fs::create_dir_all(&path).unwrap();
path.push(format!("{hash}.mreg"));
path
}
pub(super) fn load_registry(&mut self, reference: String) -> Registry {
if self.registries.contains_key(&reference) {
return root_as_registry(&self.registries.get(&reference).unwrap().data).unwrap();
} else {
let tmp_path = self.get_tmp_path_for_ref(reference.clone());
if !tmp_path.exists() {
self.download_registry(reference.clone().as_str());
}
let data = std::fs::read(&tmp_path).unwrap();
self.registries.insert(
reference.clone(),
LoadedRegistry {
reference: reference.clone(),
data,
last_used: Instant::now(),
},
);
let loaded = self.registries.get(&reference).unwrap();
root_as_registry(&loaded.data).unwrap()
}
}
pub async fn download_registry(&self, reference: &str) -> anyhow::Result<Vec<u8>> {
let url = self.resolve_registry_url(reference)?;
let bytes = reqwest::get(url).await?.bytes().await?;
Ok(bytes.to_vec())
}
pub fn resolve_registry_url(&self, reference: &str) -> anyhow::Result<String> {
if let Some(rest) = reference.strip_prefix("github:") {
let mut rest = rest;
let mut branch = "main";
let s: Vec<&str> = rest.split("#").collect();
if (s.len() == 2) {
rest = s[0];
branch = s[1];
}
Ok(format!(
"https://raw.githubusercontent.com/{rest}/{branch}/mercur/registry.mreg"
))
} else if reference.starts_with("http://") || reference.starts_with("https://") {
Ok(reference.to_string())
} else {
Err(Error::msg(format!(
"can not parse reference '{}'",
reference
)))
}
}
}