use gitks::bare::GitBare; use gitks::server::GitksService; #[allow(dead_code)] pub fn setup_service(dir: &std::path::Path) -> GitksService { GitksService::new(dir.to_path_buf()) } pub fn run_git(work_dir: &std::path::Path, args: &[&str]) -> duct::Expression { duct::cmd("git", { let work_str = work_dir.to_string_lossy().into_owned(); let mut v: Vec = vec!["-C".into(), work_str]; v.extend(args.iter().map(|s| s.to_string())); v }) .env("GIT_AUTHOR_NAME", "Test") .env("GIT_AUTHOR_EMAIL", "test@example.com") .env("GIT_COMMITTER_NAME", "Test") .env("GIT_COMMITTER_EMAIL", "test@example.com") } pub fn run(work_dir: &std::path::Path, args: &[&str]) { let result = run_git(work_dir, args) .stdout_capture() .stderr_capture() .unchecked() .run() .unwrap(); assert!( result.status.success(), "git {} failed: {}", args.join(" "), String::from_utf8_lossy(&result.stderr) ); } pub fn setup_bare_repo() -> (tempfile::TempDir, GitBare) { let dir = tempfile::tempdir().expect("create temp dir"); let bare_dir = dir.path().join("test-repo"); duct::cmd( "git", ["init", "--bare", bare_dir.to_string_lossy().as_ref()], ) .run() .expect("git init --bare"); let work_dir = dir.path().join("work"); duct::cmd( "git", [ "clone", bare_dir.to_string_lossy().as_ref(), work_dir.to_string_lossy().as_ref(), ], ) .run() .expect("clone"); run(&work_dir, &["checkout", "-b", "main"]); std::fs::write(work_dir.join("README.md"), "# Test\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "initial commit"]); run(&work_dir, &["branch", "feature"]); std::fs::write(work_dir.join("src.txt"), "source\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "second commit"]); std::fs::write(work_dir.join("README.md"), "# Test\n\nUpdated.\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "third commit"]); std::fs::create_dir_all(work_dir.join("src/lib")).unwrap(); std::fs::write(work_dir.join("src/lib/mod.rs"), "pub fn hello() {}\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "add nested file"]); run(&work_dir, &["tag", "v0.1.0"]); run( &work_dir, &["push", "-f", "origin", "main:main", "feature:feature"], ); run( &work_dir, &["push", "-f", "origin", "refs/tags/v0.1.0:refs/tags/v0.1.0"], ); duct::cmd( "git", [ "--git-dir", bare_dir.to_string_lossy().as_ref(), "symbolic-ref", "HEAD", "refs/heads/main", ], ) .run() .expect("set HEAD to main"); (dir, GitBare::new(bare_dir)) } #[allow(dead_code)] pub fn setup_bare_repo_with_conflict() -> (tempfile::TempDir, GitBare) { let dir = tempfile::tempdir().expect("create temp dir"); let bare_dir = dir.path().join("test-repo"); duct::cmd( "git", ["init", "--bare", bare_dir.to_string_lossy().as_ref()], ) .run() .expect("git init --bare"); let work_dir = dir.path().join("work"); duct::cmd( "git", [ "clone", bare_dir.to_string_lossy().as_ref(), work_dir.to_string_lossy().as_ref(), ], ) .run() .expect("clone"); run(&work_dir, &["checkout", "-b", "main"]); std::fs::write(work_dir.join("file.txt"), "base content\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "base commit"]); run(&work_dir, &["checkout", "-b", "branch-a"]); std::fs::write(work_dir.join("file.txt"), "branch A content\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "branch A change"]); run(&work_dir, &["checkout", "main"]); run(&work_dir, &["checkout", "-b", "branch-b"]); std::fs::write(work_dir.join("file.txt"), "branch B content\n").unwrap(); run(&work_dir, &["add", "."]); run(&work_dir, &["commit", "-m", "branch B change"]); run( &work_dir, &[ "push", "-f", "origin", "main:main", "branch-a:branch-a", "branch-b:branch-b", ], ); duct::cmd( "git", [ "--git-dir", bare_dir.to_string_lossy().as_ref(), "symbolic-ref", "HEAD", "refs/heads/main", ], ) .run() .expect("set HEAD to main"); (dir, GitBare::new(bare_dir)) }