use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
const MANIFEST: &str = include_str!("registry_manifest.yaml");
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CuratedRecipe {
#[serde(default)]
pub description: String,
pub url: String,
pub sha256: String,
#[serde(default)]
pub install_to: Option<String>,
#[serde(default)]
pub executable: bool,
#[serde(default)]
pub archive: Option<ArchiveSpec>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ArchiveSpec {
pub members: Vec<RecipeMember>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct RecipeMember {
pub path_in_archive: String,
pub install_to: String,
#[serde(default)]
pub executable: bool,
}
#[derive(Debug, Deserialize)]
struct Entry {
#[serde(default)]
description: String,
platforms: BTreeMap<String, PlatformRaw>,
}
#[derive(Debug, Deserialize)]
struct PlatformRaw {
url: String,
sha256: String,
#[serde(default)]
install_to: Option<String>,
#[serde(default)]
executable: bool,
#[serde(default)]
archive: Option<ArchiveSpec>,
}
fn load() -> BTreeMap<String, Entry> {
serde_yaml::from_str(MANIFEST).expect("embedded registry_manifest.yaml is valid")
}
pub fn recipe(key: &str, platform: &str) -> Option<CuratedRecipe> {
let map = load();
let entry = map.get(key)?;
let p = entry.platforms.get(platform)?;
Some(CuratedRecipe {
description: entry.description.clone(),
url: p.url.clone(),
sha256: p.sha256.clone(),
install_to: p.install_to.clone(),
executable: p.executable,
archive: p.archive.clone(),
})
}
pub fn is_curated(key: &str) -> bool {
load().contains_key(key)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lightpanda_recipe_resolves_per_platform() {
let r = recipe("lightpanda", "aarch64-macos");
assert!(r.is_some(), "lightpanda/aarch64-macos should exist");
let r = r.unwrap();
assert!(!r.url.is_empty() && r.sha256.len() == 64);
assert!(
r.install_to
.as_ref()
.map_or(false, |p| p.starts_with("aura/"))
);
assert!(is_curated("lightpanda"));
assert!(!is_curated("totally-unknown-key"));
assert!(recipe("lightpanda", "sparc-solaris").is_none());
}
#[test]
fn obscura_recipe_is_an_archive_with_two_members() {
let r = recipe("obscura", "aarch64-macos").expect("obscura/aarch64-macos");
let a = r.archive.expect("obscura ships an archive");
assert_eq!(a.members.len(), 2, "obscura + obscura-worker");
assert!(a.members.iter().any(|m| m.install_to == "aura/obscura"));
assert!(
a.members
.iter()
.any(|m| m.install_to == "aura/obscura-worker")
);
}
}