use conventional_commit_parser::commit::{CommitType, ConventionalCommit};
use semver::Version;
use crate::NextVersion;
pub enum VersionIncrement {
Major,
Minor,
Patch,
}
impl VersionIncrement {
pub fn from_commits<I>(current_version: &Version, commits: I) -> Option<Self>
where
I: IntoIterator,
I::Item: AsRef<str>,
{
let mut commits = commits.into_iter().peekable();
let are_commits_present = commits.peek().is_some();
if !are_commits_present {
None
} else {
let commits: Vec<ConventionalCommit> = commits
.filter_map(|c| conventional_commit_parser::parse(c.as_ref()).ok())
.collect();
Some(Self::from_conventional_commits(current_version, &commits))
}
}
fn from_conventional_commits(
current_version: &Version,
commits: &[ConventionalCommit],
) -> Self {
let is_there_a_breaking_change = commits.iter().any(|commit| commit.is_breaking_change);
let is_major_bump = || current_version.major != 0 && is_there_a_breaking_change;
let is_minor_bump = || {
current_version.major != 0
&& commits
.iter()
.any(|commit| commit.commit_type == CommitType::Feature)
|| current_version.major == 0 && is_there_a_breaking_change
};
if is_major_bump() {
Self::Major
} else if is_minor_bump() {
Self::Minor
} else {
Self::Patch
}
}
}
impl VersionIncrement {
pub fn bump(&self, version: &Version) -> Version {
match self {
Self::Major => version.increment_major(),
Self::Minor => version.increment_minor(),
Self::Patch => version.increment_patch(),
}
}
}