use crate::authoring::files::hash;
use serde_json::{Map, Value, json};
use std::path::Path;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Entry {
pub url: String,
pub visibility: String,
}
impl Entry {
pub fn is_public(&self) -> bool {
self.visibility.eq_ignore_ascii_case("public")
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Manifest {
pub gitmodules_sha256: String,
pub measured_at: String,
pub submodules: Vec<(String, Entry)>,
}
pub fn gitmodules_sha256(root: &Path) -> String {
hash::file(&root.join(".gitmodules")).map(|(sha, _)| sha).unwrap_or_default()
}
pub fn read(root: &Path, rel: &str) -> Option<Manifest> {
parse(&std::fs::read_to_string(root.join(rel)).ok()?)
}
pub fn parse(text: &str) -> Option<Manifest> {
let v: Value = serde_json::from_str(text).ok()?;
let gitmodules_sha256 = v.get("gitmodulesSha256")?.as_str()?.to_string();
let measured_at = v.get("measuredAt").and_then(Value::as_str).unwrap_or_default().to_string();
let mut submodules = vec![];
for (path, e) in v.get("submodules")?.as_object()? {
let visibility = e.get("visibility")?.as_str()?.to_string();
let url = e.get("url").and_then(Value::as_str).unwrap_or_default().to_string();
submodules.push((path.clone(), Entry { url, visibility }));
}
Some(Manifest { gitmodules_sha256, measured_at, submodules })
}
pub fn render(m: &Manifest) -> String {
let mut subs = Map::new();
for (path, e) in &m.submodules {
subs.insert(path.clone(), json!({"url": e.url, "visibility": e.visibility}));
}
let mut top = Map::new();
top.insert("gitmodulesSha256".into(), Value::String(m.gitmodules_sha256.clone()));
top.insert("measuredAt".into(), Value::String(m.measured_at.clone()));
top.insert("submodules".into(), Value::Object(subs));
let text = serde_json::to_string_pretty(&Value::Object(top)).unwrap_or_default();
format!("{text}\n")
}