package infra import ( "os" "os/exec" "path/filepath" "strings" "testing" ) // initDummyRepo creates a tiny git repo with a master branch and one commit so // that `git worktree add ... master` can succeed. func initDummyRepo(t *testing.T) string { t.Helper() dir := t.TempDir() runIn := func(name string, args ...string) { cmd := exec.Command(name, args...) cmd.Dir = dir // Detach from any global config that might inject signing/templates. cmd.Env = append(os.Environ(), "GIT_CONFIG_GLOBAL=/dev/null", "GIT_CONFIG_SYSTEM=/dev/null", "GIT_AUTHOR_NAME=test", "GIT_AUTHOR_EMAIL=t@t", "GIT_COMMITTER_NAME=test", "GIT_COMMITTER_EMAIL=t@t", ) if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("%s %v: %v\n%s", name, args, err, out) } } runIn("git", "init", "-b", "master") if err := os.WriteFile(filepath.Join(dir, "README.md"), []byte("hi"), 0o644); err != nil { t.Fatal(err) } runIn("git", "add", "README.md") runIn("git", "commit", "-m", "init") return dir } func TestAgentLaunchWorktree_CreatesWorktreeAndBranch(t *testing.T) { repo := initDummyRepo(t) wt := filepath.Join(t.TempDir(), "wt-0001") log := filepath.Join(t.TempDir(), "claude.log") res := AgentLaunchWorktree(WorktreeLaunchConfig{ RepoRoot: repo, Branch: "auto/test-0001", WorktreePath: wt, Prompt: "hello", LogPath: log, }) if res.Error != "" { t.Fatalf("unexpected error: %s", res.Error) } if res.PID <= 0 { t.Fatalf("expected PID>0, got %d", res.PID) } if _, err := os.Stat(wt); err != nil { t.Fatalf("worktree dir missing: %v", err) } // Branch should exist in the main repo's refs. out, err := exec.Command("git", "-C", repo, "branch", "--list", "auto/test-0001").CombinedOutput() if err != nil || !strings.Contains(string(out), "auto/test-0001") { t.Fatalf("branch not created: err=%v out=%s", err, out) } if _, err := os.Stat(log); err != nil { t.Fatalf("log file missing: %v", err) } // Cleanup (best-effort, not asserted here). _ = AgentCleanupWorktree(repo, "auto/test-0001", wt, res.PID) } func TestAgentLaunchWorktree_ResetIfExists(t *testing.T) { repo := initDummyRepo(t) wt := filepath.Join(t.TempDir(), "wt-reset") log := filepath.Join(t.TempDir(), "claude.log") // First launch. res1 := AgentLaunchWorktree(WorktreeLaunchConfig{ RepoRoot: repo, Branch: "auto/reset-test", WorktreePath: wt, Prompt: "first", LogPath: log, }) if res1.Error != "" { t.Fatalf("first launch failed: %s", res1.Error) } // Second launch with ResetIfExists=true should succeed and recreate. res2 := AgentLaunchWorktree(WorktreeLaunchConfig{ RepoRoot: repo, Branch: "auto/reset-test", WorktreePath: wt, Prompt: "second", LogPath: log, ResetIfExists: true, }) if res2.Error != "" { t.Fatalf("reset launch failed: %s", res2.Error) } if _, err := os.Stat(wt); err != nil { t.Fatalf("worktree dir missing after reset: %v", err) } _ = AgentCleanupWorktree(repo, "auto/reset-test", wt, res2.PID) } func TestAgentLaunchWorktree_MissingArgs(t *testing.T) { res := AgentLaunchWorktree(WorktreeLaunchConfig{}) if res.Error == "" { t.Fatal("expected error for empty config, got none") } }