holger-recipe/src/load.rs
//! **The open load of holger's declaration** — `.nornir/build-variants.toml` read and
//! validated in a tree where the COMMERCIAL `monetize-impl` checkout is absent.
//!
//! Holger is open source (owner rule): its open build must never NEED a
//! monetize-impl checkout. One row names it — the SOLD payload
//! [`METERED_PAYLOAD_VARIANT`](crate::packaging::METERED_PAYLOAD_VARIANT) consumes
//! holger's own signed monetize plugin through the edge
//! `plugin → monetize-impl/holger-guest : wasm`
//! ([`own_plugin_edge`](crate::packaging::own_plugin_edge)), declared `lazy = true`.
//! The shared load (`BuildVariantSet::discover_validated`, the same one the forge
//! runs) therefore:
//!
//! * donor present — type-checks the edge against monetize-impl's own build space;
//! * donor absent — validates every other rule and edge and leaves only the lazy
//! edge unresolved, so the declaration (with the edge in it) loads and lists;
//!
//! and a BUILD of the sold variant with the donor absent is refused by name — by the
//! forge's edge DAG, and by `cargo xtask build` through
//! [`refuse_absent_commercial_donor`] — and only that build.
use std::path::{Path, PathBuf};
use anyhow::{anyhow, bail, Result};
use nornir_build_thing::suite_cli::{self, BuildArgs};
use nornir_build_thing::variant::BuildVariantSet;
use crate::packaging::OWN_PLUGIN_REPO;
/// Where a donor checkout `repo` would sit: beside `repo_root`.
#[must_use]
pub fn donor_root(repo_root: &Path, repo: &str) -> PathBuf {
repo_root.parent().unwrap_or(Path::new("")).join(repo)
}
/// Whether the commercial donor checkout is beside `repo_root`.
#[must_use]
pub fn commercial_donor_present(repo_root: &Path) -> bool {
donor_root(repo_root, OWN_PLUGIN_REPO).is_dir()
}
/// **Load and validate** `repo_root`'s declaration — the shared validated load,
/// under which the commercial edge is lazy.
///
/// # Errors
/// No declaration; any shape, on-disk-input or (eager) edge refusal.
pub fn load_declaration(repo_root: &Path) -> Result<BuildVariantSet> {
BuildVariantSet::discover_validated(repo_root)?.ok_or_else(|| {
anyhow!(
"no {} — this repo declares no build space",
BuildVariantSet::conventional_path(repo_root).display()
)
})
}
/// **The describe half of `cargo xtask build`** over [`load_declaration`]: the
/// lines `suite_cli` prints for `--list`, and the chosen variant names.
///
/// # Errors
/// The load's refusals, and `suite_cli::resolve`'s (unknown suite or variant).
pub fn list(repo_root: &Path, args: &BuildArgs) -> Result<(Vec<String>, Vec<String>)> {
let set = load_declaration(repo_root)?;
let (suite, chosen) = suite_cli::resolve(&set, args)?;
Ok((
suite_cli::list_lines(suite, &chosen),
chosen.iter().map(|v| v.name.clone()).collect(),
))
}
/// **Refuse by name** a build of `variant` when one of its LAZY edges names a donor
/// checkout that is absent (holger's one: the sold variant's monetize-impl guest).
/// `Ok` for every open variant, and for the sold one when monetize-impl is beside
/// holger.
///
/// # Errors
/// The sold variant asked for in a tree without monetize-impl.
pub fn refuse_absent_commercial_donor(
set: &BuildVariantSet,
variant: &str,
repo_root: &Path,
) -> Result<()> {
let Some(edges) = set.edges_of(variant) else {
return Ok(());
};
for (feature, e) in edges {
let root = donor_root(repo_root, &e.repo);
if e.lazy && !root.is_dir() {
let what = if e.repo == OWN_PLUGIN_REPO {
"holger's SOLD variant: its edge"
} else {
"a variant whose lazy edge"
};
bail!(
"variant '{variant}' is {what} {feature} → {} : {} is built by the {} checkout, and \
there is none beside holger ({} is not a directory). The open build never needs \
it; build an open variant, or put the {} checkout there to build this one.",
e.coordinate(),
e.typ.as_str(),
e.repo,
root.display(),
e.repo
);
}
}
Ok(())
}