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",
)
}
}
}