fix: allow yaml-only config operations without database (GH#536)
Users could not run 'bd config set no-db true' without already having a database, creating a chicken-and-egg problem. The PersistentPreRunE would fail with 'no beads database found' before the config command could even run. The fix detects when a yaml-only config operation is being attempted (config set/get with keys like no-db, no-daemon, sync.branch, etc.) and allows it to proceed without requiring a database. Before: $ bd config set no-db true Error: no beads database found After: $ bd config set no-db true Set no-db = true (in config.yaml) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
8601ed01b6
commit
6572654cdc
@@ -6,6 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/beads/internal/config"
|
||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||
)
|
||||
|
||||
@@ -148,6 +149,52 @@ func TestConfigNamespaces(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestYamlOnlyConfigWithoutDatabase verifies that yaml-only config keys
|
||||
// (like no-db, no-daemon) can be set/get without requiring a SQLite database.
|
||||
// This is the fix for GH#536 - the chicken-and-egg problem where you couldn't
|
||||
// run `bd config set no-db true` without first having a database.
|
||||
func TestYamlOnlyConfigWithoutDatabase(t *testing.T) {
|
||||
// Create a temp directory with only config.yaml (no database)
|
||||
tmpDir, err := os.MkdirTemp("", "bd-test-yaml-config-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
beadsDir := filepath.Join(tmpDir, ".beads")
|
||||
if err := os.MkdirAll(beadsDir, 0755); err != nil {
|
||||
t.Fatalf("Failed to create .beads dir: %v", err)
|
||||
}
|
||||
|
||||
// Create config.yaml with a prefix but NO database
|
||||
configPath := filepath.Join(beadsDir, "config.yaml")
|
||||
if err := os.WriteFile(configPath, []byte("prefix: test\n"), 0644); err != nil {
|
||||
t.Fatalf("Failed to create config.yaml: %v", err)
|
||||
}
|
||||
|
||||
// Create empty issues.jsonl (simulates fresh clone)
|
||||
jsonlPath := filepath.Join(beadsDir, "issues.jsonl")
|
||||
if err := os.WriteFile(jsonlPath, []byte(""), 0644); err != nil {
|
||||
t.Fatalf("Failed to create issues.jsonl: %v", err)
|
||||
}
|
||||
|
||||
// Test that IsYamlOnlyKey correctly identifies yaml-only keys
|
||||
yamlOnlyKeys := []string{"no-db", "no-daemon", "no-auto-flush", "json", "sync.branch", "routing.mode"}
|
||||
for _, key := range yamlOnlyKeys {
|
||||
if !config.IsYamlOnlyKey(key) {
|
||||
t.Errorf("Expected %q to be a yaml-only key", key)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that non-yaml-only keys are correctly identified
|
||||
nonYamlKeys := []string{"jira.url", "linear.team_id", "status.custom"}
|
||||
for _, key := range nonYamlKeys {
|
||||
if config.IsYamlOnlyKey(key) {
|
||||
t.Errorf("Expected %q to NOT be a yaml-only key", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setupTestDB creates a temporary test database
|
||||
func setupTestDB(t *testing.T) (*sqlite.SQLiteStorage, func()) {
|
||||
tmpDir, err := os.MkdirTemp("", "bd-test-config-*")
|
||||
|
||||
@@ -434,7 +434,14 @@ var rootCmd = &cobra.Command{
|
||||
// Allow some commands to run without a database
|
||||
// - import: auto-initializes database if missing
|
||||
// - setup: creates editor integration files (no DB needed)
|
||||
if cmd.Name() != "import" && cmd.Name() != "setup" {
|
||||
// - config set/get for yaml-only keys: writes to config.yaml, not SQLite (GH#536)
|
||||
isYamlOnlyConfigOp := false
|
||||
if (cmd.Name() == "set" || cmd.Name() == "get") && cmd.Parent() != nil && cmd.Parent().Name() == "config" {
|
||||
if len(args) > 0 && config.IsYamlOnlyKey(args[0]) {
|
||||
isYamlOnlyConfigOp = true
|
||||
}
|
||||
}
|
||||
if cmd.Name() != "import" && cmd.Name() != "setup" && !isYamlOnlyConfigOp {
|
||||
// No database found - provide context-aware error message
|
||||
fmt.Fprintf(os.Stderr, "Error: no beads database found\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user