diff --git a/server/src/agents/gates.rs b/server/src/agents/gates.rs index bbdb8ff4..0d1fd43a 100644 --- a/server/src/agents/gates.rs +++ b/server/src/agents/gates.rs @@ -447,26 +447,35 @@ mod tests { use super::*; fn init_git_repo(repo: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(repo) - .output() - .unwrap(); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git") + .args(["init"]) + .current_dir(repo) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(repo) + .output(), + "git commit", + ); } // ── find_duplicate_module_files tests ──────────────────────── diff --git a/server/src/agents/lifecycle.rs b/server/src/agents/lifecycle.rs index 8261e596..26bbdc51 100644 --- a/server/src/agents/lifecycle.rs +++ b/server/src/agents/lifecycle.rs @@ -821,26 +821,35 @@ mod tests { // ── feature_branch_has_unmerged_changes tests ──────────────────────────── fn init_git_repo(repo: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(repo) - .output() - .unwrap(); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git") + .args(["init"]) + .current_dir(repo) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(repo) + .output(), + "git commit", + ); } /// Bug 226: feature_branch_has_unmerged_changes returns true when the diff --git a/server/src/agents/merge/squash/tests_advanced.rs b/server/src/agents/merge/squash/tests_advanced.rs index d331e1be..ec0ab3df 100644 --- a/server/src/agents/merge/squash/tests_advanced.rs +++ b/server/src/agents/merge/squash/tests_advanced.rs @@ -3,26 +3,35 @@ use super::*; use std::process::Command; fn init_git_repo(repo: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(repo) - .output() - .unwrap(); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git") + .args(["init"]) + .current_dir(repo) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(repo) + .output(), + "git commit", + ); } #[tokio::test] diff --git a/server/src/agents/merge/squash/tests_basic.rs b/server/src/agents/merge/squash/tests_basic.rs index 5a154d84..d6a850a7 100644 --- a/server/src/agents/merge/squash/tests_basic.rs +++ b/server/src/agents/merge/squash/tests_basic.rs @@ -3,26 +3,35 @@ use super::*; use std::process::Command; fn init_git_repo(repo: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(repo) - .output() - .unwrap(); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git") + .args(["init"]) + .current_dir(repo) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(repo) + .output(), + "git commit", + ); } #[tokio::test] diff --git a/server/src/agents/pool/pipeline/completion/tests.rs b/server/src/agents/pool/pipeline/completion/tests.rs index 8164bc4b..0fc04b79 100644 --- a/server/src/agents/pool/pipeline/completion/tests.rs +++ b/server/src/agents/pool/pipeline/completion/tests.rs @@ -6,26 +6,35 @@ use std::path::PathBuf; use std::process::Command; fn init_git_repo(repo: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(repo) - .output() - .unwrap(); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git") + .args(["init"]) + .current_dir(repo) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(repo) + .output(), + "git commit", + ); } // ── report_completion tests ──────────────────────────────────── diff --git a/server/src/agents/pool/pipeline/merge/tests.rs b/server/src/agents/pool/pipeline/merge/tests.rs index 425e463c..76d41036 100644 --- a/server/src/agents/pool/pipeline/merge/tests.rs +++ b/server/src/agents/pool/pipeline/merge/tests.rs @@ -34,26 +34,35 @@ fn serial_test_lock() -> std::sync::MutexGuard<'static, ()> { } fn init_git_repo(repo: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(repo) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(repo) - .output() - .unwrap(); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git") + .args(["init"]) + .current_dir(repo) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(repo) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(repo) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(repo) + .output(), + "git commit", + ); } // ── bug 498: stale Running job blocks retry ─────────────────────────────── diff --git a/server/src/agents/pool/worktree_lifecycle.rs b/server/src/agents/pool/worktree_lifecycle.rs index 2fb3fa1e..dd07773a 100644 --- a/server/src/agents/pool/worktree_lifecycle.rs +++ b/server/src/agents/pool/worktree_lifecycle.rs @@ -189,16 +189,32 @@ mod tests { use tempfile::TempDir; fn init_git_repo(dir: &Path) { - Command::new("git") - .args(["init"]) - .current_dir(dir) - .output() - .expect("git init"); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(dir) - .output() - .expect("git commit"); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git").args(["init"]).current_dir(dir).output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } fn setup_project(tmp: &TempDir) -> PathBuf { diff --git a/server/src/chat/commands/status/tests.rs b/server/src/chat/commands/status/tests.rs index 3c26730d..b3f2a03b 100644 --- a/server/src/chat/commands/status/tests.rs +++ b/server/src/chat/commands/status/tests.rs @@ -1161,34 +1161,45 @@ fn display_section_returns_closed_for_new_terminal_variants() { /// Initialise a bare-minimum git repo in `dir` with one commit. fn init_git_repo(dir: &std::path::Path) { + use crate::git_test_support::git_ok; use std::process::Command; - Command::new("git") - .args(["init", "-b", "main"]) - .current_dir(dir) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(dir) - .output() - .unwrap(); - Command::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(dir) - .output() - .unwrap(); + git_ok( + Command::new("git") + .args(["init", "-b", "main"]) + .current_dir(dir) + .output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); // Create an initial commit so the repo has a HEAD. std::fs::write(dir.join("README.md"), "# test").unwrap(); - Command::new("git") - .args(["add", "README.md"]) - .current_dir(dir) - .output() - .unwrap(); - Command::new("git") - .args(["commit", "-m", "init"]) - .current_dir(dir) - .output() - .unwrap(); + git_ok( + Command::new("git") + .args(["add", "README.md"]) + .current_dir(dir) + .output(), + "git add", + ); + git_ok( + Command::new("git") + .args(["commit", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } #[test] diff --git a/server/src/chat/commands/triage.rs b/server/src/chat/commands/triage.rs index cd36b654..27e13d3b 100644 --- a/server/src/chat/commands/triage.rs +++ b/server/src/chat/commands/triage.rs @@ -566,33 +566,44 @@ mod tests { /// Initialise a bare-minimum git repo in `dir` with one commit. fn init_git_repo(dir: &std::path::Path) { + use crate::git_test_support::git_ok; use std::process::Command as Cmd; - Cmd::new("git") - .args(["init", "-b", "main"]) - .current_dir(dir) - .output() - .unwrap(); - Cmd::new("git") - .args(["config", "user.email", "test@test.com"]) - .current_dir(dir) - .output() - .unwrap(); - Cmd::new("git") - .args(["config", "user.name", "Test"]) - .current_dir(dir) - .output() - .unwrap(); + git_ok( + Cmd::new("git") + .args(["init", "-b", "main"]) + .current_dir(dir) + .output(), + "git init", + ); + git_ok( + Cmd::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Cmd::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); std::fs::write(dir.join("README.md"), "# test").unwrap(); - Cmd::new("git") - .args(["add", "README.md"]) - .current_dir(dir) - .output() - .unwrap(); - Cmd::new("git") - .args(["commit", "-m", "init"]) - .current_dir(dir) - .output() - .unwrap(); + git_ok( + Cmd::new("git") + .args(["add", "README.md"]) + .current_dir(dir) + .output(), + "git add", + ); + git_ok( + Cmd::new("git") + .args(["commit", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } #[test] diff --git a/server/src/chat/compact/transcript.rs b/server/src/chat/compact/transcript.rs index ab769991..d3ce41ad 100644 --- a/server/src/chat/compact/transcript.rs +++ b/server/src/chat/compact/transcript.rs @@ -10,10 +10,55 @@ use std::path::{Path, PathBuf}; /// replaced by `-` (e.g. `/workspace/.huskies/worktrees/1186` becomes /// `-workspace--huskies-worktrees-1186`). pub fn transcript_path(cwd: &Path, session_id: &str) -> PathBuf { + #[cfg(test)] + if let Some(home) = test_home::get() { + return transcript_path_under_home(&home, cwd, session_id); + } let home = std::env::var("HOME").unwrap_or_else(|_| "/home/huskies".to_string()); transcript_path_under_home(Path::new(&home), cwd, session_id) } +/// Per-thread `$HOME` override for tests, so a test can sandbox where +/// [`transcript_path`] looks without mutating the process-global `$HOME` +/// env var (which every thread shares, including unrelated `git` +/// subprocesses spawned by other tests reading `$HOME` for +/// `~/.gitconfig`). Thread-local storage gives each test's thread its own +/// independent value — no lock, no serialization, no race, since +/// `#[tokio::test]` (current-thread flavor, used throughout this crate) +/// pins a test's whole async call graph to the one thread that set it. +#[cfg(test)] +pub(crate) mod test_home { + use std::cell::RefCell; + use std::path::{Path, PathBuf}; + + thread_local! { + static HOME: RefCell> = const { RefCell::new(None) }; + } + + /// Return the current thread's `$HOME` override, if one is set. + pub(crate) fn get() -> Option { + HOME.with(|h| h.borrow().clone()) + } + + /// RAII guard: while held, this thread's [`super::transcript_path`] + /// calls resolve under the overridden home instead of the real + /// `$HOME`. Clears the override on drop. + pub(crate) struct HomeGuard; + + impl Drop for HomeGuard { + fn drop(&mut self) { + HOME.with(|h| *h.borrow_mut() = None); + } + } + + /// Override `$HOME` resolution for [`super::transcript_path`] calls + /// made on the current thread for the lifetime of the returned guard. + pub(crate) fn set(home: &Path) -> HomeGuard { + HOME.with(|h| *h.borrow_mut() = Some(home.to_path_buf())); + HomeGuard + } +} + /// Same as [`transcript_path`] but takes an explicit `$HOME` directory, /// keeping the path-joining logic testable without mutating process env vars. fn transcript_path_under_home(home: &Path, cwd: &Path, session_id: &str) -> PathBuf { diff --git a/server/src/chat/transport/discord/commands.rs b/server/src/chat/transport/discord/commands.rs index 54cc26b4..272b6233 100644 --- a/server/src/chat/transport/discord/commands.rs +++ b/server/src/chat/transport/discord/commands.rs @@ -673,11 +673,7 @@ mod tests { let project_root = tmp.path().join("project"); std::fs::create_dir_all(&project_root).unwrap(); let home = tempfile::tempdir().unwrap(); - // SAFETY: this test owns HOME for its duration; no other test in this - // process reads HOME concurrently with this call. - unsafe { - std::env::set_var("HOME", home.path()); - } + let _home_guard = crate::chat::compact::transcript::test_home::set(home.path()); let transcript_dir = crate::chat::compact::transcript::transcript_path(&project_root, session_id) .parent() diff --git a/server/src/chat/transport/matrix/bot/messages/on_room_message.rs b/server/src/chat/transport/matrix/bot/messages/on_room_message.rs index 8c18e773..5ec802ff 100644 --- a/server/src/chat/transport/matrix/bot/messages/on_room_message.rs +++ b/server/src/chat/transport/matrix/bot/messages/on_room_message.rs @@ -2108,11 +2108,7 @@ mod tests { let project_root_dir = tempfile::tempdir().unwrap(); let project_root = project_root_dir.path().to_path_buf(); let home = tempfile::tempdir().unwrap(); - // SAFETY: this test owns HOME for its duration; no other test in this - // process reads HOME concurrently with this call. - unsafe { - std::env::set_var("HOME", home.path()); - } + let _home_guard = crate::chat::compact::transcript::test_home::set(home.path()); let transcript_dir = crate::chat::compact::transcript::transcript_path(&project_root, session_id) .parent() diff --git a/server/src/chat/transport/matrix/compact.rs b/server/src/chat/transport/matrix/compact.rs index 478c9cc4..77713cdc 100644 --- a/server/src/chat/transport/matrix/compact.rs +++ b/server/src/chat/transport/matrix/compact.rs @@ -139,11 +139,7 @@ mod tests { let session_id = "sess-compact-1"; let project_root = tempfile::tempdir().unwrap(); let home = tempfile::tempdir().unwrap(); - // SAFETY: this test owns HOME for its duration; no other test in this - // process reads HOME concurrently with this call. - unsafe { - std::env::set_var("HOME", home.path()); - } + let _home_guard = crate::chat::compact::transcript::test_home::set(home.path()); let transcript_dir = compact::transcript::transcript_path(project_root.path(), session_id) .parent() .unwrap() diff --git a/server/src/git_test_support.rs b/server/src/git_test_support.rs new file mode 100644 index 00000000..85847586 --- /dev/null +++ b/server/src/git_test_support.rs @@ -0,0 +1,22 @@ +//! Shared test helper for driving `git` as a subprocess in unit tests. +//! +//! `Command::output()` resolves to `Ok` even when the spawned process exits +//! non-zero — a bare `.expect(...)`/`.unwrap()` on that `Output` only +//! checks that the process could be spawned, not that git itself +//! succeeded. A failed `git commit` (e.g. missing `user.name`/`user.email` +//! identity) then silently leaves the repo without the commit the rest of +//! the test assumes exists, surfacing later as a confusing, unrelated +//! assertion failure instead of the real git error. + +use std::io; +use std::process::Output; + +/// Unwrap a `git` subprocess result, panicking with `context` and git's +/// stderr if the process failed to spawn or exited non-zero. +pub(crate) fn git_ok(output: io::Result, context: &str) -> Output { + let output = output.unwrap_or_else(|e| panic!("{context}: failed to run git: {e}")); + if !output.status.success() { + panic!("{context}: {}", String::from_utf8_lossy(&output.stderr)); + } + output +} diff --git a/server/src/main.rs b/server/src/main.rs index 73799d40..6ef56bbb 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -30,6 +30,10 @@ pub(crate) mod event_log; /// Gateway mode — multi-project reverse proxy that fronts multiple project containers. pub mod gateway; mod gateway_relay; +/// Shared test helper for driving `git` as a subprocess and checking its +/// exit status, used by `init_git_repo`-style helpers across the crate. +#[cfg(test)] +pub(crate) mod git_test_support; /// History — subject-scoped, cursor-paged timeline over chat turns, agent /// runs, and pipeline transitions. pub(crate) mod history; diff --git a/server/src/worktree/cleanup.rs b/server/src/worktree/cleanup.rs index 829612b5..e5e56b69 100644 --- a/server/src/worktree/cleanup.rs +++ b/server/src/worktree/cleanup.rs @@ -177,16 +177,32 @@ mod tests { use tempfile::TempDir; fn init_git_repo(dir: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(dir) - .output() - .expect("git init"); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(dir) - .output() - .expect("git commit"); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git").args(["init"]).current_dir(dir).output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } fn empty_config() -> ProjectConfig { diff --git a/server/src/worktree/create.rs b/server/src/worktree/create.rs index ae2d1ecd..bc4b7bfa 100644 --- a/server/src/worktree/create.rs +++ b/server/src/worktree/create.rs @@ -216,16 +216,32 @@ mod tests { use tempfile::TempDir; fn init_git_repo(dir: &Path) { - Command::new("git") - .args(["init"]) - .current_dir(dir) - .output() - .expect("git init"); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(dir) - .output() - .expect("git commit"); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git").args(["init"]).current_dir(dir).output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } fn empty_config() -> ProjectConfig { diff --git a/server/src/worktree/git.rs b/server/src/worktree/git.rs index 667d54f0..15ea085c 100644 --- a/server/src/worktree/git.rs +++ b/server/src/worktree/git.rs @@ -64,11 +64,20 @@ pub(crate) fn create_worktree_sync( .current_dir(project_root) .output(); - // Try to create branch. If it already exists that's fine. - let _ = Command::new("git") + // Try to create branch. If it already exists that's fine; any other + // failure (e.g. unborn HEAD, invalid branch name) must surface here + // rather than resurface later as a confusing "git worktree add" error. + let output = Command::new("git") .args(["branch", branch]) .current_dir(project_root) - .output(); + .output() + .map_err(|e| format!("git branch: {e}"))?; + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + if !stderr.contains("already exists") { + return Err(format!("git branch failed: {stderr}")); + } + } // Create worktree let output = Command::new("git") @@ -227,16 +236,32 @@ mod tests { use tempfile::TempDir; fn init_git_repo(dir: &Path) { - Command::new("git") - .args(["init"]) - .current_dir(dir) - .output() - .expect("git init"); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(dir) - .output() - .expect("git commit"); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git").args(["init"]).current_dir(dir).output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } #[test] diff --git a/server/src/worktree/remove.rs b/server/src/worktree/remove.rs index bb02b261..e1aa0610 100644 --- a/server/src/worktree/remove.rs +++ b/server/src/worktree/remove.rs @@ -74,16 +74,32 @@ mod tests { use tempfile::TempDir; fn init_git_repo(dir: &std::path::Path) { - Command::new("git") - .args(["init"]) - .current_dir(dir) - .output() - .expect("git init"); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(dir) - .output() - .expect("git commit"); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git").args(["init"]).current_dir(dir).output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } fn empty_config() -> ProjectConfig { diff --git a/server/src/worktree/sweep.rs b/server/src/worktree/sweep.rs index dd648ade..17931bb0 100644 --- a/server/src/worktree/sweep.rs +++ b/server/src/worktree/sweep.rs @@ -98,16 +98,32 @@ mod tests { use tempfile::TempDir; fn init_git_repo(dir: &Path) { - Command::new("git") - .args(["init"]) - .current_dir(dir) - .output() - .expect("git init"); - Command::new("git") - .args(["commit", "--allow-empty", "-m", "init"]) - .current_dir(dir) - .output() - .expect("git commit"); + use crate::git_test_support::git_ok; + git_ok( + Command::new("git").args(["init"]).current_dir(dir).output(), + "git init", + ); + git_ok( + Command::new("git") + .args(["config", "user.email", "test@test.com"]) + .current_dir(dir) + .output(), + "git config user.email", + ); + git_ok( + Command::new("git") + .args(["config", "user.name", "Test"]) + .current_dir(dir) + .output(), + "git config user.name", + ); + git_ok( + Command::new("git") + .args(["commit", "--allow-empty", "-m", "init"]) + .current_dir(dir) + .output(), + "git commit", + ); } fn empty_config() -> ProjectConfig {