#![allow(dead_code)]
use std::collections::BTreeMap;
use serde::Deserialize;
use thiserror::Error;
pub const TEMPLATE: &str = include_str!("../templates/omne-readme-template.md");
#[derive(Debug, Clone)]
pub struct Vars {
pub volume: String,
pub distro: String,
pub distro_version: String,
pub created: String,
pub kernel_source: String,
pub distro_source: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct ManifestFrontmatter {
pub volume: String,
pub distro: String,
#[serde(rename = "distro-version")]
pub distro_version: String,
pub created: String,
#[serde(rename = "kernel-source")]
pub kernel_source: String,
#[serde(rename = "distro-source")]
pub distro_source: String,
}
#[derive(Debug, Error)]
pub enum Error {
#[error(".omne/omne.md is missing its `---...---` YAML frontmatter fences")]
MissingFrontmatter,
#[error(".omne/omne.md frontmatter is missing required field: {field}")]
MissingField { field: String },
#[error(".omne/omne.md frontmatter is not valid YAML: {0}")]
Yaml(#[from] serde_yml::Error),
#[error("invalid source format '{value}' in .omne/omne.md — expected org/repo")]
InvalidSourceFormat { value: String },
}
pub fn stamp(vars: &Vars) -> String {
TEMPLATE
.replace("{{volume}}", &vars.volume)
.replace("{{distro}}", &vars.distro)
.replace("{{distro-version}}", &vars.distro_version)
.replace("{{created}}", &vars.created)
.replace("{{kernel-source}}", &vars.kernel_source)
.replace("{{distro-source}}", &vars.distro_source)
}
pub fn parse_frontmatter(md: &str) -> Result<ManifestFrontmatter, Error> {
let yaml_body = extract_frontmatter_block(md)?;
let mut map: BTreeMap<String, String> = serde_yml::from_str(&yaml_body)?;
fn take(map: &mut BTreeMap<String, String>, key: &str) -> Result<String, Error> {
map.remove(key).ok_or_else(|| Error::MissingField {
field: key.to_string(),
})
}
let volume = take(&mut map, "volume")?;
let distro = take(&mut map, "distro")?;
let distro_version = take(&mut map, "distro-version")?;
let created = take(&mut map, "created")?;
let kernel_source = take(&mut map, "kernel-source")?;
let distro_source = take(&mut map, "distro-source")?;
Ok(ManifestFrontmatter {
volume,
distro,
distro_version,
created,
kernel_source,
distro_source,
})
}
pub(crate) fn extract_frontmatter_block(md: &str) -> Result<String, Error> {
let mut lines = md.lines();
match lines.next() {
Some("---") => {}
_ => return Err(Error::MissingFrontmatter),
}
let mut body = String::new();
let mut closed = false;
for line in lines {
if line == "---" {
closed = true;
break;
}
body.push_str(line);
body.push('\n');
}
if !closed {
return Err(Error::MissingFrontmatter);
}
Ok(body)
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_vars() -> Vars {
Vars {
volume: "my-app".to_string(),
distro: "omne-faber".to_string(),
distro_version: "1.0.0".to_string(),
created: "2026-04-09".to_string(),
kernel_source: "omne-org/omne".to_string(),
distro_source: "omne-org/omne-faber".to_string(),
}
}
#[test]
fn template_contains_all_placeholders() {
for placeholder in [
"{{volume}}",
"{{distro}}",
"{{distro-version}}",
"{{created}}",
"{{kernel-source}}",
"{{distro-source}}",
] {
assert!(
TEMPLATE.contains(placeholder),
"template must contain {placeholder}, template was:\n{TEMPLATE}",
);
}
}
#[test]
fn stamp_replaces_all_placeholders() {
let out = stamp(&sample_vars());
assert!(
!out.contains("{{"),
"stamped output still contains `{{{{`:\n{out}",
);
assert!(
!out.contains("}}"),
"stamped output still contains `}}}}`:\n{out}",
);
}
#[test]
fn stamp_contains_volume_name() {
let out = stamp(&sample_vars());
assert!(out.contains("my-app"), "missing volume name:\n{out}");
}
#[test]
fn stamp_contains_distro_name() {
let out = stamp(&sample_vars());
assert!(out.contains("omne-faber"), "missing distro name:\n{out}");
}
#[test]
fn stamp_contains_distro_version() {
let out = stamp(&sample_vars());
assert!(out.contains("1.0.0"), "missing distro version:\n{out}");
}
#[test]
fn stamp_contains_created_date() {
let out = stamp(&sample_vars());
assert!(out.contains("2026-04-09"), "missing created date:\n{out}");
}
#[test]
fn stamp_contains_kernel_source() {
let out = stamp(&sample_vars());
assert!(
out.contains("kernel-source: omne-org/omne"),
"missing `kernel-source` frontmatter line:\n{out}",
);
}
#[test]
fn stamp_contains_distro_source() {
let out = stamp(&sample_vars());
assert!(
out.contains("distro-source: omne-org/omne-faber"),
"missing `distro-source` frontmatter line:\n{out}",
);
}
#[test]
fn stamp_output_starts_with_yaml_fence() {
let out = stamp(&sample_vars());
assert!(
out.starts_with("---\n") || out.starts_with("---\r\n"),
"stamped output should begin with `---` fence, got: {:?}",
&out.chars().take(10).collect::<String>(),
);
}
#[test]
fn parse_frontmatter_round_trips_with_stamp() {
let vars = sample_vars();
let stamped = stamp(&vars);
let parsed =
parse_frontmatter(&stamped).expect("parsing a freshly-stamped manifest should succeed");
assert_eq!(parsed.volume, vars.volume);
assert_eq!(parsed.distro, vars.distro);
assert_eq!(parsed.distro_version, vars.distro_version);
assert_eq!(parsed.created, vars.created);
assert_eq!(parsed.kernel_source, vars.kernel_source);
assert_eq!(parsed.distro_source, vars.distro_source);
}
#[test]
fn parse_frontmatter_errors_on_no_fences() {
let md = "# MANIFEST\n\nNo frontmatter here.\n";
match parse_frontmatter(md) {
Err(Error::MissingFrontmatter) => {}
other => panic!("expected MissingFrontmatter, got {other:?}"),
}
}
#[test]
fn parse_frontmatter_errors_on_unclosed_fence() {
let md = "---\nvolume: x\ndistro: y\n\n# body without closing fence\n";
match parse_frontmatter(md) {
Err(Error::MissingFrontmatter) => {}
other => panic!("expected MissingFrontmatter on unclosed fence, got {other:?}"),
}
}
#[test]
fn parse_frontmatter_errors_on_missing_kernel_source() {
let md = "---\n\
volume: my-app\n\
distro: omne-faber\n\
distro-version: 1.0.0\n\
created: 2026-04-09\n\
distro-source: omne-org/omne-faber\n\
---\n\
\n\
# body\n";
match parse_frontmatter(md) {
Err(Error::MissingField { field }) => {
assert_eq!(field, "kernel-source");
}
other => panic!("expected MissingField kernel-source, got {other:?}"),
}
}
#[test]
fn parse_frontmatter_errors_on_missing_distro_source() {
let md = "---\n\
volume: my-app\n\
distro: omne-faber\n\
distro-version: 1.0.0\n\
created: 2026-04-09\n\
kernel-source: omne-org/omne\n\
---\n\
\n\
# body\n";
match parse_frontmatter(md) {
Err(Error::MissingField { field }) => {
assert_eq!(field, "distro-source");
}
other => panic!("expected MissingField distro-source, got {other:?}"),
}
}
}