use crate::dependent_version_release::{ReleaseBump, UnsupportedVersion, patch_bump_version};
use std::collections::{HashMap, HashSet};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WorkspaceNode {
pub name: String,
pub directory: Vec<u8>,
pub version: Option<Vec<u16>>,
pub edge_names: Vec<String>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PlannedBump {
pub name: String,
pub directory: Vec<u8>,
pub bump: ReleaseBump,
}
pub fn transitive_dependent_names(
nodes: &[WorkspaceNode],
bumped_names: &[String],
) -> HashSet<String> {
let workspace: HashSet<&str> = nodes
.iter()
.map(|node: &WorkspaceNode| return node.name.as_str())
.collect();
let mut dependents: HashMap<&str, Vec<&str>> = HashMap::new();
for node in nodes {
for edge in &node.edge_names {
if workspace.contains(edge.as_str()) && *edge != node.name {
dependents
.entry(edge.as_str())
.or_default()
.push(node.name.as_str());
}
}
}
let mut pending: Vec<&str> = bumped_names.iter().map(String::as_str).collect();
let mut reached: HashSet<String> = HashSet::new();
while let Some(current) = pending.pop() {
for dependent in dependents.get(current).map_or(&[][..], Vec::as_slice) {
if reached.insert(String::from(*dependent)) {
pending.push(dependent);
}
}
}
return reached;
}
pub fn utf16_order(left: &str, right: &str) -> std::cmp::Ordering {
return left.encode_utf16().cmp(right.encode_utf16());
}
pub fn plan_dependent_bumps(
nodes: &[WorkspaceNode],
bumped_names: &[String],
publishable_names: &[String],
) -> Result<Vec<PlannedBump>, UnsupportedVersion> {
let reached: HashSet<String> = transitive_dependent_names(nodes, bumped_names);
let mut bumps: Vec<PlannedBump> = Vec::new();
for node in nodes {
let needs_bump: bool = reached.contains(&node.name)
&& !bumped_names.contains(&node.name)
&& publishable_names.contains(&node.name);
if let (true, Some(version)) = (needs_bump, &node.version) {
bumps.push(PlannedBump {
name: node.name.clone(),
directory: node.directory.clone(),
bump: patch_bump_version(&node.name, version)?,
});
}
}
bumps.sort_by(|left: &PlannedBump, right: &PlannedBump| {
return utf16_order(&left.name, &right.name);
});
return Ok(bumps);
}
#[cfg(test)]
#[path = "dependent_version_graph_tests.rs"]
mod tests;