refactor: remove bd daemon code from gastown
Remove all code that calls bd daemon commands, as bd daemon functionality has been removed from beads: - Delete internal/beads/daemon.go (CheckBdDaemonHealth, StopAllBdProcesses, etc.) - Delete internal/beads/daemon_test.go - Delete internal/doctor/bd_daemon_check.go (BdDaemonCheck health check) - Remove bd daemon health check from gt status - Remove bd daemon stopping from gt down - Remove bd daemon cleanup from gt install - Remove BdDaemonCheck registration from gt doctor Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,213 +0,0 @@
|
||||
package doctor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BdDaemonCheck verifies that the bd (beads) daemon is running and healthy.
|
||||
// When the daemon fails to start, it surfaces the actual error (e.g., legacy
|
||||
// database detected, repo mismatch) and provides actionable fix commands.
|
||||
type BdDaemonCheck struct {
|
||||
FixableCheck
|
||||
}
|
||||
|
||||
// NewBdDaemonCheck creates a new bd daemon check.
|
||||
func NewBdDaemonCheck() *BdDaemonCheck {
|
||||
return &BdDaemonCheck{
|
||||
FixableCheck: FixableCheck{
|
||||
BaseCheck: BaseCheck{
|
||||
CheckName: "bd-daemon",
|
||||
CheckDescription: "Check if bd (beads) daemon is running",
|
||||
CheckCategory: CategoryInfrastructure,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Run checks if the bd daemon is running and healthy.
|
||||
func (c *BdDaemonCheck) Run(ctx *CheckContext) *CheckResult {
|
||||
// Check daemon status
|
||||
cmd := exec.Command("bd", "daemon", "status")
|
||||
cmd.Dir = ctx.TownRoot
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
output := strings.TrimSpace(stdout.String() + stderr.String())
|
||||
|
||||
// Check if daemon is running
|
||||
if err == nil && strings.Contains(output, "Daemon is running") {
|
||||
// Daemon is running, now check health
|
||||
healthCmd := exec.Command("bd", "daemon", "health")
|
||||
healthCmd.Dir = ctx.TownRoot
|
||||
var healthOut bytes.Buffer
|
||||
healthCmd.Stdout = &healthOut
|
||||
_ = healthCmd.Run() // Ignore error, health check is optional
|
||||
|
||||
healthOutput := healthOut.String()
|
||||
if strings.Contains(healthOutput, "HEALTHY") {
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusOK,
|
||||
Message: "bd daemon is running and healthy",
|
||||
}
|
||||
}
|
||||
|
||||
// Daemon running but unhealthy
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusWarning,
|
||||
Message: "bd daemon is running but may be unhealthy",
|
||||
Details: []string{strings.TrimSpace(healthOutput)},
|
||||
}
|
||||
}
|
||||
|
||||
// Daemon is not running - try to start it and capture any errors
|
||||
startErr := c.tryStartDaemon(ctx)
|
||||
if startErr != nil {
|
||||
// Parse the error to provide specific guidance
|
||||
return c.parseStartError(startErr)
|
||||
}
|
||||
|
||||
// Started successfully
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusOK,
|
||||
Message: "bd daemon started successfully",
|
||||
}
|
||||
}
|
||||
|
||||
// tryStartDaemon attempts to start the bd daemon and returns any error output.
|
||||
func (c *BdDaemonCheck) tryStartDaemon(ctx *CheckContext) *startError {
|
||||
cmd := exec.Command("bd", "daemon", "start")
|
||||
cmd.Dir = ctx.TownRoot
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return &startError{
|
||||
output: strings.TrimSpace(stdout.String() + stderr.String()),
|
||||
exitCode: cmd.ProcessState.ExitCode(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// startError holds information about a failed daemon start.
|
||||
type startError struct {
|
||||
output string
|
||||
exitCode int
|
||||
}
|
||||
|
||||
// parseStartError analyzes the error output and returns a helpful CheckResult.
|
||||
func (c *BdDaemonCheck) parseStartError(err *startError) *CheckResult {
|
||||
output := err.output
|
||||
|
||||
// Check for legacy database error
|
||||
if strings.Contains(output, "LEGACY DATABASE DETECTED") {
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusError,
|
||||
Message: "bd daemon failed: legacy database detected",
|
||||
Details: []string{
|
||||
"Database was created before bd version 0.17.5",
|
||||
"Missing repository fingerprint prevents daemon from starting",
|
||||
},
|
||||
FixHint: "Run 'bd migrate --update-repo-id' to add fingerprint",
|
||||
}
|
||||
}
|
||||
|
||||
// Check for database mismatch error
|
||||
if strings.Contains(output, "DATABASE MISMATCH DETECTED") {
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusError,
|
||||
Message: "bd daemon failed: database belongs to different repository",
|
||||
Details: []string{
|
||||
"The .beads database was created for a different git repository",
|
||||
"This can happen if .beads was copied or if the git remote URL changed",
|
||||
},
|
||||
FixHint: "Run 'bd migrate --update-repo-id' if URL changed, or 'rm -rf .beads && bd init' for fresh start",
|
||||
}
|
||||
}
|
||||
|
||||
// Check for already running (not actually an error)
|
||||
if strings.Contains(output, "daemon already running") {
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusOK,
|
||||
Message: "bd daemon is already running",
|
||||
}
|
||||
}
|
||||
|
||||
// Check for permission/lock errors
|
||||
if strings.Contains(output, "lock") || strings.Contains(output, "permission") {
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusError,
|
||||
Message: "bd daemon failed: lock or permission issue",
|
||||
Details: []string{output},
|
||||
FixHint: "Check if another bd daemon is running, or remove .beads/daemon.lock",
|
||||
}
|
||||
}
|
||||
|
||||
// Check for database corruption
|
||||
if strings.Contains(output, "corrupt") || strings.Contains(output, "malformed") {
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusError,
|
||||
Message: "bd daemon failed: database may be corrupted",
|
||||
Details: []string{output},
|
||||
FixHint: "Run 'bd repair' or 'rm .beads/issues.db && bd sync --from-main'",
|
||||
}
|
||||
}
|
||||
|
||||
// Generic error with full output
|
||||
details := []string{output}
|
||||
if output == "" {
|
||||
details = []string{"No error output captured (exit code " + string(rune('0'+err.exitCode)) + ")"}
|
||||
}
|
||||
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusError,
|
||||
Message: "bd daemon failed to start",
|
||||
Details: details,
|
||||
FixHint: "Check 'bd daemon status' and logs in .beads/daemon.log",
|
||||
}
|
||||
}
|
||||
|
||||
// Fix attempts to start the bd daemon.
|
||||
func (c *BdDaemonCheck) Fix(ctx *CheckContext) error {
|
||||
// First check if it's a legacy database issue
|
||||
startErr := c.tryStartDaemon(ctx)
|
||||
if startErr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If legacy database, run migrate first
|
||||
if strings.Contains(startErr.output, "LEGACY DATABASE") ||
|
||||
strings.Contains(startErr.output, "DATABASE MISMATCH") {
|
||||
|
||||
migrateCmd := exec.Command("bd", "migrate", "--update-repo-id", "--yes")
|
||||
migrateCmd.Dir = ctx.TownRoot
|
||||
if err := migrateCmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try starting again
|
||||
startCmd := exec.Command("bd", "daemon", "start")
|
||||
startCmd.Dir = ctx.TownRoot
|
||||
return startCmd.Run()
|
||||
}
|
||||
|
||||
// For other errors, just try to start
|
||||
startCmd := exec.Command("bd", "daemon", "start")
|
||||
startCmd.Dir = ctx.TownRoot
|
||||
return startCmd.Run()
|
||||
}
|
||||
Reference in New Issue
Block a user