use std::path::Path;
use crate::files_view::Preview;
use crate::opslog::OpEntry;
use crate::workdiff::{Change, WorkFile, patch, read};
use super::{ball, snap, xdg};
const WS: &str = "/data/workspaces/storeroom";
const NAME: &str = "storeroom";
const BALL: &str = "bl-1";
fn trail(project: &Path, bindings: &[&Path]) -> Vec<OpEntry> {
let mut entries = vec![OpEntry {
argv: ["bl", "claim", BALL, "--as", NAME]
.map(str::to_owned)
.to_vec(),
cwd: project.to_string_lossy().into_owned(),
..OpEntry::default()
}];
for (i, binding) in bindings.iter().enumerate() {
entries.push(OpEntry {
argv: [
"lernie",
"prompt",
"--name",
&format!("conv-{i}"),
"--cwd",
&binding.to_string_lossy(),
]
.map(str::to_owned)
.to_vec(),
cwd: WS.to_owned(),
..OpEntry::default()
});
}
entries
}
fn work(worktree: &Path, file: &str) {
use crate::git_tree::tests::git::run_git;
std::fs::write(worktree.join(file), "fn f() {}\n").unwrap();
run_git(worktree, &["add", file]);
run_git(worktree, &["config", "user.email", "t@t.local"]);
run_git(worktree, &["config", "user.name", "Tester"]);
run_git(worktree, &["config", "commit.gpgsign", "false"]);
run_git(worktree, &["commit", "-q", "-m", "candidate work"]);
}
#[test]
fn candidates_read_at_the_ruled_range_and_wear_the_derived_mark() {
let project = super::Project::new();
let dir = tempfile::tempdir().unwrap();
let xdg = xdg(dir.path());
let obligation = crate::fan::Obligation {
project: "proj".to_owned(),
ball: Some(BALL.to_owned()),
};
let candidates = crate::fan::open(&obligation, &project.path, &xdg, 2).unwrap();
work(&candidates[0].worktree, "won.rs");
let entries = trail(
&project.path,
&[&candidates[0].worktree, &candidates[1].worktree],
);
let snap = snap(
Path::new(WS),
NAME,
&project.path,
vec![ball(BALL, Some(NAME), None)],
);
let attempts = read(&snap, Path::new(WS), &entries, &xdg);
assert_eq!(attempts.len(), 3, "{attempts:?}");
assert_eq!(attempts[0].handle, None);
let (worked, empty) = (&attempts[1], &attempts[2]);
assert_eq!(
worked.handle.as_deref(),
Some(candidates[0].handle.as_str())
);
assert_eq!(worked.ball_id, BALL);
assert_eq!(worked.project, snap.project_name(&project.path));
assert_eq!(
worked.range(),
Some(format!("work/{BALL}..attempt/{}", candidates[0].handle)),
);
let Change::Diff { files, .. } = &worked.change else {
panic!("a worked candidate diffs: {worked:?}");
};
assert_eq!(files.len(), 1);
assert_eq!(files[0].path, "won.rs");
assert_eq!(worked.delivered, None);
assert_eq!(empty.delivered, None);
let picked = WorkFile {
ball: BALL.to_owned(),
handle: Some(candidates[0].handle.clone()),
path: "won.rs".to_owned(),
};
let Some(Preview::Text(text)) = patch(&snap, &attempts, &picked) else {
panic!("a changed candidate file has a patch");
};
assert!(text.contains("+fn f() {}"), "{text}");
let delivery = crate::fan::deliver(
&obligation,
&project.path,
&xdg,
&candidates[0].handle,
"take it",
)
.unwrap();
let attempts = read(&snap, Path::new(WS), &entries, &xdg);
assert_eq!(attempts[1].delivered, delivery.commit);
assert_eq!(attempts[2].delivered, None);
}
#[test]
fn an_ordinary_claim_fire_is_no_candidate() {
let project = super::Project::new();
let dir = tempfile::tempdir().unwrap();
let xdg = xdg(dir.path());
let claim_worktree = dir.path().join("claim");
let entries = trail(&project.path, &[&claim_worktree]);
let snap = snap(
Path::new(WS),
NAME,
&project.path,
vec![ball(BALL, Some(NAME), None)],
);
let attempts = read(&snap, Path::new(WS), &entries, &xdg);
assert_eq!(attempts.len(), 1, "the claim row alone: {attempts:?}");
assert_eq!(attempts[0].handle, None);
}