fix(nodb): set storeActive when initializing no-db mode

The `bd comment --no-db` command was failing because
initializeNoDbMode() set the global `store` but never set
`storeActive = true`. When comments.go called ensureStoreActive(),
the guard check failed and it tried to find a SQLite database,
returning an ironic error telling the user to use --no-db.

Why only `comment` was affected:
- Commands like `create`, `update`, `close` use `store` directly
- The `comment` command calls `ensureStoreActive()` first as a safety check
- That function guards on `storeActive && store != nil`
- Since `storeActive` was never set, the guard failed and it looked for SQLite

The fix aligns no-db mode with what ensureStoreActive() expects.
This commit is contained in:
Eugene Sukhodolin
2025-12-26 22:23:58 -08:00
parent ea8ae11002
commit 0575ca9bd9
2 changed files with 88 additions and 1 deletions

View File

@@ -72,8 +72,11 @@ func initializeNoDbMode() error {
debug.Logf("using prefix '%s'", prefix)
// Set global store
// Set global store and mark as active (fixes bd comment --no-db)
storeMutex.Lock()
store = memStore
storeActive = true
storeMutex.Unlock()
return nil
}

View File

@@ -158,6 +158,90 @@ func TestDetectPrefix(t *testing.T) {
})
}
func TestInitializeNoDbMode_SetsStoreActive(t *testing.T) {
// This test verifies the fix for bd comment --no-db not working.
// The bug was that initializeNoDbMode() set `store` but not `storeActive`,
// so ensureStoreActive() would try to find a SQLite database.
tempDir := t.TempDir()
beadsDir := filepath.Join(tempDir, ".beads")
if err := os.MkdirAll(beadsDir, 0o755); err != nil {
t.Fatalf("Failed to create .beads dir: %v", err)
}
// Create a minimal JSONL file with one issue
jsonlPath := filepath.Join(beadsDir, "issues.jsonl")
content := `{"id":"bd-1","title":"Test Issue","status":"open"}
`
if err := os.WriteFile(jsonlPath, []byte(content), 0o600); err != nil {
t.Fatalf("Failed to write JSONL: %v", err)
}
// Save and restore global state
oldStore := store
oldStoreActive := storeActive
oldCwd, _ := os.Getwd()
defer func() {
storeMutex.Lock()
store = oldStore
storeActive = oldStoreActive
storeMutex.Unlock()
_ = os.Chdir(oldCwd)
}()
// Change to temp dir so initializeNoDbMode finds .beads
if err := os.Chdir(tempDir); err != nil {
t.Fatalf("Failed to chdir: %v", err)
}
// Reset global state
storeMutex.Lock()
store = nil
storeActive = false
storeMutex.Unlock()
// Initialize no-db mode
if err := initializeNoDbMode(); err != nil {
t.Fatalf("initializeNoDbMode failed: %v", err)
}
// Verify storeActive is now true
storeMutex.Lock()
active := storeActive
s := store
storeMutex.Unlock()
if !active {
t.Error("storeActive should be true after initializeNoDbMode")
}
if s == nil {
t.Fatal("store should not be nil after initializeNoDbMode")
}
// ensureStoreActive should now return immediately without error
if err := ensureStoreActive(); err != nil {
t.Errorf("ensureStoreActive should succeed after initializeNoDbMode: %v", err)
}
// Verify comments work (this was the failing case)
ctx := rootCtx
comment, err := s.AddIssueComment(ctx, "bd-1", "testuser", "Test comment")
if err != nil {
t.Fatalf("AddIssueComment failed: %v", err)
}
if comment.Text != "Test comment" {
t.Errorf("Expected 'Test comment', got %s", comment.Text)
}
comments, err := s.GetIssueComments(ctx, "bd-1")
if err != nil {
t.Fatalf("GetIssueComments failed: %v", err)
}
if len(comments) != 1 {
t.Errorf("Expected 1 comment, got %d", len(comments))
}
}
func TestWriteIssuesToJSONL(t *testing.T) {
tempDir := t.TempDir()
beadsDir := filepath.Join(tempDir, ".beads")