git-next/crates/cli/src/repo/branch.rs
Paul Campbell 6c60e3fb7a
All checks were successful
Rust / build (push) Successful in 6m11s
Release Please / Release-plz (push) Successful in 1m38s
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
ci/woodpecker/cron/cron-docker-builder Pipeline was successful
ci/woodpecker/cron/push-next Pipeline was successful
ci/woodpecker/cron/tag-created Pipeline was successful
refactor: reimplement git fetch using git
2024-09-13 18:55:21 +01:00

114 lines
2.9 KiB
Rust

//
use crate::repo::messages::MessageToken;
use git_next_core::{
git::{
commit::Message,
push::{reset, Force},
repository::open::OpenRepositoryLike,
Commit, GitRef, RepoDetails,
},
RepoConfig,
};
use derive_more::Display;
use tracing::{info, instrument, warn};
// advance next to the next commit towards the head of the dev branch
#[instrument(fields(next), skip_all)]
pub fn advance_next(
commit: Option<Commit>,
force: git_next_core::git::push::Force,
repo_details: &RepoDetails,
repo_config: RepoConfig,
open_repository: &dyn OpenRepositoryLike,
message_token: MessageToken,
) -> Result<MessageToken> {
let commit = commit.ok_or_else(|| Error::NextAtDev)?;
validate_commit_message(commit.message())?;
info!("Advancing next to commit '{}'", commit);
reset(
open_repository,
repo_details,
&repo_config.branches().next(),
&commit.into(),
&force,
)?;
Ok(message_token)
}
#[instrument]
fn validate_commit_message(message: &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: &Commit,
main: &Commit,
dev_commit_history: &[Commit],
) -> (Option<Commit>, Force) {
let mut next_commit: Option<&Commit> = None;
let mut force = Force::No;
for commit in dev_commit_history {
if commit == next {
break;
};
if commit == main {
force = Force::From(GitRef::from(next.sha().clone()));
break;
};
next_commit.replace(commit);
}
(next_commit.cloned(), force)
}
// advance main branch to the commit 'next'
#[instrument(fields(next), skip_all)]
pub fn advance_main(
next: Commit,
repo_details: &RepoDetails,
repo_config: &RepoConfig,
open_repository: &dyn OpenRepositoryLike,
) -> Result<()> {
info!("Advancing main to next");
reset(
open_repository,
repo_details,
&repo_config.branches().main(),
&next.into(),
&Force::No,
)?;
Ok(())
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error, Display)]
pub enum Error {
#[display("push: {}", 0)]
Push(#[from] crate::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 },
}