use crate::error::Result;
use governor_core::{
domain::commit::{Commit, CommitType},
domain::version::{BumpType, SemanticVersion},
traits::source_control::SourceControl,
};
use governor_git::GitAdapter;
use std::path::PathBuf;
pub async fn analyze_versions(
workspace_path: &str,
) -> Result<(BumpType, SemanticVersion, SemanticVersion)> {
let config = governor_git::GitAdapterConfig {
repository_path: Some(PathBuf::from(workspace_path)),
..Default::default()
};
let git = GitAdapter::open(config)
.map_err(|e| crate::error::Error::Config(format!("Failed to open git repository: {e}")))?;
let commits = git
.get_commits_since(None)
.await
.map_err(|e| crate::error::Error::Git(format!("Failed to get commits: {e}")))?;
let bump_type = determine_bump_from_commits(&commits);
let current_version = super::metadata::get_current_version(workspace_path)?;
let current = SemanticVersion::parse(¤t_version).map_err(|e| {
crate::error::Error::Version(format!("Failed to parse current version: {e}"))
})?;
let new_version = bump_type.apply_to(¤t);
Ok((bump_type, current, new_version))
}
fn determine_bump_from_commits(commits: &[Commit]) -> BumpType {
let mut has_breaking = false;
let mut has_features = false;
let mut has_fixes = false;
for commit in commits {
match commit.commit_type {
Some(CommitType::Feat | CommitType::Fix | CommitType::Perf | CommitType::Refactor)
if commit.breaking =>
{
has_breaking = true;
}
Some(CommitType::Feat) => has_features = true,
Some(CommitType::Fix | CommitType::Perf) => has_fixes = true,
_ => {}
}
}
if has_breaking {
BumpType::Major
} else if has_features {
BumpType::Minor
} else if has_fixes {
BumpType::Patch
} else {
BumpType::None
}
}