koala-core 1.0.4

Shared types, invariant evaluator, and primitives for the koala framework.
Documentation
use crate::invariant::rules::util::{list_cargo_tomls, rel};
use crate::invariant::{Category, Context, Invariant, Outcome};
use std::fs;

pub struct NoWildcardDep;

impl Invariant for NoWildcardDep {
    fn id(&self) -> &'static str {
        "deps.no-wildcard"
    }
    fn category(&self) -> Category {
        Category::Deps
    }
    fn intent(&self) -> &'static str {
        "No wildcard (`*`) version constraint in any Cargo.toml — crates.io rejects them on publish."
    }
    fn adr(&self) -> Option<&'static str> {
        Some("ADR-0013")
    }

    fn evaluate(&self, ctx: &Context) -> Outcome {
        let mut hits = Vec::new();
        for path in list_cargo_tomls(ctx.root()) {
            let Ok(content) = fs::read_to_string(&path) else {
                continue;
            };
            for (i, line) in content.lines().enumerate() {
                let trimmed = line.trim_start();
                if trimmed.starts_with('#') {
                    continue;
                }
                if trimmed.contains("version = \"*\"") || trimmed.contains("version=\"*\"") {
                    hits.push(format!("{}:{}", rel(&path, ctx.root()), i + 1));
                }
            }
        }
        if hits.is_empty() {
            Outcome::pass()
        } else {
            Outcome::fail_repro(
                format!("wildcard version found:\n  {}", hits.join("\n  ")),
                "grep -rn 'version *= *\"\\*\"' --include=Cargo.toml",
            )
        }
    }
}