Remove ~/.beads fallback behavior
- Remove ~/.beads/default.db fallback from FindDatabasePath() - Update daemon to error if no database found instead of falling back - Update main.go to require explicit database initialization - Add help/version/quickstart to commands that don't need database - Add MCP client debug logging for database routing Amp-Thread-ID: https://ampcode.com/threads/T-2b757a14-cf10-400e-a83c-30349182dd82 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
13
beads.go
13
beads.go
@@ -53,9 +53,8 @@ func NewSQLiteStorage(dbPath string) (Storage, error) {
|
|||||||
// FindDatabasePath discovers the bd database path using bd's standard search order:
|
// FindDatabasePath discovers the bd database path using bd's standard search order:
|
||||||
// 1. $BEADS_DB environment variable
|
// 1. $BEADS_DB environment variable
|
||||||
// 2. .beads/*.db in current directory or ancestors
|
// 2. .beads/*.db in current directory or ancestors
|
||||||
// 3. ~/.beads/default.db (fallback)
|
|
||||||
//
|
//
|
||||||
// Returns empty string if no database is found at (1) or (2) and (3) doesn't exist.
|
// Returns empty string if no database is found.
|
||||||
func FindDatabasePath() string {
|
func FindDatabasePath() string {
|
||||||
// 1. Check environment variable
|
// 1. Check environment variable
|
||||||
if envDB := os.Getenv("BEADS_DB"); envDB != "" {
|
if envDB := os.Getenv("BEADS_DB"); envDB != "" {
|
||||||
@@ -67,15 +66,7 @@ func FindDatabasePath() string {
|
|||||||
return foundDB
|
return foundDB
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Try home directory default
|
// No fallback to ~/.beads - return empty string
|
||||||
if home, err := os.UserHomeDir(); err == nil {
|
|
||||||
defaultDB := filepath.Join(home, ".beads", "default.db")
|
|
||||||
// Only return if it exists
|
|
||||||
if _, err := os.Stat(defaultDB); err == nil {
|
|
||||||
return defaultDB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,11 +115,8 @@ func ensureBeadsDir() (string, error) {
|
|||||||
if dbPath != "" {
|
if dbPath != "" {
|
||||||
beadsDir = filepath.Dir(dbPath)
|
beadsDir = filepath.Dir(dbPath)
|
||||||
} else {
|
} else {
|
||||||
home, err := os.UserHomeDir()
|
// No database path - error out instead of falling back to ~/.beads
|
||||||
if err != nil {
|
return "", fmt.Errorf("no database path configured (run 'bd init' or set BEADS_DB)")
|
||||||
return "", fmt.Errorf("cannot resolve home directory: %w", err)
|
|
||||||
}
|
|
||||||
beadsDir = filepath.Join(home, ".beads")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(beadsDir, 0700); err != nil {
|
if err := os.MkdirAll(beadsDir, 0700); err != nil {
|
||||||
@@ -446,13 +443,10 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush bool, logPath, p
|
|||||||
if foundDB := beads.FindDatabasePath(); foundDB != "" {
|
if foundDB := beads.FindDatabasePath(); foundDB != "" {
|
||||||
daemonDBPath = foundDB
|
daemonDBPath = foundDB
|
||||||
} else {
|
} else {
|
||||||
// Fallback to default location
|
// No database found - error out instead of falling back to ~/.beads
|
||||||
home, err := os.UserHomeDir()
|
log("Error: no beads database found")
|
||||||
if err != nil {
|
log("Hint: run 'bd init' to create a database or set BEADS_DB environment variable")
|
||||||
log("Error: cannot resolve home directory: %v", err)
|
os.Exit(1)
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
daemonDBPath = filepath.Join(home, ".beads", "default.db")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ var rootCmd = &cobra.Command{
|
|||||||
Short: "bd - Dependency-aware issue tracker",
|
Short: "bd - Dependency-aware issue tracker",
|
||||||
Long: `Issues chained together like beads. A lightweight issue tracker with first-class dependency support.`,
|
Long: `Issues chained together like beads. A lightweight issue tracker with first-class dependency support.`,
|
||||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Skip database initialization for init and daemon commands
|
// Skip database initialization for commands that don't need a database
|
||||||
if cmd.Name() == "init" || cmd.Name() == "daemon" {
|
if cmd.Name() == "init" || cmd.Name() == "daemon" || cmd.Name() == "help" || cmd.Name() == "version" || cmd.Name() == "quickstart" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +72,11 @@ var rootCmd = &cobra.Command{
|
|||||||
if foundDB := beads.FindDatabasePath(); foundDB != "" {
|
if foundDB := beads.FindDatabasePath(); foundDB != "" {
|
||||||
dbPath = foundDB
|
dbPath = foundDB
|
||||||
} else {
|
} else {
|
||||||
// Fallback to default location (will be created by init command)
|
// No database found - error out instead of falling back to ~/.beads
|
||||||
home, _ := os.UserHomeDir()
|
fmt.Fprintf(os.Stderr, "Error: no beads database found\n")
|
||||||
dbPath = filepath.Join(home, ".beads", "default.db")
|
fmt.Fprintf(os.Stderr, "Hint: run 'bd init' to create a database in the current directory\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " or set BEADS_DB environment variable to specify a database\n")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,12 +149,20 @@ class BdClient:
|
|||||||
"""
|
"""
|
||||||
cmd = [self.bd_path, *args, *self._global_flags(), "--json"]
|
cmd = [self.bd_path, *args, *self._global_flags(), "--json"]
|
||||||
|
|
||||||
|
# Log database routing for debugging
|
||||||
|
import sys
|
||||||
|
working_dir = self._get_working_dir()
|
||||||
|
db_info = self.beads_db if self.beads_db else "auto-discover"
|
||||||
|
print(f"[beads-mcp] Running bd command: {' '.join(args)}", file=sys.stderr)
|
||||||
|
print(f"[beads-mcp] Database: {db_info}", file=sys.stderr)
|
||||||
|
print(f"[beads-mcp] Working dir: {working_dir}", file=sys.stderr)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
process = await asyncio.create_subprocess_exec(
|
process = await asyncio.create_subprocess_exec(
|
||||||
*cmd,
|
*cmd,
|
||||||
stdout=asyncio.subprocess.PIPE,
|
stdout=asyncio.subprocess.PIPE,
|
||||||
stderr=asyncio.subprocess.PIPE,
|
stderr=asyncio.subprocess.PIPE,
|
||||||
cwd=self._get_working_dir(),
|
cwd=working_dir,
|
||||||
)
|
)
|
||||||
stdout, stderr = await process.communicate()
|
stdout, stderr = await process.communicate()
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user