This commit is contained in:
Steve Yegge
2025-11-23 23:05:29 -08:00
5 changed files with 226 additions and 280 deletions

File diff suppressed because one or more lines are too long

View File

@@ -18,6 +18,7 @@ func TestNewSQLiteStorage(t *testing.T) {
if err != nil {
t.Fatalf("NewSQLiteStorage failed: %v", err)
}
defer store.Close()
if store == nil {
t.Error("expected non-nil storage")

View File

@@ -32,20 +32,8 @@ func TestIsGitRepo_NotInGitRepo(t *testing.T) {
}
func TestGitHasUpstream_NoUpstream(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a fresh git repo without upstream
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Should not have upstream
if gitHasUpstream() {
@@ -55,23 +43,10 @@ func TestGitHasUpstream_NoUpstream(t *testing.T) {
func TestGitHasChanges_NoFile(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
_, cleanup := setupGitRepo(t)
defer cleanup()
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create and commit a file
testFile := filepath.Join(tmpDir, "test.txt")
os.WriteFile(testFile, []byte("original"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
// Check - should have no changes
// Check - should have no changes (test.txt was committed by setupGitRepo)
hasChanges, err := gitHasChanges(ctx, "test.txt")
if err != nil {
t.Fatalf("gitHasChanges() error = %v", err)
@@ -83,23 +58,11 @@ func TestGitHasChanges_NoFile(t *testing.T) {
func TestGitHasChanges_ModifiedFile(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create and commit a file
testFile := filepath.Join(tmpDir, "test.txt")
os.WriteFile(testFile, []byte("original"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
tmpDir, cleanup := setupGitRepo(t)
defer cleanup()
// Modify the file
testFile := filepath.Join(tmpDir, "test.txt")
os.WriteFile(testFile, []byte("modified"), 0644)
// Check - should have changes
@@ -113,20 +76,8 @@ func TestGitHasChanges_ModifiedFile(t *testing.T) {
}
func TestGitHasUnmergedPaths_CleanRepo(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Should not have unmerged paths
hasUnmerged, err := gitHasUnmergedPaths()
@@ -140,23 +91,11 @@ func TestGitHasUnmergedPaths_CleanRepo(t *testing.T) {
func TestGitCommit_Success(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("initial.txt", []byte("initial"), 0644)
exec.Command("git", "add", "initial.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Create a new file
testFile := "test.txt"
testFile := "new.txt"
os.WriteFile(testFile, []byte("content"), 0644)
// Commit the file
@@ -177,23 +116,11 @@ func TestGitCommit_Success(t *testing.T) {
func TestGitCommit_AutoMessage(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("initial.txt", []byte("initial"), 0644)
exec.Command("git", "add", "initial.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Create a new file
testFile := "test.txt"
testFile := "new.txt"
os.WriteFile(testFile, []byte("content"), 0644)
// Commit with auto-generated message (empty string)
@@ -275,20 +202,8 @@ not valid json
func TestGetCurrentBranch(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Get current branch
branch, err := getCurrentBranch(ctx)
@@ -304,20 +219,8 @@ func TestGetCurrentBranch(t *testing.T) {
func TestMergeSyncBranch_NoSyncBranchConfigured(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Try to merge without sync.branch configured (or database)
err := mergeSyncBranch(ctx, false)
@@ -332,20 +235,8 @@ func TestMergeSyncBranch_NoSyncBranchConfigured(t *testing.T) {
func TestMergeSyncBranch_OnSyncBranch(t *testing.T) {
ctx := context.Background()
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit on main
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
tmpDir, cleanup := setupGitRepo(t)
defer cleanup()
// Create sync branch
exec.Command("git", "checkout", "-b", "beads-metadata").Run()
@@ -363,20 +254,8 @@ func TestMergeSyncBranch_OnSyncBranch(t *testing.T) {
}
func TestMergeSyncBranch_DirtyWorkingTree(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Create uncommitted changes
os.WriteFile("test.txt", []byte("modified"), 0644)
@@ -443,20 +322,8 @@ func TestGetSyncBranch_EnvOverridesDB(t *testing.T) {
}
func TestIsInRebase_NotInRebase(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Should not be in rebase
if isInRebase() {
@@ -465,20 +332,8 @@ func TestIsInRebase_NotInRebase(t *testing.T) {
}
func TestIsInRebase_InRebase(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
tmpDir, cleanup := setupGitRepo(t)
defer cleanup()
// Simulate rebase by creating rebase-merge directory
os.MkdirAll(filepath.Join(tmpDir, ".git", "rebase-merge"), 0755)
@@ -490,13 +345,8 @@ func TestIsInRebase_InRebase(t *testing.T) {
}
func TestIsInRebase_InRebaseApply(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
tmpDir, cleanup := setupMinimalGitRepo(t)
defer cleanup()
// Simulate non-interactive rebase by creating rebase-apply directory
os.MkdirAll(filepath.Join(tmpDir, ".git", "rebase-apply"), 0755)
@@ -508,20 +358,8 @@ func TestIsInRebase_InRebaseApply(t *testing.T) {
}
func TestHasJSONLConflict_NoConflict(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
os.WriteFile("test.txt", []byte("test"), 0644)
exec.Command("git", "add", "test.txt").Run()
exec.Command("git", "commit", "-m", "initial").Run()
_, cleanup := setupGitRepo(t)
defer cleanup()
// Should not have JSONL conflict
if hasJSONLConflict() {
@@ -530,22 +368,15 @@ func TestHasJSONLConflict_NoConflict(t *testing.T) {
}
func TestHasJSONLConflict_OnlyJSONLConflict(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
tmpDir, cleanup := setupGitRepoWithBranch(t, "main")
defer cleanup()
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init", "-b", "main").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
// Create initial commit with beads.jsonl
beadsDir := filepath.Join(tmpDir, ".beads")
os.MkdirAll(beadsDir, 0755)
os.WriteFile(filepath.Join(beadsDir, "beads.jsonl"), []byte(`{"id":"bd-1","title":"original"}`), 0644)
exec.Command("git", "add", ".").Run()
exec.Command("git", "commit", "-m", "initial").Run()
exec.Command("git", "commit", "-m", "add beads.jsonl").Run()
// Create a second commit on main (modify same issue)
os.WriteFile(filepath.Join(beadsDir, "beads.jsonl"), []byte(`{"id":"bd-1","title":"main-version"}`), 0644)
@@ -568,15 +399,8 @@ func TestHasJSONLConflict_OnlyJSONLConflict(t *testing.T) {
}
func TestHasJSONLConflict_MultipleConflicts(t *testing.T) {
tmpDir := t.TempDir()
originalWd, _ := os.Getwd()
defer os.Chdir(originalWd)
// Create a git repo
os.Chdir(tmpDir)
exec.Command("git", "init", "-b", "main").Run()
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
tmpDir, cleanup := setupGitRepoWithBranch(t, "main")
defer cleanup()
// Create initial commit with beads.jsonl and another file
beadsDir := filepath.Join(tmpDir, ".beads")
@@ -584,7 +408,7 @@ func TestHasJSONLConflict_MultipleConflicts(t *testing.T) {
os.WriteFile(filepath.Join(beadsDir, "beads.jsonl"), []byte(`{"id":"bd-1","title":"original"}`), 0644)
os.WriteFile("other.txt", []byte("line1\nline2\nline3"), 0644)
exec.Command("git", "add", ".").Run()
exec.Command("git", "commit", "-m", "initial").Run()
exec.Command("git", "commit", "-m", "add initial files").Run()
// Create a second commit on main (modify both files)
os.WriteFile(filepath.Join(beadsDir, "beads.jsonl"), []byte(`{"id":"bd-1","title":"main-version"}`), 0644)

View File

@@ -1,6 +1,8 @@
package main
import (
"os"
"os/exec"
"testing"
"time"
)
@@ -18,3 +20,122 @@ func waitFor(t *testing.T, timeout, poll time.Duration, pred func() bool) {
}
t.Fatalf("condition not met within %v", timeout)
}
// setupGitRepo creates a temporary git repository and returns its path and cleanup function.
// The repo is initialized with git config and an initial commit.
// The current directory is changed to the new repo.
func setupGitRepo(t *testing.T) (repoPath string, cleanup func()) {
t.Helper()
tmpDir := t.TempDir()
originalWd, err := os.Getwd()
if err != nil {
t.Fatalf("failed to get working directory: %v", err)
}
if err := os.Chdir(tmpDir); err != nil {
t.Fatalf("failed to change to temp directory: %v", err)
}
// Initialize git repo
if err := exec.Command("git", "init").Run(); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to init git repo: %v", err)
}
// Configure git
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
if err := os.WriteFile("test.txt", []byte("test"), 0644); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to write test file: %v", err)
}
exec.Command("git", "add", "test.txt").Run()
if err := exec.Command("git", "commit", "-m", "initial").Run(); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to create initial commit: %v", err)
}
cleanup = func() {
os.Chdir(originalWd)
}
return tmpDir, cleanup
}
// setupGitRepoWithBranch creates a git repo and checks out a specific branch.
// Use this when tests need a specific branch name (e.g., "main").
func setupGitRepoWithBranch(t *testing.T, branch string) (repoPath string, cleanup func()) {
t.Helper()
tmpDir := t.TempDir()
originalWd, err := os.Getwd()
if err != nil {
t.Fatalf("failed to get working directory: %v", err)
}
if err := os.Chdir(tmpDir); err != nil {
t.Fatalf("failed to change to temp directory: %v", err)
}
// Initialize git repo with specific branch
if err := exec.Command("git", "init", "-b", branch).Run(); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to init git repo: %v", err)
}
// Configure git
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
// Create initial commit
if err := os.WriteFile("test.txt", []byte("test"), 0644); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to write test file: %v", err)
}
exec.Command("git", "add", "test.txt").Run()
if err := exec.Command("git", "commit", "-m", "initial").Run(); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to create initial commit: %v", err)
}
cleanup = func() {
os.Chdir(originalWd)
}
return tmpDir, cleanup
}
// setupMinimalGitRepo creates a git repo without an initial commit.
// Use this when tests need to control the initial state more precisely.
func setupMinimalGitRepo(t *testing.T) (repoPath string, cleanup func()) {
t.Helper()
tmpDir := t.TempDir()
originalWd, err := os.Getwd()
if err != nil {
t.Fatalf("failed to get working directory: %v", err)
}
if err := os.Chdir(tmpDir); err != nil {
t.Fatalf("failed to change to temp directory: %v", err)
}
// Initialize git repo
if err := exec.Command("git", "init").Run(); err != nil {
os.Chdir(originalWd)
t.Fatalf("failed to init git repo: %v", err)
}
// Configure git
exec.Command("git", "config", "user.email", "test@test.com").Run()
exec.Command("git", "config", "user.name", "Test User").Run()
cleanup = func() {
os.Chdir(originalWd)
}
return tmpDir, cleanup
}

View File

@@ -345,7 +345,7 @@ func findDatabaseInTree() string {
// Returns a slice of DatabaseInfo for each database found, starting from the
// closest to CWD (most relevant) to the furthest (least relevant).
func FindAllDatabases() []DatabaseInfo {
var databases []DatabaseInfo
databases := []DatabaseInfo{} // Initialize to empty slice, never return nil
seen := make(map[string]bool) // Track canonical paths to avoid duplicates
dir, err := os.Getwd()