#![cfg(unix)]
use super::*;
use crate::bounded_push::STOP_GRACE;
use crate::stale_ref_lock_killed_git as killed;
use crate::stale_ref_lock_killed_git::{Held, Stage};
use crate::test_support::scratch_environment;
use std::time::Duration;
const PATIENCE: Patience = Patience::Fixed(Duration::from_secs(120));
const TRACKING: &str = "refs/remotes/origin/main";
fn run(stage: &Stage, arguments: &[&str], judge: &Judge) -> PushAttempt {
let command: Command = killed::plain_git(stage, arguments);
return run_clearing_locks(command, PATIENCE, STOP_GRACE, scratch_environment().as_slice(), judge).expect("the run");
}
#[test]
fn a_push_runs_after_the_lock_of_a_killed_push_is_cleared() {
let stage: Stage = killed::stage("push-clearing-killed-push", true);
let mut held: Held = killed::hold_push(&stage);
assert!(stage.lock_of(TRACKING).exists(), "the push holds the tracking reference");
held.kill();
let _removed = std::fs::remove_file(stage.git_dir.join("hooks").join("reference-transaction"));
let attempt: PushAttempt = run(&stage, &["push", "--quiet", "origin", "main"], &killed::judge());
assert_eq!(attempt.exit_code, 0, "{}", attempt.output);
assert!(!stage.lock_of(TRACKING).exists());
stage.finish();
}
#[test]
fn a_failed_push_carries_the_notice_of_the_lock_it_could_not_clear() {
let stage: Stage = killed::stage("push-clearing-unproven", true);
let mut held: Held = killed::hold_push(&stage);
held.kill();
let _removed = std::fs::remove_file(stage.git_dir.join("hooks").join("reference-transaction"));
let partial: Judge = Judge { pid_view_complete: false, ..killed::judge() };
let attempt: PushAttempt = run(&stage, &["push", "--quiet", "origin", "main"], &partial);
assert!(attempt.output.contains("cannot lock ref"), "Git's own refusal stays: {}", attempt.output);
assert!(attempt.output.contains("cli-git: left the reference lock"), "{}", attempt.output);
assert!(attempt.output.contains(&format!("rm -- {} ", stage.lock_of(TRACKING).display())), "{}", attempt.output);
assert!(stage.lock_of(TRACKING).exists());
stage.finish();
}
#[test]
fn a_successful_run_adds_no_words() {
let stage: Stage = killed::stage("push-clearing-silent", true);
let mut held: Held = killed::hold_fetch(&stage);
held.kill();
let _removed = std::fs::remove_file(stage.git_dir.join("hooks").join("reference-transaction"));
let attempt: PushAttempt = run(&stage, &["fetch", "--prune", "--quiet", "origin"], &killed::judge());
assert_eq!(attempt.exit_code, 0, "{}", attempt.output);
assert_eq!(attempt.output, "");
stage.finish();
}