use super::tests::{show, workspace, write_files};
use super::{Error, Origin, Pass, author};
use crate::template::{GitRunner, RealGit};
use crate::workspace::repo_git;
use std::io;
use std::path::Path;
fn has_ref(ws: &Path, name: &str) -> bool {
RealGit::new()
.run(
&repo_git(ws),
&[
"show-ref",
"--verify",
"--quiet",
&format!("refs/heads/config/{name}"),
],
)
.is_ok()
}
#[test]
fn a_no_op_edit_is_a_declined_pass_not_a_failure() {
let (holder, ws) = workspace();
let head = show(&ws, "config/default:version").unwrap();
let pass = author(
&ws,
&holder.path().join("no-pool"),
"default",
Origin::Advance,
write_files(&[]),
&RealGit::new(),
)
.unwrap();
assert_eq!(
pass,
Pass::Declined {
target: "config/default".to_string()
}
);
assert_eq!(show(&ws, "config/default:version").unwrap(), head);
assert!(!ws.join(".config-author").exists(), "checkout must be gone");
}
#[test]
fn a_declined_pass_leaves_the_verb_ready_for_an_immediate_re_author() {
let (holder, ws) = workspace();
let no_pool = holder.path().join("no-pool");
author(
&ws,
&no_pool,
"default",
Origin::Advance,
write_files(&[]),
&RealGit::new(),
)
.unwrap();
let pass = author(
&ws,
&no_pool,
"default",
Origin::Advance,
write_files(&[("providers.yaml", "roles: {second: 1}\n")]),
&RealGit::new(),
)
.unwrap();
assert_eq!(pass, Pass::Landed);
assert_eq!(
show(&ws, "config/default:providers.yaml").unwrap(),
"roles: {second: 1}"
);
}
#[test]
fn a_declined_fork_leaves_no_ref() {
let (holder, ws) = workspace();
let pass = author(
&ws,
&holder.path().join("no-pool"),
"stillborn",
Origin::Fork { source: "default" },
write_files(&[]),
&RealGit::new(),
)
.unwrap();
assert!(matches!(pass, Pass::Declined { .. }), "got {pass:?}");
assert!(!has_ref(&ws, "stillborn"), "declined fork left a ref");
assert!(!ws.join(".config-author").exists());
}
#[test]
fn a_failed_fork_leaves_neither_checkout_nor_ref() {
let (holder, ws) = workspace();
let err = author(
&ws,
&holder.path().join("no-pool"),
"doomed",
Origin::Fork { source: "default" },
|_dir: &Path| Err(io::Error::other("editor blew up")),
&RealGit::new(),
)
.unwrap_err();
assert!(matches!(err, Error::Edit(_)), "got {err:?}");
assert!(!has_ref(&ws, "doomed"), "failed fork left a ref");
assert!(!ws.join(".config-author").exists());
}
#[test]
fn a_failed_orphan_leaves_neither_checkout_nor_ref() {
let (holder, ws) = workspace();
let err = author(
&ws,
&holder.path().join("no-pool"),
"doomed",
Origin::Orphan,
|_dir: &Path| Err(io::Error::other("editor blew up")),
&RealGit::new(),
)
.unwrap_err();
assert!(matches!(err, Error::Edit(_)), "got {err:?}");
assert!(!has_ref(&ws, "doomed"), "failed orphan left a ref");
}
#[test]
fn a_killed_pass_leaves_debris_the_next_pass_heals() {
let (holder, ws) = workspace();
let no_pool = holder.path().join("no-pool");
RealGit::new()
.run(
&repo_git(&ws),
&[
"worktree",
"add",
&ws.join(".config-author").to_string_lossy(),
"config/default",
],
)
.unwrap();
std::fs::write(ws.join(".config-author/half-typed.yaml"), "oops").unwrap();
let pass = author(
&ws,
&no_pool,
"default",
Origin::Advance,
write_files(&[("providers.yaml", "roles: {healed: 1}\n")]),
&RealGit::new(),
)
.unwrap();
assert_eq!(pass, Pass::Landed);
assert_eq!(
show(&ws, "config/default:providers.yaml").unwrap(),
"roles: {healed: 1}"
);
assert!(show(&ws, "config/default:half-typed.yaml").is_err());
assert!(!ws.join(".config-author").exists());
}
#[test]
fn an_unremovable_checkout_path_surfaces_rather_than_wedging_silently() {
let (holder, ws) = workspace();
std::fs::write(ws.join(".config-author"), b"squat").unwrap();
let err = author(
&ws,
&holder.path().join("no-pool"),
"default",
Origin::Advance,
write_files(&[]),
&RealGit::new(),
)
.unwrap_err();
assert!(matches!(err, Error::Io(_)), "got {err:?}");
}