use crate::conf;
use crate::converge;
use crate::layout::Xdg;
use crate::substrate;
use std::fs;
use std::path::PathBuf;
use tempfile::TempDir;
fn clone(tmp: &TempDir) -> crate::layout::CloneDir {
let xdg = Xdg::with(tmp.path(), None, Some(&tmp.path().join("state").to_string_lossy()));
xdg.clone_dir(&tmp.path().join("proj"))
}
fn founded(tmp: &TempDir) -> (crate::layout::CloneDir, PathBuf) {
let clone = clone(tmp);
let xdg = Xdg::with(tmp.path(), None, Some(&tmp.path().join("state").to_string_lossy()));
let landing = clone.landing();
substrate::found_landing(&landing, &xdg, None, "tester").unwrap();
(clone, landing)
}
#[test]
fn a_clean_checkout_reports_nothing() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
assert_eq!(converge::debris(&clone, &landing).unwrap(), Vec::<String>::new());
}
#[test]
fn an_absent_changes_dir_is_not_an_error() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
assert!(!clone.root().join("changes").exists());
assert!(converge::debris(&clone, &landing).unwrap().is_empty());
}
#[test]
fn a_change_worktree_names_the_removal_command_conditioned_on_no_op_running() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
let orphan = clone.change("dead-uuid");
fs::create_dir_all(&orphan).unwrap();
let notes = converge::debris(&clone, &landing).unwrap();
assert_eq!(
notes,
vec![format!(
"change worktree {} (crash debris unless an op is running here right now — an op holds its change worktree for its whole run, a close for its whole gate): with none running, remove with `git worktree remove {}`",
orphan.display(),
orphan.display()
)]
);
assert!(orphan.exists(), "the report deletes nothing");
}
#[test]
fn a_change_worktree_is_never_called_orphaned_or_told_to_remove_unconditionally() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
fs::create_dir_all(clone.change("maybe-live")).unwrap();
let note = converge::debris(&clone, &landing).unwrap().remove(0);
assert!(!note.contains("orphan"), "prime cannot prove orphanhood: {note}");
assert!(!note.contains("teardown never ran"), "prime cannot prove the op concluded: {note}");
let (hedge, advice) = note.split_once("): ").expect("the hedge precedes the advice");
assert!(hedge.contains("unless an op is running here right now"), "the hedge names liveness: {hedge}");
assert!(advice.starts_with("with none running, remove with "), "advice is conditioned: {advice}");
}
#[test]
fn two_orphan_change_worktrees_each_get_their_own_line() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
fs::create_dir_all(clone.change("a")).unwrap();
fs::create_dir_all(clone.change("b")).unwrap();
assert_eq!(converge::debris(&clone, &landing).unwrap().len(), 2);
}
#[test]
fn a_changes_path_that_is_not_a_directory_surfaces_its_io_error() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
fs::write(clone.root().join("changes"), "").unwrap();
assert!(converge::debris(&clone, &landing).is_err());
}
#[test]
fn a_stealth_lock_with_stealth_undeclared_warns_without_claiming_a_publish() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
fs::write(clone.root().join("stealth.lock"), "").unwrap();
let notes = converge::debris(&clone, &landing).unwrap();
assert_eq!(
notes,
vec![format!(
"{} is retired and unread by the remote ladder — declare stealth with `bl conf set task-remote none`, then delete the file",
clone.root().join("stealth.lock").display()
)]
);
assert!(!notes[0].to_lowercase().contains("publish"), "core cannot see whether a remote resolves — never claim one happened");
}
#[test]
fn a_stealth_lock_is_suppressed_once_the_sentinel_already_declares_stealth() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
fs::write(clone.root().join("stealth.lock"), "").unwrap();
conf::declare_stealth(&landing, "tester").unwrap();
assert!(converge::debris(&clone, &landing).unwrap().is_empty(), "operator re-declared — the file is inert cruft, stay silent");
}
#[test]
fn an_absent_stealth_lock_is_silent_even_when_stealth_is_undeclared() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
assert!(!clone.root().join("stealth.lock").exists());
assert!(converge::debris(&clone, &landing).unwrap().is_empty());
}
#[test]
fn an_index_lock_in_the_landing_names_the_lock_and_the_removal() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
let lock = landing.join(".git").join("index.lock");
fs::write(&lock, "").unwrap();
let notes = converge::debris(&clone, &landing).unwrap();
assert_eq!(
notes,
vec![format!(
"git index lock {} blocks every commit in this landing, founding's `git add -A` included (crash debris unless an op is running here right now): with none running, remove with `rm {}`",
lock.display(),
lock.display()
)]
);
assert!(lock.exists(), "the report deletes nothing");
}
#[test]
fn an_absent_index_lock_is_silent() {
let tmp = TempDir::new().unwrap();
let (clone, landing) = founded(&tmp);
assert!(!landing.join(".git").join("index.lock").exists());
assert!(converge::debris(&clone, &landing).unwrap().is_empty());
}