Fix Dolt backend init/daemon/doctor; prevent accidental SQLite artifacts; add integration tests; clean up lint (#1218)
* /{cmd,internal}: get dolt backend init working and allow issue creation
* /{website,internal,docs,cmd}: integration tests and more split backend fixes
* /{cmd,internal}: fix lint issues
* /cmd/bd/doctor/integrity.go: fix unable to query issues bug with dolt backend
* /cmd/bd/daemon.go: remove debug logging
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/beads/cmd/bd/doctor"
|
||||
"github.com/steveyegge/beads/internal/beads"
|
||||
"github.com/steveyegge/beads/internal/configfile"
|
||||
"github.com/steveyegge/beads/internal/daemon"
|
||||
"github.com/steveyegge/beads/internal/rpc"
|
||||
"github.com/steveyegge/beads/internal/storage/factory"
|
||||
@@ -298,7 +299,6 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush, autoPull, local
|
||||
stackTrace := string(stackBuf[:stackSize])
|
||||
log.Error("stack trace", "trace", stackTrace)
|
||||
|
||||
// Write crash report to daemon-error file for user visibility
|
||||
var beadsDir string
|
||||
if dbPath != "" {
|
||||
beadsDir = filepath.Dir(dbPath)
|
||||
@@ -307,13 +307,9 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush, autoPull, local
|
||||
}
|
||||
|
||||
if beadsDir != "" {
|
||||
errFile := filepath.Join(beadsDir, "daemon-error")
|
||||
crashReport := fmt.Sprintf("Daemon crashed at %s\n\nPanic: %v\n\nStack trace:\n%s\n",
|
||||
time.Now().Format(time.RFC3339), r, stackTrace)
|
||||
// nolint:gosec // G306: Error file needs to be readable for debugging
|
||||
if err := os.WriteFile(errFile, []byte(crashReport), 0644); err != nil {
|
||||
log.Warn("could not write crash report", "error", err)
|
||||
}
|
||||
log.Error("crash report", "report", crashReport)
|
||||
}
|
||||
|
||||
// Clean up PID file
|
||||
@@ -350,50 +346,63 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush, autoPull, local
|
||||
|
||||
// Check for multiple .db files (ambiguity error)
|
||||
beadsDir := filepath.Dir(daemonDBPath)
|
||||
backend := factory.GetBackendFromConfig(beadsDir)
|
||||
if backend == "" {
|
||||
backend = configfile.BackendSQLite
|
||||
}
|
||||
|
||||
// Reset backoff on daemon start (fresh start, but preserve NeedsManualSync hint)
|
||||
if !localMode {
|
||||
ResetBackoffOnDaemonStart(beadsDir)
|
||||
}
|
||||
matches, err := filepath.Glob(filepath.Join(beadsDir, "*.db"))
|
||||
if err == nil && len(matches) > 1 {
|
||||
// Filter out backup files (*.backup-*.db, *.backup.db)
|
||||
var validDBs []string
|
||||
for _, match := range matches {
|
||||
baseName := filepath.Base(match)
|
||||
// Skip if it's a backup file (contains ".backup" in name)
|
||||
if !strings.Contains(baseName, ".backup") && baseName != "vc.db" {
|
||||
validDBs = append(validDBs, match)
|
||||
}
|
||||
}
|
||||
if len(validDBs) > 1 {
|
||||
errMsg := fmt.Sprintf("Error: Multiple database files found in %s:\n", beadsDir)
|
||||
for _, db := range validDBs {
|
||||
errMsg += fmt.Sprintf(" - %s\n", filepath.Base(db))
|
||||
}
|
||||
errMsg += fmt.Sprintf("\nBeads requires a single canonical database: %s\n", beads.CanonicalDatabaseName)
|
||||
errMsg += "Run 'bd init' to migrate legacy databases or manually remove old databases\n"
|
||||
errMsg += "Or run 'bd doctor' for more diagnostics"
|
||||
|
||||
log.log(errMsg)
|
||||
|
||||
// Write error to file so user can see it without checking logs
|
||||
errFile := filepath.Join(beadsDir, "daemon-error")
|
||||
// nolint:gosec // G306: Error file needs to be readable for debugging
|
||||
if err := os.WriteFile(errFile, []byte(errMsg), 0644); err != nil {
|
||||
log.Warn("could not write daemon-error file", "error", err)
|
||||
// Check for multiple .db files (ambiguity error) - SQLite only.
|
||||
// Dolt is directory-backed so this check is irrelevant and can be misleading.
|
||||
if backend == configfile.BackendSQLite {
|
||||
matches, err := filepath.Glob(filepath.Join(beadsDir, "*.db"))
|
||||
if err == nil && len(matches) > 1 {
|
||||
// Filter out backup files (*.backup-*.db, *.backup.db)
|
||||
var validDBs []string
|
||||
for _, match := range matches {
|
||||
baseName := filepath.Base(match)
|
||||
// Skip if it's a backup file (contains ".backup" in name)
|
||||
if !strings.Contains(baseName, ".backup") && baseName != "vc.db" {
|
||||
validDBs = append(validDBs, match)
|
||||
}
|
||||
}
|
||||
if len(validDBs) > 1 {
|
||||
errMsg := fmt.Sprintf("Error: Multiple database files found in %s:\n", beadsDir)
|
||||
for _, db := range validDBs {
|
||||
errMsg += fmt.Sprintf(" - %s\n", filepath.Base(db))
|
||||
}
|
||||
errMsg += fmt.Sprintf("\nBeads requires a single canonical database: %s\n", beads.CanonicalDatabaseName)
|
||||
errMsg += "Run 'bd init' to migrate legacy databases or manually remove old databases\n"
|
||||
errMsg += "Or run 'bd doctor' for more diagnostics"
|
||||
|
||||
return // Use return instead of os.Exit to allow defers to run
|
||||
log.log(errMsg)
|
||||
|
||||
// Write error to file so user can see it without checking logs
|
||||
errFile := filepath.Join(beadsDir, "daemon-error")
|
||||
// nolint:gosec // G306: Error file needs to be readable for debugging
|
||||
if err := os.WriteFile(errFile, []byte(errMsg), 0644); err != nil {
|
||||
log.Warn("could not write daemon-error file", "error", err)
|
||||
}
|
||||
|
||||
return // Use return instead of os.Exit to allow defers to run
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate using canonical name
|
||||
dbBaseName := filepath.Base(daemonDBPath)
|
||||
if dbBaseName != beads.CanonicalDatabaseName {
|
||||
log.Error("non-canonical database name", "name", dbBaseName, "expected", beads.CanonicalDatabaseName)
|
||||
log.Info("run 'bd init' to migrate to canonical name")
|
||||
return // Use return instead of os.Exit to allow defers to run
|
||||
// Validate using canonical name (SQLite only).
|
||||
// Dolt uses a directory-backed store (typically .beads/dolt), so the "beads.db"
|
||||
// basename invariant does not apply.
|
||||
if backend == configfile.BackendSQLite {
|
||||
dbBaseName := filepath.Base(daemonDBPath)
|
||||
if dbBaseName != beads.CanonicalDatabaseName {
|
||||
log.Error("non-canonical database name", "name", dbBaseName, "expected", beads.CanonicalDatabaseName)
|
||||
log.Info("run 'bd init' to migrate to canonical name")
|
||||
return // Use return instead of os.Exit to allow defers to run
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("using database", "path", daemonDBPath)
|
||||
@@ -621,6 +630,7 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush, autoPull, local
|
||||
// - If either BEADS_AUTO_COMMIT/daemon.auto_commit or BEADS_AUTO_PUSH/daemon.auto_push
|
||||
// is enabled, treat as auto-sync=true (full read/write)
|
||||
// - Otherwise check auto-pull for read-only mode
|
||||
//
|
||||
// 4. Fallback: all default to true when sync-branch configured
|
||||
//
|
||||
// Note: The individual auto-commit/auto-push settings are deprecated.
|
||||
|
||||
Reference in New Issue
Block a user