mur_common/deps/
registry.rs1use serde::{Deserialize, Serialize};
5use std::collections::BTreeMap;
6
7const MANIFEST: &str = include_str!("registry_manifest.yaml");
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct CuratedRecipe {
11 #[serde(default)]
12 pub description: String,
13 pub url: String,
14 pub sha256: String,
15 #[serde(default)]
17 pub install_to: Option<String>,
18 #[serde(default)]
19 pub executable: bool,
20 #[serde(default)]
22 pub archive: Option<ArchiveSpec>,
23}
24
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
26pub struct ArchiveSpec {
27 pub members: Vec<RecipeMember>,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
31pub struct RecipeMember {
32 pub path_in_archive: String,
33 pub install_to: String,
34 #[serde(default)]
35 pub executable: bool,
36}
37
38#[derive(Debug, Deserialize)]
39struct Entry {
40 #[serde(default)]
41 description: String,
42 platforms: BTreeMap<String, PlatformRaw>,
43}
44
45#[derive(Debug, Deserialize)]
46struct PlatformRaw {
47 url: String,
48 sha256: String,
49 #[serde(default)]
50 install_to: Option<String>,
51 #[serde(default)]
52 executable: bool,
53 #[serde(default)]
54 archive: Option<ArchiveSpec>,
55}
56
57fn load() -> BTreeMap<String, Entry> {
58 serde_yaml::from_str(MANIFEST).expect("embedded registry_manifest.yaml is valid")
59}
60
61pub fn recipe(key: &str, platform: &str) -> Option<CuratedRecipe> {
63 let map = load();
64 let entry = map.get(key)?;
65 let p = entry.platforms.get(platform)?;
66 Some(CuratedRecipe {
67 description: entry.description.clone(),
68 url: p.url.clone(),
69 sha256: p.sha256.clone(),
70 install_to: p.install_to.clone(),
71 executable: p.executable,
72 archive: p.archive.clone(),
73 })
74}
75
76pub fn is_curated(key: &str) -> bool {
78 load().contains_key(key)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn lightpanda_recipe_resolves_per_platform() {
87 let r = recipe("lightpanda", "aarch64-macos");
88 assert!(r.is_some(), "lightpanda/aarch64-macos should exist");
89 let r = r.unwrap();
90 assert!(!r.url.is_empty() && r.sha256.len() == 64);
91 assert!(
92 r.install_to
93 .as_ref()
94 .map_or(false, |p| p.starts_with("aura/"))
95 );
96 assert!(is_curated("lightpanda"));
97 assert!(!is_curated("totally-unknown-key"));
98 assert!(recipe("lightpanda", "sparc-solaris").is_none());
99 }
100
101 #[test]
102 fn obscura_recipe_is_an_archive_with_two_members() {
103 let r = recipe("obscura", "aarch64-macos").expect("obscura/aarch64-macos");
104 let a = r.archive.expect("obscura ships an archive");
105 assert_eq!(a.members.len(), 2, "obscura + obscura-worker");
106 assert!(a.members.iter().any(|m| m.install_to == "aura/obscura"));
107 assert!(
108 a.members
109 .iter()
110 .any(|m| m.install_to == "aura/obscura-worker")
111 );
112 }
113}