use std::path::Path;
use std::process::Command;
use std::sync::Arc;
use lds_core::{Session, SessionConfig};
use lds_git::GitModule;
fn init_temp_repo(dir: &Path) {
let run = |args: &[&str]| {
Command::new("git")
.args(args)
.current_dir(dir)
.output()
.unwrap();
};
run(&["init", "-b", "main"]);
run(&["config", "user.email", "test@test.com"]);
run(&["config", "user.name", "Test"]);
std::fs::write(dir.join("README.md"), "init\n").unwrap();
run(&["add", "."]);
run(&["commit", "-m", "initial"]);
std::fs::create_dir_all(dir.join(".worktrees")).unwrap();
}
fn make_session(root: &Path) -> Arc<Session> {
Arc::new(
Session::new(SessionConfig {
root: root.to_path_buf(),
timeout_secs: Some(30),
..Default::default()
})
.unwrap(),
)
}
#[test]
fn worktree_lifecycle() {
let tmp = tempfile::tempdir().unwrap();
init_temp_repo(tmp.path());
let session = make_session(tmp.path());
let mut git = GitModule::new(session);
let list = git.worktree_list().unwrap();
assert!(list.contains("owned: false"));
let result = git
.worktree_add("test-wt", "feat/test", Some("main"))
.unwrap();
assert!(result.contains("worktree created"));
assert!(result.contains("feat/test"));
let list = git.worktree_list().unwrap();
assert!(list.contains("owned: true"));
let wt_path = tmp.path().join(".worktrees/test-wt");
std::fs::write(wt_path.join("new_file.txt"), "content\n").unwrap();
let commit_result = git.commit(&wt_path, "test commit", None).unwrap();
assert!(commit_result.contains("committed"));
assert!(commit_result.contains("files_changed=1"));
let merge_result = git.merge("feat/test", "main", tmp.path()).unwrap();
assert!(merge_result.contains("merged"));
let remove_result = git.worktree_remove("test-wt").unwrap();
assert!(remove_result.contains("worktree removed"));
let delete_result = git.branch_delete("feat/test").unwrap();
assert!(delete_result.contains("branch deleted"));
assert!(tmp.path().join("new_file.txt").exists());
let log = git.log(5).unwrap();
assert!(log.contains("Merge branch"));
}
#[test]
fn ownership_guard_rejects_unowned_worktree() {
let tmp = tempfile::tempdir().unwrap();
init_temp_repo(tmp.path());
let session = make_session(tmp.path());
let git = GitModule::new(session);
Command::new("git")
.args([
"worktree",
"add",
"-b",
"other/branch",
tmp.path().join(".worktrees/foreign").to_str().unwrap(),
"main",
])
.current_dir(tmp.path())
.output()
.unwrap();
let foreign_path = tmp.path().join(".worktrees/foreign");
std::fs::write(foreign_path.join("file.txt"), "x").unwrap();
let err = git.commit(&foreign_path, "bad commit", None);
assert!(err.is_err());
assert!(
err.unwrap_err()
.to_string()
.contains("not owned by this session")
);
let err = git.branch_delete("other/branch");
assert!(err.is_err());
assert!(
err.unwrap_err()
.to_string()
.contains("not owned by this session")
);
}
#[test]
fn commit_allowed_at_session_root() {
let tmp = tempfile::tempdir().unwrap();
init_temp_repo(tmp.path());
let session = make_session(tmp.path());
let git = GitModule::new(session);
std::fs::write(tmp.path().join("root_file.txt"), "content\n").unwrap();
let result = git.commit(
tmp.path(),
"root commit",
Some(&["root_file.txt".to_string()]),
);
assert!(result.is_ok());
assert!(result.unwrap().contains("committed"));
}