use super::dispatch::{dispatch_push, DispatchInput, DispatchOutcome};
use crate::error::{BallError, Result};
use crate::git;
use crate::participant::Event;
use crate::participant_config::{override_log, InvocationOverrides};
use crate::store::Store;
use crate::task::Task;
pub fn state_head(store: &Store) -> Result<Option<String>> {
if store.stealth {
return Ok(None);
}
Ok(Some(git::git_resolve_sha(
&store.state_worktree_dir(),
"HEAD",
)?))
}
pub fn log_overrides(store: &Store, tokens: &[String]) -> Result<()> {
let fragment = override_log(tokens);
if fragment.is_empty() || store.stealth {
return Ok(());
}
let dir = store.state_worktree_dir();
let out = git::clean_git_command(&dir)
.args(["log", "-1", "--format=%B"])
.output()?;
let raw = String::from_utf8_lossy(&out.stdout);
let new_msg = amended_message(raw.trim_end(), &fragment);
let st = git::clean_git_command(&dir)
.args(["commit", "--amend", "-m", &new_msg])
.status()?;
if !st.success() {
return Err(BallError::Other(
"failed to amend §11 override log into the state-branch commit".into(),
));
}
Ok(())
}
fn amended_message(msg: &str, fragment: &str) -> String {
let (subject, body) = msg.split_once('\n').unwrap_or((msg, ""));
if body.is_empty() {
format!("{subject}{fragment}")
} else {
format!("{subject}{fragment}\n{body}")
}
}
pub enum Rollback<'a> {
State(Option<&'a str>),
DropClaim,
}
#[allow(clippy::too_many_arguments)]
pub fn finish(
store: &Store,
task_before: Option<&Task>,
task: &Task,
event: Event,
identity: &str,
overrides: &InvocationOverrides,
tokens: &[String],
rollback: Rollback<'_>,
) -> Result<DispatchOutcome> {
log_overrides(store, tokens)?;
let commit = state_head(store)?;
let input = DispatchInput {
store,
task_before,
task,
event,
identity,
commit: commit.as_deref(),
overrides,
override_tokens: tokens,
};
match dispatch_push(&input) {
Ok(outcome) => Ok(outcome),
Err(e) => {
match rollback {
Rollback::State(Some(sha)) if !store.stealth => {
let _ = git::git_reset_hard(&store.state_worktree_dir(), sha);
}
Rollback::State(_) => {}
Rollback::DropClaim => {
let _ = crate::worktree::drop_worktree(store, &task.id, true);
}
}
Err(e)
}
}
}
#[cfg(test)]
#[path = "consume_tests.rs"]
mod tests;