use std::collections::HashMap;
use anyhow::Context as _;
use git_cliff_core::{config::ChangelogConfig, contributor::RemoteContributor};
use git_cmd::Repo;
use crate::{GitClient, NO_COMMIT_ID, diff::Commit};
#[derive(Debug)]
pub struct RequiredInfo {
author_name: bool,
author_email: bool,
committer_name: bool,
committer_email: bool,
remote_username: bool,
remote_pr_number: bool,
}
impl RequiredInfo {
fn is_remote_required(&self) -> bool {
self.remote_username || self.remote_pr_number
}
}
pub async fn fill_commit<'a>(
commit: &'a mut Commit,
required_info: &RequiredInfo,
repository: &Repo,
all_commits: &mut HashMap<String, &'a Commit>,
git_client: Option<&GitClient>,
) -> anyhow::Result<()> {
if let Some(existing_commit) = all_commits.get(&commit.id) {
commit.author = existing_commit.author.clone();
commit.committer = existing_commit.committer.clone();
commit.remote = existing_commit.remote.clone();
} else {
if required_info.author_name {
commit.author.name = Some(repository.get_author_name(&commit.id)?);
}
if required_info.author_email {
commit.author.email = Some(repository.get_author_email(&commit.id)?);
}
if required_info.committer_name {
commit.committer.name = Some(repository.get_committer_name(&commit.id)?);
}
if required_info.committer_email {
commit.committer.email = Some(repository.get_committer_email(&commit.id)?);
}
if required_info.is_remote_required() {
let git_client = git_client
.context("The changelog template requires information from the remote, but git token wasn't provided")?;
let username = if required_info.remote_username && commit.id != NO_COMMIT_ID {
git_client.get_remote_commit(&commit.id).await?.username
} else {
None
};
let pr_number = if required_info.remote_pr_number && commit.id != NO_COMMIT_ID {
let associated_prs = git_client.associated_prs(&commit.id).await?;
associated_prs.first().map(|pr| pr.number)
} else {
None
};
commit.remote = RemoteContributor {
username,
pr_number: pr_number.and_then(|n| i64::try_from(n).ok()),
..RemoteContributor::default()
};
}
all_commits.insert(commit.id.clone(), commit);
}
Ok(())
}
pub fn get_required_info(changelog_config: &ChangelogConfig) -> RequiredInfo {
let mut required_info = RequiredInfo {
author_name: false,
author_email: false,
committer_name: false,
committer_email: false,
remote_username: false,
remote_pr_number: false,
};
required_info.author_name = changelog_config.body.contains("author.name");
required_info.author_email = changelog_config.body.contains("author.email");
required_info.committer_name = changelog_config.body.contains("committer.name");
required_info.committer_email = changelog_config.body.contains("committer.email");
required_info.remote_username = changelog_config.body.contains("remote.username");
required_info.remote_pr_number = changelog_config.body.contains("remote.pr_number");
required_info
}