Files
superwork/tui/internal/git/worktree_test.go
T
2026-06-23 05:02:15 +08:00

146 lines
3.7 KiB
Go

package git_test
import (
"context"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"superwork-tui/internal/git"
)
// initRepo creates a bare git repo with one commit so worktree operations work.
func initRepo(t *testing.T) string {
t.Helper()
dir := t.TempDir()
run := func(args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
}
run("init")
run("config", "user.email", "test@test.com")
run("config", "user.name", "test")
// Need at least one commit for worktree add -b to work.
f := filepath.Join(dir, "README")
if err := os.WriteFile(f, []byte("init"), 0o644); err != nil {
t.Fatal(err)
}
run("add", ".")
run("commit", "-m", "init")
return dir
}
func TestCreateWorktree(t *testing.T) {
root := initRepo(t)
wtPath := filepath.Join(t.TempDir(), "feature-wt")
err := git.CreateWorktree(context.Background(), git.CreateWorktreeOpts{
WorkspaceRoot: root,
WorktreePath: wtPath,
Branch: "feature/test-branch",
})
if err != nil {
t.Fatalf("CreateWorktree: %v", err)
}
// Directory must exist.
if _, err := os.Stat(wtPath); err != nil {
t.Fatalf("worktree dir not created: %v", err)
}
// The new branch must exist in the main repo.
out, err := exec.Command("git", "-C", root, "branch", "--list", "feature/test-branch").Output()
if err != nil {
t.Fatalf("git branch --list: %v", err)
}
if !strings.Contains(string(out), "feature/test-branch") {
t.Errorf("branch not created; git branch output: %q", string(out))
}
}
func TestCreateWorktree_BadBranch(t *testing.T) {
root := initRepo(t)
wtPath := filepath.Join(t.TempDir(), "bad-wt")
// Using a branch name with ".." is invalid for git.
err := git.CreateWorktree(context.Background(), git.CreateWorktreeOpts{
WorkspaceRoot: root,
WorktreePath: wtPath,
Branch: "bad..branch",
})
if err == nil {
t.Fatal("expected error for invalid branch name, got nil")
}
// Error must mention something useful (stderr wrapped in).
t.Logf("got expected error: %v", err)
}
func TestRemoveWorktree(t *testing.T) {
root := initRepo(t)
wtPath := filepath.Join(t.TempDir(), "rm-wt")
if err := git.CreateWorktree(context.Background(), git.CreateWorktreeOpts{
WorkspaceRoot: root,
WorktreePath: wtPath,
Branch: "feature/rm-test",
}); err != nil {
t.Fatalf("setup CreateWorktree: %v", err)
}
err := git.RemoveWorktree(context.Background(), git.RemoveWorktreeOpts{
WorkspaceRoot: root,
WorktreePath: wtPath,
Force: false,
})
if err != nil {
t.Fatalf("RemoveWorktree: %v", err)
}
// Directory must be gone.
if _, err := os.Stat(wtPath); !os.IsNotExist(err) {
t.Errorf("worktree dir still exists after remove")
}
}
func TestRemoveWorktree_Force(t *testing.T) {
root := initRepo(t)
wtPath := filepath.Join(t.TempDir(), "force-wt")
if err := git.CreateWorktree(context.Background(), git.CreateWorktreeOpts{
WorkspaceRoot: root,
WorktreePath: wtPath,
Branch: "feature/force-test",
}); err != nil {
t.Fatalf("setup: %v", err)
}
// Write an uncommitted change to make the worktree "dirty".
if err := os.WriteFile(filepath.Join(wtPath, "dirty"), []byte("x"), 0o644); err != nil {
t.Fatal(err)
}
cmd := exec.Command("git", "add", ".")
cmd.Dir = wtPath
cmd.Run() //nolint — best effort for test setup
// Without force this might fail; with force it must succeed.
err := git.RemoveWorktree(context.Background(), git.RemoveWorktreeOpts{
WorkspaceRoot: root,
WorktreePath: wtPath,
Force: true,
})
if err != nil {
t.Fatalf("RemoveWorktree --force: %v", err)
}
if _, err := os.Stat(wtPath); !os.IsNotExist(err) {
t.Errorf("worktree dir still exists after force remove")
}
}