use super::drain;
use crate::prompt::Error;
use crate::prompt::inbox;
use crate::template::GitRunner;
use crate::workspace;
use std::path::Path;
#[derive(Debug, PartialEq, Eq)]
#[cfg(test)] pub enum DriveOutcome {
AlreadyDriven,
NothingToDeliver,
Delivered(usize),
}
#[cfg(test)] pub fn drive(workspace: &Path, agent_id: &str, git: &dyn GitRunner) -> Result<DriveOutcome, Error> {
let inbox_dir = inbox::inbox_dir(workspace, agent_id);
let Some(_lock) = inbox::try_acquire(&inbox_dir).map_err(|source| Error::ExecutorLock {
path: inbox_dir.clone(),
source,
})?
else {
return Ok(DriveOutcome::AlreadyDriven);
};
match deliver(workspace, agent_id, git)? {
0 => Ok(DriveOutcome::NothingToDeliver),
n => Ok(DriveOutcome::Delivered(n)),
}
}
pub(super) fn deliver(
workspace: &Path,
agent_id: &str,
git: &dyn GitRunner,
) -> Result<usize, Error> {
let inbox_dir = inbox::inbox_dir(workspace, agent_id);
let pending = drain::pending(&inbox_dir)?.len();
let worktree = workspace::agent_worktree(workspace, agent_id);
if !worktree.exists() {
if pending == 0 {
return Ok(0);
}
rematerialize(workspace, agent_id, &worktree, git)?;
}
drain::drain(&worktree, &inbox_dir, agent_id, git)?;
Ok(pending)
}
fn rematerialize(
workspace: &Path,
agent_id: &str,
worktree: &Path,
git: &dyn GitRunner,
) -> Result<(), Error> {
let wt_str = worktree.to_string_lossy().to_string();
let branch_ref = workspace::agent_ref(agent_id);
git.run(
&workspace::repo_git(workspace),
&["worktree", "add", wt_str.as_str(), branch_ref.as_str()],
)
.map_err(|source| Error::Git {
op: "worktree add (rematerialize)",
source,
})
}
#[cfg(test)]
mod tests;