// use crate::messages::MessageToken; use git_next_core::RepoConfig; use git_next_git::{self as git, repository::open::OpenRepositoryLike}; use derive_more::Display; use tracing::{info, warn}; // advance next to the next commit towards the head of the dev branch #[tracing::instrument(fields(next), skip_all)] pub fn advance_next( next: &git::Commit, dev_commit_history: &[git::Commit], repo_details: git::RepoDetails, repo_config: RepoConfig, open_repository: &dyn OpenRepositoryLike, message_token: MessageToken, ) -> Result { let commit = find_next_commit_on_dev(next, dev_commit_history).ok_or_else(|| Error::NextAtDev)?; validate_commit_message(commit.message())?; info!("Advancing next to commit '{}'", commit); git::push::reset( open_repository, &repo_details, &repo_config.branches().next(), &commit.into(), &git::push::Force::No, )?; Ok(message_token) } #[tracing::instrument] fn validate_commit_message(message: &git::commit::Message) -> Result<()> { let message = &message.to_string(); if message.to_ascii_lowercase().starts_with("wip") { return Err(Error::IsWorkInProgress); } match git_conventional::Commit::parse(message) { Ok(commit) => { info!(?commit, "Pass"); Ok(()) } Err(err) => { warn!(?err, "Fail"); Err(Error::InvalidCommitMessage { reason: err.kind().to_string(), }) } } } pub fn find_next_commit_on_dev( next: &git::Commit, dev_commit_history: &[git::Commit], ) -> Option { let mut next_commit: Option<&git::Commit> = None; for commit in dev_commit_history.iter() { if commit == next { break; }; next_commit.replace(commit); } next_commit.cloned() } // advance main branch to the commit 'next' #[tracing::instrument(fields(next), skip_all)] pub fn advance_main( next: git::Commit, repo_details: &git::RepoDetails, repo_config: &RepoConfig, open_repository: &dyn OpenRepositoryLike, ) -> Result<()> { info!("Advancing main to next"); git::push::reset( open_repository, repo_details, &repo_config.branches().main(), &next.into(), &git::push::Force::No, )?; Ok(()) } pub type Result = core::result::Result; #[derive(Debug, thiserror::Error, Display)] pub enum Error { #[display("push: {}", 0)] Push(#[from] git::push::Error), #[display("no commits to advance next to")] NextAtDev, #[display("commit is a Work-in-progress")] IsWorkInProgress, #[display("commit message is not in conventional commit format: {reason}")] InvalidCommitMessage { reason: String }, }