#![cfg(unix)]
use super::tests::{project, tip};
use super::*;
use crate::delivery::Repo;
use std::os::unix::fs::PermissionsExt;
fn install_hook(root: &Path, script: &str, mode: u32) {
let hook = root.join(".git/hooks/pre-commit");
fs::write(&hook, script).unwrap();
fs::set_permissions(&hook, fs::Permissions::from_mode(mode)).unwrap();
}
#[test]
fn a_passing_gate_delivers_and_runs_in_the_worktree() {
let (tmp, root, p) = project();
let wt = tmp.path().join("wt");
p.materialize(&wt, "work/bl-x").unwrap();
fs::write(wt.join("feature.txt"), "shipped\n").unwrap();
install_hook(&root, "#!/bin/sh\ntest -f feature.txt\n", 0o755);
p.deliver(&wt, "work/bl-x", "main", "Add feature [bl-x]", "[bl-x]").unwrap();
assert_eq!(tip(&root), "Add feature [bl-x]");
}
#[test]
fn a_failing_gate_aborts_the_delivery_before_integration_moves() {
let (tmp, root, p) = project();
let wt = tmp.path().join("wt");
p.materialize(&wt, "work/bl-x").unwrap();
fs::write(wt.join("feature.txt"), "broken\n").unwrap();
install_hook(&root, "#!/bin/sh\nexit 1\n", 0o755);
let err = p.deliver(&wt, "work/bl-x", "main", "Add feature [bl-x]", "[bl-x]").unwrap_err();
assert!(err.to_string().contains("delivery gate"), "{err}");
assert_eq!(tip(&root), "seed"); let subject = Project::run(&root, &["log", "-1", "--format=%s", "work/bl-x"]).unwrap();
assert_eq!(subject.trim(), "Add feature [bl-x]");
}
#[test]
fn a_non_executable_hook_is_ignored_gits_rule() {
let (tmp, root, p) = project();
let wt = tmp.path().join("wt");
p.materialize(&wt, "work/bl-x").unwrap();
fs::write(wt.join("feature.txt"), "shipped\n").unwrap();
install_hook(&root, "#!/bin/sh\nexit 1\n", 0o644);
p.deliver(&wt, "work/bl-x", "main", "Add feature [bl-x]", "[bl-x]").unwrap();
assert_eq!(tip(&root), "Add feature [bl-x]");
}
#[test]
fn the_gate_checks_the_reintegrated_tree_when_integration_moved() {
let (tmp, root, p) = project();
let wt = tmp.path().join("wt");
p.materialize(&wt, "work/bl-x").unwrap();
fs::write(wt.join("feature.txt"), "shipped\n").unwrap();
fs::write(root.join("late.txt"), "landed meanwhile\n").unwrap();
Project::run(&root, &["add", "-A"]).unwrap();
Project::run(&root, &["commit", "-qm", "late main edit"]).unwrap();
install_hook(&root, "#!/bin/sh\ntest -f feature.txt && test -f late.txt\n", 0o755);
p.deliver(&wt, "work/bl-x", "main", "Add feature [bl-x]", "[bl-x]").unwrap();
assert_eq!(tip(&root), "Add feature [bl-x]");
assert_eq!(Project::run(&root, &["show", "main:late.txt"]).unwrap(), "landed meanwhile\n");
assert_eq!(Project::run(&root, &["rev-list", "--count", "main"]).unwrap().trim(), "3");
}
#[test]
fn a_reintegration_that_dissolves_the_diff_skips_gate_and_squash() {
let (tmp, root, p) = project();
let wt = tmp.path().join("wt");
p.materialize(&wt, "work/bl-x").unwrap();
fs::write(wt.join("feature.txt"), "same\n").unwrap();
Project::run(&wt, &["add", "-A"]).unwrap();
Project::run(&wt, &["commit", "-qm", "work copy"]).unwrap();
fs::write(root.join("feature.txt"), "same\n").unwrap();
fs::write(root.join("late.txt"), "more\n").unwrap();
Project::run(&root, &["add", "-A"]).unwrap();
Project::run(&root, &["commit", "-qm", "already landed"]).unwrap();
install_hook(&root, "#!/bin/sh\nexit 1\n", 0o755);
p.deliver(&wt, "work/bl-x", "main", "dup [bl-x]", "[bl-x]").unwrap();
assert_eq!(tip(&root), "already landed"); }
#[test]
fn deliver_rematerializes_an_absent_worktree_to_gate_in() {
let (tmp, root, p) = project();
let wt = tmp.path().join("wt");
p.materialize(&wt, "work/bl-x").unwrap();
fs::write(wt.join("feature.txt"), "shipped\n").unwrap();
Project::run(&wt, &["add", "-A"]).unwrap();
Project::run(&wt, &["commit", "-qm", "wip"]).unwrap();
p.release(&wt).unwrap(); install_hook(&root, "#!/bin/sh\ntest -f feature.txt\n", 0o755);
p.deliver(&wt, "work/bl-x", "main", "Add feature [bl-x]", "[bl-x]").unwrap();
assert_eq!(tip(&root), "Add feature [bl-x]");
assert!(wt.exists()); }