use crate::engine::capabilities::commit::check::ParsedHeader;
use crate::engine::models::{
git::CommitSummary,
policy::{commit::CommitModel, enforcement::BumpLevel, versioning::Version},
};
pub fn classify_commits(
commits: &[CommitSummary],
policy: &CommitModel,
) -> Vec<(CommitSummary, BumpLevel)> {
commits
.iter()
.map(|commit| {
let bump = classify_single_commit(commit, policy);
(commit.clone(), bump)
})
.collect()
}
fn classify_single_commit(commit: &CommitSummary, policy: &CommitModel) -> BumpLevel {
let header = &commit.summary;
if let Some(parsed) = ParsedHeader::parse(header) {
let is_breaking_footer = commit
.full_message
.as_ref()
.map(|msg| msg.contains(&format!("{}:", policy.breaking_footer_key)))
.unwrap_or(false);
if parsed.is_breaking || is_breaking_footer {
return BumpLevel::Major;
}
if let Some(type_model) = policy.find_type(&parsed.type_name) {
return type_model.bump;
}
return BumpLevel::None;
}
BumpLevel::None
}
pub fn calculate_next_version(
current_version: Option<Version>,
classified_commits: &[(CommitSummary, BumpLevel)],
) -> Version {
let highest_bump = classified_commits
.iter()
.map(|(_, bump)| bump)
.max_by_key(|bump| match bump {
BumpLevel::Major => 3,
BumpLevel::Minor => 2,
BumpLevel::Patch => 1,
BumpLevel::None => 0,
})
.copied()
.unwrap_or(BumpLevel::None);
let base_version = current_version.unwrap_or(Version {
major: 0,
minor: 1,
patch: 0,
});
base_version.with_bump(highest_bump)
}