use super::*;
use crate::test_support::{fixture, remove};
use crate::transaction_journal::RefFormat;
use std::path::Path;
fn layout(root: &Path) -> InvocationLayout {
return InvocationLayout {
symbolic_head: crate::transaction_journal::SymbolicHead::Branch(String::from("refs/heads/main")),
target_ref: String::from("refs/heads/main"),
conclusion: crate::transaction_journal::Conclusion::None,
repository_root: root.to_path_buf(),
git_dir: root.join(".git"),
common_dir: root.join(".git"),
real_index_path: root.join(".git/index"),
object_directory: root.join(".git/objects"),
registry_root: root.join(".git/cli-git-transactions"),
ref_format: RefFormat::Files,
object_format: String::from("sha1"),
empty_tree_oid: "4".repeat(40),
invoked_at: String::from("2026-10-11T00:00:00.000Z"),
};
}
#[test]
fn publication_creates_an_owned_directory_and_derives_the_paths() {
let root: PathBuf = fixture("workspace-publish");
std::fs::create_dir_all(root.join(".git")).expect("git dir");
let mut workspace: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("workspace");
let id: &str = workspace.landing.transaction_id.as_str();
assert_eq!(workspace.landing.directory, root.join(".git/cli-git-transactions").join(id));
assert!(workspace.landing.directory.join("owner.json").exists());
assert_eq!(workspace.landing.commit_index, workspace.landing.directory.join("commit.index"));
assert_eq!(workspace.landing.captured_index, workspace.landing.directory.join("captured.index"));
assert_eq!(workspace.landing.shadow, root.join(".git/cli-git/shadow").join(id));
assert_eq!(workspace.object_directory, workspace.landing.shadow.join("objects"));
assert_eq!(workspace.hooks_directory, workspace.landing.directory.join("hooks"));
assert!(!workspace.landing.preserved);
assert_eq!(workspace.git_dir(), root.join(".git"));
assert_eq!(workspace.registry_root(), root.join(".git/cli-git-transactions"));
workspace.dispose().expect("dispose");
remove(root.as_path());
}
#[test]
fn every_workspace_has_its_own_identity() {
let root: PathBuf = fixture("workspace-unique");
std::fs::create_dir_all(root.join(".git")).expect("git dir");
let first: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("first");
let second: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("second");
assert_ne!(first.landing.transaction_id, second.landing.transaction_id);
assert_ne!(first.landing.directory, second.landing.directory);
remove(root.as_path());
}
#[test]
fn disposal_removes_unless_a_landing_record_handed_the_directory_to_recovery() {
let root: PathBuf = fixture("workspace-dispose");
std::fs::create_dir_all(root.join(".git")).expect("git dir");
let mut removed: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("removed");
std::fs::create_dir_all(removed.landing.shadow.as_path()).expect("shadow");
removed.dispose().expect("dispose");
assert!(!removed.landing.directory.exists());
assert!(!removed.landing.shadow.exists());
removed.dispose().expect("a later call does nothing");
let mut kept: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("kept");
std::fs::create_dir_all(kept.landing.shadow.as_path()).expect("shadow");
kept.landing.preserved = true;
kept.dispose().expect("dispose");
assert!(kept.landing.directory.exists());
assert!(kept.landing.shadow.exists());
let mut finished: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("finished");
finished.landing.preserved = true;
finished.finish_transaction();
assert!(!finished.landing.preserved);
finished.dispose().expect("dispose");
assert!(!finished.landing.directory.exists());
let mut handed: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("handed");
handed.mark_disposed();
handed.dispose().expect("dispose");
assert!(handed.landing.directory.exists(), "a workspace marked disposed removes nothing again");
let directory: PathBuf = {
let dropped: CommitWorkspace = create_commit_workspace(&layout(root.as_path())).expect("dropped");
dropped.landing.directory.clone()
};
assert!(!directory.exists());
remove(root.as_path());
}
#[test]
fn each_failure_displays_its_own_words() {
assert_eq!(
WorkspaceError::Registry(crate::recovery_error::RecoveryError(String::from("registry words"))).to_string(),
"registry words"
);
assert_eq!(WorkspaceError::Random(String::from("random words")).to_string(), "random words");
let identity: String = WorkspaceError::Identity(crate::process_identity::ProcessIdentityError::MalformedStat { pid: 7 }).to_string();
assert!(identity.contains("MalformedStat") && identity.contains('7'), "{identity}");
}