Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

xtask/tests/free_tree.rs

//! **RED-when-broken: gunnar's tree names no paid crate** (the owner, 2026-10-08).
//!
//! Every outside service has ONE seam in open monetize, a FREE impl there and a commercial one
//! in monetize-impl; the dependency points one way and gunnar never names monetize-impl. This
//! gate walks every manifest and every lockfile of the tree — the detached workspaces included —
//! and fails on any paid crate, or any path into monetize-impl.
//!
//! LEGACY (ONE monetize, owner 2026-10-10 13:35Z): `gunnar-front-commercial`, the paid front
//! built from monetize-impl with an estate's own monetize in it, is gone — the metered front is
//! gunnar's own `gunnar-front --features metered`, which links no monetize. The name stays in
//! the paid list so it can never come back into gunnar's tree.

use std::path::{Path, PathBuf};

use xtask::one_clone::{lockfiles, manifests};

/// The crates monetize-impl publishes to nobody: what an open gunnar build may never name.
const PAID: &[&str] = &[
    "monetize-server-vetra",
    "monetize-cloud-impl",
    "monetize-pay-impl",
    "monetize-signup-impl",
    "monetize-tax-impl",
    "monetize-product-njord",
    "monetize-plugin-holger",
    "gunnar-front-commercial",
    "gunnar-shop-bench",
];

fn root() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .expect("xtask has a parent")
        .to_path_buf()
}

/// Pure: **the paid names a manifest's text depends on** — a `<name> =` key, a
/// `[dependencies.<name>]` table, or a `path` into `monetize-impl`. Comment lines are prose.
fn paid_in_manifest(text: &str) -> Vec<String> {
    let mut out = Vec::new();
    for line in text.lines().map(str::trim).filter(|l| !l.starts_with('#')) {
        let line = line.split(" #").next().unwrap_or(line);
        for name in PAID {
            let key = line
                .split('=')
                .next()
                .unwrap_or("")
                .trim()
                .trim_matches('"');
            let table = line.trim_start_matches('[').trim_end_matches(']');
            if key == *name || table.ends_with(&format!(".{name}")) {
                out.push((*name).to_string());
            }
        }
        if line.contains("path") && line.contains("monetize-impl") {
            out.push(format!("a path into monetize-impl: {line}"));
        }
    }
    out
}

/// Pure: the paid packages a lockfile holds.
fn paid_in_lock(text: &str) -> Vec<String> {
    PAID.iter()
        .filter(|n| text.contains(&format!("name = \"{n}\"")))
        .map(|n| (*n).to_string())
        .collect()
}

#[test]
fn gunnars_tree_names_no_paid_crate() {
    let root = root();
    let (ms, ls) = (manifests(&root), lockfiles(&root));
    assert!(
        ms.len() > 20 && ms.iter().any(|m| m.starts_with("crates/gunnar-growbench")),
        "the walk sees the tree, detached crates included: {}",
        ms.len()
    );
    let mut found = Vec::new();
    for m in &ms {
        for p in paid_in_manifest(&std::fs::read_to_string(root.join(m)).unwrap_or_default()) {
            found.push(format!("{m}: {p}"));
        }
    }
    for l in &ls {
        for p in paid_in_lock(&std::fs::read_to_string(root.join(l)).unwrap_or_default()) {
            found.push(format!("{l}: {p}"));
        }
    }
    assert!(
        found.is_empty(),
        "gunnar's tree names paid crates — a paid crate lives in monetize-impl, never here:\n  {}",
        found.join("\n  ")
    );
}

/// The red half: each shape is SEEN, and prose that forbids it is not mistaken for it.
#[test]
fn a_paid_dependency_is_reported_in_each_shape() {
    assert_eq!(paid_in_manifest("monetize-server-vetra = { path = \"../../../monetize-impl/crates/monetize-server-vetra\" }").len(), 2);
    assert_eq!(
        paid_in_manifest("[dependencies.monetize-cloud-impl]\nversion = \"0.1\""),
        vec!["monetize-cloud-impl".to_string()]
    );
    assert_eq!(
        paid_in_manifest("x = { path = \"../../monetize-impl/crates/y\" }").len(),
        1
    );
    assert!(paid_in_manifest(
        "# monetize-server-vetra = { path = \"../monetize-impl\" } is never named here"
    )
    .is_empty());
    assert!(
        paid_in_manifest(
            "monetize-server = { path = \"../../../monetize/crates/monetize-server\" }"
        )
        .is_empty(),
        "the OPEN server is fine"
    );
    assert_eq!(
        paid_in_lock("[[package]]\nname = \"monetize-pay-impl\"\n"),
        vec!["monetize-pay-impl".to_string()]
    );
}