zlayer_toolchain/
formula.rs1use crate::error::Result;
15
16pub use zlayer_types::package_index::{FormulaData as Formula, UsesFromMacos};
19
20pub async fn fetch_formula(formula: &str) -> Result<Formula> {
32 tracing::info!("Resolving Homebrew formula metadata for: {formula}");
33 crate::package_index::PackageIndexClient::from_env()
34 .get_formula(formula)
35 .await
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 const GIT_JSON: &str = r#"{
43 "versions": {"stable": "2.55.0"},
44 "urls": {"stable": {"url": "https://example/git-2.55.0.tar.xz", "checksum": "sha256:abc123"}},
45 "dependencies": ["pcre2", "gettext"],
46 "build_dependencies": ["gettext", "pkgconf"],
47 "uses_from_macos": ["curl", "expat", {"llvm": ["build"]}],
48 "ruby_source_path": "Formula/g/git.rb"
49 }"#;
50
51 #[test]
52 fn parses_all_unified_fields_including_checksum() {
53 let f: Formula = serde_json::from_str(GIT_JSON).unwrap();
54 assert_eq!(f.stable_version(), Some("2.55.0"));
55 assert_eq!(f.stable_url(), Some("https://example/git-2.55.0.tar.xz"));
56 assert_eq!(f.stable_checksum().as_deref(), Some("abc123"));
58 assert_eq!(f.dependencies, vec!["pcre2", "gettext"]);
59 assert_eq!(f.build_dependencies, vec!["gettext", "pkgconf"]);
60 assert_eq!(f.ruby_source_path.as_deref(), Some("Formula/g/git.rb"));
61 assert_eq!(f.macos_provided(), vec!["curl", "expat", "llvm"]);
63 }
64
65 #[test]
66 fn missing_fields_default_cleanly() {
67 let f: Formula = serde_json::from_str("{}").unwrap();
68 assert_eq!(f.stable_version(), None);
69 assert_eq!(f.stable_url(), None);
70 assert_eq!(f.stable_checksum(), None);
71 assert!(f.dependencies.is_empty());
72 assert!(f.build_dependencies.is_empty());
73 assert!(f.macos_provided().is_empty());
74 assert!(f.ruby_source_path.is_none());
75 }
76
77 #[test]
78 fn empty_version_and_url_are_treated_as_absent() {
79 let f: Formula =
80 serde_json::from_str(r#"{"versions":{"stable":""},"urls":{"stable":{"url":""}}}"#)
81 .unwrap();
82 assert_eq!(f.stable_version(), None);
83 assert_eq!(f.stable_url(), None);
84 }
85
86 #[test]
87 fn uses_from_macos_name_accessor() {
88 let bare = UsesFromMacos::Name("curl".to_string());
89 assert_eq!(bare.name(), Some("curl"));
90 }
91}