use super::*;
use crate::fs_btrfs_test_support::btrfs_fixture;
use crate::fs_kind::{BTRFS_SUBVOLUME_ROOT_INODE, is_subvolume_root};
use crate::test_support::{fixture, git, git_output, remove, repository};
use std::os::unix::fs::MetadataExt;
use std::process::Output;
fn plan_for(destination: PathBuf) -> AddPlan {
return AddPlan { destination, insert_at: 2, quiet: false };
}
#[test]
fn btrfs_a_missing_destination_becomes_an_empty_subvolume_and_settles_away() {
let Some(root) = btrfs_fixture("worktree-subvolume-create") else { return };
let plan: AddPlan = plan_for(root.join("topic"));
let created: CreatedSubvolume = prepare_subvolume_destination(&plan).expect("a subvolume is created");
assert_eq!(created.path, plan.destination);
assert!(is_subvolume_root(plan.destination.as_path()).expect("probe"));
assert_eq!(std::fs::metadata(plan.destination.as_path()).expect("metadata").ino(), BTRFS_SUBVOLUME_ROOT_INODE);
settle_subvolume_destination(&created);
assert!(!plan.destination.exists(), "an empty subvolume is removed");
remove(root.as_path());
}
#[test]
fn btrfs_an_existing_or_unplaceable_destination_is_left_to_git() {
let Some(root) = btrfs_fixture("worktree-subvolume-existing") else { return };
std::fs::create_dir(root.join("empty")).expect("empty directory");
std::fs::create_dir(root.join("full")).expect("full directory");
std::fs::write(root.join("full/file"), b"x").expect("file");
std::os::unix::fs::symlink(root.join("full"), root.join("link")).expect("link");
for name in ["empty", "full", "link"] {
assert_eq!(prepare_subvolume_destination(&plan_for(root.join(name))), None, "{name}");
}
assert!(!is_subvolume_root(root.join("empty").as_path()).expect("probe"), "the existing directory is untouched");
assert_eq!(prepare_subvolume_destination(&plan_for(root.join("absent/topic"))), None);
assert!(!root.join("absent").exists());
remove(root.as_path());
}
#[test]
fn btrfs_a_filled_destination_is_not_removed() {
let Some(root) = btrfs_fixture("worktree-subvolume-filled") else { return };
let plan: AddPlan = plan_for(root.join("topic"));
let created: CreatedSubvolume = prepare_subvolume_destination(&plan).expect("created");
std::fs::write(plan.destination.join(".git"), b"gitdir: elsewhere\n").expect("a file Git wrote");
settle_subvolume_destination(&created);
assert!(plan.destination.join(".git").is_file());
std::fs::remove_file(plan.destination.join(".git")).expect("empty it");
std::fs::remove_dir(plan.destination.as_path()).expect("remove it");
settle_subvolume_destination(&created);
remove(root.as_path());
}
#[test]
fn creation_happens_exactly_when_the_parent_is_on_btrfs() {
let root: PathBuf = fixture("worktree-subvolume-kind");
let on_btrfs: bool = filesystem_kind(root.as_path()) == Ok(FilesystemKind::Btrfs);
let created: Option<CreatedSubvolume> = prepare_subvolume_destination(&plan_for(root.join("topic")));
assert_eq!(created.is_some(), on_btrfs);
assert_eq!(root.join("topic").exists(), on_btrfs);
if let Some(found) = created {
settle_subvolume_destination(&found);
}
remove(root.as_path());
}
#[test]
fn btrfs_real_git_fills_the_subvolume_and_removes_it() {
let Some(root) = btrfs_fixture("worktree-subvolume-git") else { return };
let repo: PathBuf = repository(root.as_path(), "repo");
std::fs::write(repo.join("tracked.txt"), b"tracked\n").expect("tracked file");
git(repo.as_path(), &["add", "tracked.txt"]);
git(repo.as_path(), &["commit", "--quiet", "--message=tracked"]);
let plan: AddPlan = plan_for(root.join("wt"));
let created: CreatedSubvolume = prepare_subvolume_destination(&plan).expect("created");
git(repo.as_path(), &["worktree", "add", "--quiet", "-b", "topic", "../wt"]);
settle_subvolume_destination(&created);
assert!(is_subvolume_root(plan.destination.as_path()).expect("probe"), "Git filled the subvolume in place");
assert_eq!(std::fs::read(plan.destination.join("tracked.txt")).expect("checked out"), b"tracked\n");
git(repo.as_path(), &["worktree", "remove", "../wt"]);
assert!(!plan.destination.exists());
remove(root.as_path());
}
#[test]
fn btrfs_a_failed_git_leaves_nothing_after_settling() {
let Some(root) = btrfs_fixture("worktree-subvolume-failed") else { return };
let repo: PathBuf = repository(root.as_path(), "repo");
git(repo.as_path(), &["branch", "taken"]);
let plan: AddPlan = plan_for(root.join("wt"));
let created: CreatedSubvolume = prepare_subvolume_destination(&plan).expect("created");
let failed: Output = git_output(repo.as_path(), &["worktree", "add", "-b", "taken", "../wt"]);
assert!(!failed.status.success());
assert!(plan.destination.exists(), "Git itself leaves the destination it did not create");
settle_subvolume_destination(&created);
assert!(!plan.destination.exists());
remove(root.as_path());
}