use crate::cli::OutputFormat;
use crate::error::CommandError;
use crate::release;
pub(crate) fn run_graph(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 unit_graph = release::build_unit_graph(&crate_graph);
let crate_order = crate_graph.topological_order().map_err(|topo_err| {
CommandError::Release(release::ReleaseError::Validation(vec![
release::Diagnostic {
crate_name: "graph".to_string(),
message: format!("{topo_err}"),
},
]))
})?;
let unit_order = unit_graph.topological_order().map_err(|topo_err| {
CommandError::Release(release::ReleaseError::Validation(vec![
release::Diagnostic {
crate_name: "graph".to_string(),
message: format!("{topo_err}"),
},
]))
})?;
match format {
OutputFormat::Human => {
println!("Publishable crates: {}", crate_graph.nodes.len());
println!("Release units: {}", unit_graph.nodes.len());
println!();
println!("Crate topological order:");
for (i, name) in crate_order.iter().enumerate() {
println!(" {}. {name}", i + 1);
}
println!();
println!("Unit topological order:");
for (i, name) in unit_order.iter().enumerate() {
let node = &unit_graph.nodes[name];
println!(" {}. {name} (members: {})", i + 1, node.members.len());
}
Ok(())
}
OutputFormat::Json => {
let payload = serde_json::json!({
"crate_count": crate_graph.nodes.len(),
"unit_count": unit_graph.nodes.len(),
"crate_topological_order": crate_order,
"unit_topological_order": unit_order,
"units": unit_graph.nodes.iter().map(|(name, node)| {
serde_json::json!({
"name": name,
"members": node.members,
"dependencies": node.dependencies.keys().collect::<Vec<_>>(),
})
}).collect::<Vec<_>>(),
});
println!("{}", serde_json::to_string_pretty(&payload)?);
Ok(())
}
}
}