use crate::cli::OutputFormat;
use crate::error::CommandError;
use crate::release;
pub(crate) fn run_version(format: OutputFormat) -> Result<(), CommandError> {
let document = release::load_metadata()?;
let crates = release::discover(&document);
release::validate(&crates).map_err(|diagnostics| {
CommandError::Release(release::ReleaseError::Validation(diagnostics))
})?;
let crate_graph = release::build_crate_graph(&document, &crates);
let mut current_versions: std::collections::BTreeMap<String, release::Ybf> =
std::collections::BTreeMap::new();
let mut version_diagnostics: Vec<release::Diagnostic> = Vec::new();
for pkg in &document.packages {
if let Some(raw) = &pkg.version {
match release::Ybf::parse(raw) {
Ok(v) => {
current_versions.insert(pkg.name.clone(), v);
}
Err(error) => {
version_diagnostics.push(release::Diagnostic {
crate_name: pkg.name.clone(),
message: format!("{error}"),
});
}
}
}
}
let range_findings = release::validate_ranges(&document, &crates, &crate_graph);
let mut all_findings = version_diagnostics;
all_findings.extend(range_findings);
all_findings.sort_by(|a, b| {
a.crate_name
.cmp(&b.crate_name)
.then(a.message.cmp(&b.message))
});
match format {
OutputFormat::Human => {
println!("Publishable crates: {}", crate_graph.nodes.len());
println!();
println!("Current versions:");
for (name, version) in ¤t_versions {
let in_graph = crate_graph.nodes.contains_key(name);
if in_graph {
println!(" {name}: {version}");
}
}
println!();
if all_findings.is_empty() {
println!("YBF range validation: OK (no findings)");
} else {
println!("YBF range validation: {} finding(s)", all_findings.len());
for finding in &all_findings {
println!(" {finding}");
}
}
Ok(())
}
OutputFormat::Json => {
let payload = serde_json::json!({
"crate_count": crate_graph.nodes.len(),
"versions": current_versions.iter()
.filter(|(name, _)| crate_graph.nodes.contains_key(name.as_str()))
.map(|(name, v)| (name.clone(), v.to_string()))
.collect::<std::collections::BTreeMap<String, String>>(),
"findings": all_findings.iter().map(|d| serde_json::json!({
"crate": d.crate_name,
"message": d.message,
})).collect::<Vec<_>>(),
"ok": all_findings.is_empty(),
});
println!("{}", serde_json::to_string_pretty(&payload)?);
Ok(())
}
}
}