use crate::engine::host::Host;
use crate::git::GitError;
use crate::merge::deliver;
pub const YOUR_FILES: &str = "your files";
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Lands {
Files,
FilesAfterYourCommit,
FirstCommit { branch: String },
FirstCommitMade { branch: String, commit: String },
}
impl Lands {
pub fn target(&self) -> &str {
match self {
Self::Files | Self::FilesAfterYourCommit => YOUR_FILES,
Self::FirstCommit { branch } | Self::FirstCommitMade { branch, .. } => branch,
}
}
}
pub async fn base(host: &Host) -> Result<Option<String>, GitError> {
let name = argonauts_core::unborn::base_ref(host.run_id());
host.git().ref_commit(&host.repo().root, &name).await
}
pub async fn lands(host: &Host) -> Result<Option<Lands>, GitError> {
if base(host).await?.is_none() {
return Ok(None);
}
if !argonauts_core::unborn::makes_first_commit(host.settings()) {
return Ok(Some(Lands::Files));
}
let git = host.git();
let root = &host.repo().root;
let Some(branch) = git.current_branch(root).await? else {
return Ok(Some(Lands::FilesAfterYourCommit));
};
Ok(Some(match git.head_commit(root).await? {
None => Lands::FirstCommit { branch },
Some(commit) if is_the_runs_first_commit(host, &commit).await? => {
Lands::FirstCommitMade { branch, commit }
}
Some(_) => Lands::FilesAfterYourCommit,
}))
}
async fn is_the_runs_first_commit(host: &Host, commit: &str) -> Result<bool, GitError> {
let git = host.git();
let root = &host.repo().root;
if !git.parents(root, commit).await?.is_empty() {
return Ok(false);
}
let log = git.log_messages(root, commit).await?;
Ok(log
.first()
.is_some_and(|(_, message)| deliver::names_run(message, host.run_id())))
}
pub async fn approval_line(host: &Host) -> Result<Option<String>, GitError> {
Ok(match lands(host).await? {
Some(Lands::FirstCommit { branch }) => Some(format!(
"{branch} has no commits yet, so merging makes its first one: your files as the \
run found them, with the run's work (merge.unborn)"
)),
_ => None,
})
}
pub async fn edited_in_the_way(
host: &Host,
base: &str,
head: &str,
) -> Result<Vec<String>, GitError> {
let repo = host.repo();
let scratch = repo.run_dir.join("in-the-way.index");
host.git()
.differing_in_the_way(&repo.root, &scratch, base, head)
.await
}