use super::*;
use crate::subvolume_arguments::MigrateMode;
use crate::subvolume_test_support::{PlainPlatform, checkout_with_worktree, migrate_arguments, run_command};
use crate::test_support::remove;
const DONE: i32 = 0;
fn names(directory: &Path) -> Vec<String> {
let mut found: Vec<String> = std::fs::read_dir(directory).expect("listing").flatten().map(|item| { return item.file_name().to_string_lossy().into_owned(); }).collect();
found.sort();
return found;
}
#[test]
fn a_second_command_on_one_checkout_is_refused_whatever_its_mode() {
let (parent, root) = checkout_with_worktree("ownership-second-command");
let platform: PlainPlatform = PlainPlatform::new();
let mut inner: Vec<(MigrateMode, i32, Vec<String>)> = Vec::new();
let mut outer_lines: Vec<String> = Vec::new();
let outer_code: i32 = execute(&platform, &migrate_arguments(), root.as_path(), &Interrupt::never(), &mut |text: &str| {
outer_lines.push(text.to_string());
if inner.is_empty() && text.starts_with("checkout ") {
for mode in [MigrateMode::Migrate, MigrateMode::Rollback, MigrateMode::RemoveOld] {
let arguments: MigrateArguments = MigrateArguments { mode, ..migrate_arguments() };
let (code, lines) = run_command(&platform, &arguments, root.as_path(), &Interrupt::never());
inner.push((mode, code, lines));
}
}
});
assert_eq!(inner.len(), 3, "the second commands ran while the first announced");
for (mode, code, lines) in &inner {
let text: String = lines.join("\n");
assert_eq!(*code, REFUSED_EXIT_CODE, "{mode:?}: {text}");
assert!(text.contains(format!("process {}", std::process::id()).as_str()) && text.contains("Nothing was changed."), "{mode:?}: {text}");
}
assert_eq!(outer_code, DONE, "{outer_lines:#?}");
remove(parent.as_path());
}
#[test]
fn a_preview_leaves_no_claim_behind() {
let (parent, root) = checkout_with_worktree("ownership-preview");
let before: Vec<String> = names(parent.as_path());
let arguments: MigrateArguments = MigrateArguments { dry_run: true, ..migrate_arguments() };
let (code, lines) = run_command(&PlainPlatform::new(), &arguments, root.as_path(), &Interrupt::never());
assert_eq!(code, DONE, "{lines:#?}");
assert_eq!(names(parent.as_path()), before);
remove(parent.as_path());
}
#[test]
fn a_migration_is_refused_while_a_worktree_is_being_converted() {
use crate::process_identity::process_birth_identity;
use crate::single_owner_claim::plant_claim_for_tests;
use crate::worktree_convert_journal::CLAIM_PREFIX;
let (parent, root) = checkout_with_worktree("ownership-conversion-running");
let mut conversion: std::process::Child = crate::test_support::spawn_owned(std::process::Command::new("sleep").arg("30")).expect("sleep");
let pid: i64 = i64::from(conversion.id());
let birth: String = process_birth_identity(pid).expect("identity").expect("alive");
plant_claim_for_tests(root.join(".git/worktrees/wt").as_path(), std::ffi::OsStr::new(CLAIM_PREFIX), 1, pid, birth.as_str());
let before: Vec<String> = names(parent.as_path());
let (code, lines) = run_command(&PlainPlatform::new(), &migrate_arguments(), root.as_path(), &Interrupt::never());
let text: String = lines.join("\n");
assert_eq!(code, REFUSED_EXIT_CODE, "{text}");
assert!(text.contains(format!("process {pid}").as_str()) && text.contains("Nothing was changed."), "{text}");
let created: Vec<String> = names(parent.as_path()).into_iter().filter(|name: &String| { return !before.contains(name) && !name.starts_with(".cli-git-migrate-checkout.owner."); }).collect();
assert_eq!(created, Vec::<String>::new(), "nothing was created beside the checkout");
conversion.kill().expect("kill");
conversion.wait().expect("wait");
remove(parent.as_path());
}