Files
gastown/internal/git/git_test.go
Steve Yegge f46a1e6eab feat: add git wrapper package for subprocess operations
Operations:
- Clone, Checkout, Fetch, Pull, Push
- Add, Commit, CommitAll
- Status, CurrentBranch, HasUncommittedChanges, RemoteURL
- Merge, Rebase, AbortMerge, AbortRebase
- CreateBranch, DeleteBranch, Rev, IsAncestor

Error handling:
- Detects ErrNotARepo, ErrMergeConflict, ErrAuthFailure, ErrRebaseConflict
- Wraps git stderr in error messages

Closes gt-u1j.3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 13:27:03 -08:00

189 lines
3.8 KiB
Go

package git
import (
"os"
"os/exec"
"path/filepath"
"testing"
)
func initTestRepo(t *testing.T) string {
t.Helper()
dir := t.TempDir()
// Initialize repo
cmd := exec.Command("git", "init")
cmd.Dir = dir
if err := cmd.Run(); err != nil {
t.Fatalf("git init: %v", err)
}
// Configure user for commits
cmd = exec.Command("git", "config", "user.email", "test@test.com")
cmd.Dir = dir
cmd.Run()
cmd = exec.Command("git", "config", "user.name", "Test User")
cmd.Dir = dir
cmd.Run()
// Create initial commit
testFile := filepath.Join(dir, "README.md")
if err := os.WriteFile(testFile, []byte("# Test\n"), 0644); err != nil {
t.Fatalf("write file: %v", err)
}
cmd = exec.Command("git", "add", ".")
cmd.Dir = dir
cmd.Run()
cmd = exec.Command("git", "commit", "-m", "initial")
cmd.Dir = dir
cmd.Run()
return dir
}
func TestCurrentBranch(t *testing.T) {
dir := initTestRepo(t)
g := NewGit(dir)
branch, err := g.CurrentBranch()
if err != nil {
t.Fatalf("CurrentBranch: %v", err)
}
// Modern git uses "main", older uses "master"
if branch != "main" && branch != "master" {
t.Errorf("branch = %q, want main or master", branch)
}
}
func TestStatus(t *testing.T) {
dir := initTestRepo(t)
g := NewGit(dir)
// Should be clean initially
status, err := g.Status()
if err != nil {
t.Fatalf("Status: %v", err)
}
if !status.Clean {
t.Error("expected clean status")
}
// Add an untracked file
testFile := filepath.Join(dir, "new.txt")
if err := os.WriteFile(testFile, []byte("new"), 0644); err != nil {
t.Fatalf("write file: %v", err)
}
status, err = g.Status()
if err != nil {
t.Fatalf("Status: %v", err)
}
if status.Clean {
t.Error("expected dirty status")
}
if len(status.Untracked) != 1 {
t.Errorf("untracked = %d, want 1", len(status.Untracked))
}
}
func TestAddAndCommit(t *testing.T) {
dir := initTestRepo(t)
g := NewGit(dir)
// Create a new file
testFile := filepath.Join(dir, "new.txt")
if err := os.WriteFile(testFile, []byte("new content"), 0644); err != nil {
t.Fatalf("write file: %v", err)
}
// Add and commit
if err := g.Add("new.txt"); err != nil {
t.Fatalf("Add: %v", err)
}
if err := g.Commit("add new file"); err != nil {
t.Fatalf("Commit: %v", err)
}
// Should be clean
status, err := g.Status()
if err != nil {
t.Fatalf("Status: %v", err)
}
if !status.Clean {
t.Error("expected clean after commit")
}
}
func TestHasUncommittedChanges(t *testing.T) {
dir := initTestRepo(t)
g := NewGit(dir)
has, err := g.HasUncommittedChanges()
if err != nil {
t.Fatalf("HasUncommittedChanges: %v", err)
}
if has {
t.Error("expected no changes initially")
}
// Modify a file
testFile := filepath.Join(dir, "README.md")
if err := os.WriteFile(testFile, []byte("modified"), 0644); err != nil {
t.Fatalf("write file: %v", err)
}
has, err = g.HasUncommittedChanges()
if err != nil {
t.Fatalf("HasUncommittedChanges: %v", err)
}
if !has {
t.Error("expected changes after modify")
}
}
func TestCheckout(t *testing.T) {
dir := initTestRepo(t)
g := NewGit(dir)
// Create a new branch
if err := g.CreateBranch("feature"); err != nil {
t.Fatalf("CreateBranch: %v", err)
}
// Checkout the new branch
if err := g.Checkout("feature"); err != nil {
t.Fatalf("Checkout: %v", err)
}
branch, _ := g.CurrentBranch()
if branch != "feature" {
t.Errorf("branch = %q, want feature", branch)
}
}
func TestNotARepo(t *testing.T) {
dir := t.TempDir() // Empty dir, not a git repo
g := NewGit(dir)
_, err := g.CurrentBranch()
if err != ErrNotARepo {
t.Errorf("expected ErrNotARepo, got %v", err)
}
}
func TestRev(t *testing.T) {
dir := initTestRepo(t)
g := NewGit(dir)
hash, err := g.Rev("HEAD")
if err != nil {
t.Fatalf("Rev: %v", err)
}
// Should be a 40-char hex string
if len(hash) != 40 {
t.Errorf("hash length = %d, want 40", len(hash))
}
}