146 lines
3.7 KiB
Go
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")
|
|
}
|
|
}
|