use tempfile::TempDir;
use super::manager::SessionManager;
use super::record::ManagedSessionId;
use super::tests::FakeTmuxDriver;
#[tokio::test]
async fn reap_orphaned_worktrees_removes_orphan_preserves_live() {
let store_dir = TempDir::new().unwrap();
let repos = TempDir::new().unwrap();
let mgr = SessionManager::new(store_dir.path(), FakeTmuxDriver::new())
.await
.expect("manager");
let wt_root = repos.path().join("owner").join("repo").join(".worktrees");
let live_wt = wt_root.join("live-session");
let orphan_wt = wt_root.join("orphan-session");
std::fs::create_dir_all(&live_wt).unwrap();
std::fs::create_dir_all(&orphan_wt).unwrap();
let aged = chrono::Utc::now()
- super::worktree_ownership::OWNERLESS_GRACE
- chrono::Duration::minutes(1);
std::fs::write(
orphan_wt.join(super::decommission::WORKTREE_SENTINEL_FILE),
serde_json::to_vec(&super::worktree_ownership::WorktreeSentinel {
owner_session_id: ManagedSessionId::new(),
created_at: aged,
})
.expect("serialize aged sentinel"),
)
.expect("write ownerless sentinel");
let _record = mgr
.create_with_id(
ManagedSessionId::new(),
"task".into(),
Some(live_wt.clone()),
None,
Some(live_wt.clone()),
None,
None,
crate::runtime::RuntimeKind::default(),
false,
false,
)
.await
.expect("create live record");
let outcome = mgr
.reap_orphaned_worktrees(repos.path())
.await
.expect("reap must not error");
let removed = outcome.removed;
assert!(
!orphan_wt.exists(),
"orphaned worktree dir must be removed by the auto-reaper (#1838)"
);
assert!(
live_wt.exists(),
"live session worktree must be preserved by the auto-reaper (#1838)"
);
assert!(
removed.iter().any(|p| p.ends_with("orphan-session")),
"removed set must include the orphan; got {removed:?}"
);
assert!(
!removed.iter().any(|p| p.ends_with("live-session")),
"removed set must NOT include the live worktree; got {removed:?}"
);
assert!(
outcome.owner_unknown.is_empty(),
"no owner-unknown candidates expected in this fixture; got {:?}",
outcome.owner_unknown
);
}