use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};
use argonauts_core::TaskId;
use argonauts_core::layout;
use argonauts_core::paths::create_private_dir_all;
use crate::engine::host::Host;
use crate::error::EngineResult;
use crate::git::{Claims, Git, LeftOut};
use crate::task::claims;
use crate::task::worktree::{self, TaskTree};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct TaskChange {
pub base: String,
pub files: Vec<String>,
pub diff: String,
pub left_out: Vec<LeftOut>,
}
impl TaskChange {
pub fn is_empty(&self) -> bool {
self.files.is_empty()
}
}
pub async fn of_task(host: &Host, task: &TaskId) -> EngineResult<TaskChange> {
let reading = Reading::of(host, task).await?;
let change = reading
.git
.change_since(
&reading.tree.path,
&reading.tree.base,
&reading.index,
&reading.commits,
reading.claims.as_ref(),
)
.await?;
Ok(TaskChange {
base: reading.tree.base,
files: change.files,
diff: change.diff,
left_out: change.left_out,
})
}
pub async fn commit_of_task(host: &Host, task: &TaskId) -> EngineResult<String> {
let reading = Reading::of(host, task).await?;
Ok(reading
.git
.commit_of_change(
&reading.tree.path,
&reading.index,
&reading.commits,
reading.claims.as_ref(),
)
.await?)
}
struct Reading {
tree: TaskTree,
git: Git,
claims: Option<Claims>,
commits: Vec<String>,
index: PathBuf,
}
impl Reading {
async fn of(host: &Host, task: &TaskId) -> EngineResult<Self> {
let tree = worktree::ensure(host, task).await?;
let git = worktree::tree_git(host, &tree.path).await?;
let claims = claims::of_task(host, task, &tree.path);
let engine = worktree::conductor_commits(host, task)?;
let commits: Vec<String> = git
.first_parent_log(&tree.path, &format!("{}..HEAD", tree.base))
.await?
.into_iter()
.map(|(sha, _)| sha)
.filter(|sha| !engine.contains(sha))
.collect();
let dir = layout::task_dir(&host.repo().run_dir, task);
create_private_dir_all(&dir)?;
let index = dir.join(format!("change-{}.index", next_index()));
Ok(Self {
tree,
git,
claims,
commits,
index,
})
}
}
fn next_index() -> u64 {
static NEXT: AtomicU64 = AtomicU64::new(0);
NEXT.fetch_add(1, Ordering::Relaxed)
}