Enforce canonical database naming (beads.db) - bd-165
- Added CanonicalDatabaseName constant (beads.db) and LegacyDatabaseNames list - Updated bd init to use canonical name via constant - Added daemon validation to reject non-canonical database names - Updated bd migrate to use canonical name constant - Enhanced FindDatabasePath to warn when using legacy database names - All database discovery now prefers beads.db with backward compatibility Closes bd-165
This commit is contained in:
File diff suppressed because one or more lines are too long
71
beads.go
71
beads.go
@@ -19,6 +19,12 @@ import (
|
|||||||
"github.com/steveyegge/beads/internal/types"
|
"github.com/steveyegge/beads/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CanonicalDatabaseName is the required database filename for all beads repositories
|
||||||
|
const CanonicalDatabaseName = "beads.db"
|
||||||
|
|
||||||
|
// LegacyDatabaseNames are old names that should be migrated
|
||||||
|
var LegacyDatabaseNames = []string{"bd.db", "issues.db", "bugs.db"}
|
||||||
|
|
||||||
// Issue represents a tracked work item with metadata, dependencies, and status.
|
// Issue represents a tracked work item with metadata, dependencies, and status.
|
||||||
type (
|
type (
|
||||||
Issue = types.Issue
|
Issue = types.Issue
|
||||||
@@ -184,38 +190,53 @@ func findDatabaseInTree() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to canonical beads.db for backward compatibility
|
// Fall back to canonical beads.db for backward compatibility
|
||||||
canonicalDB := filepath.Join(beadsDir, "beads.db")
|
canonicalDB := filepath.Join(beadsDir, CanonicalDatabaseName)
|
||||||
if _, err := os.Stat(canonicalDB); err == nil {
|
if _, err := os.Stat(canonicalDB); err == nil {
|
||||||
return canonicalDB
|
return canonicalDB
|
||||||
}
|
}
|
||||||
|
|
||||||
// Found .beads/ directory, look for *.db files
|
// Found .beads/ directory, look for *.db files
|
||||||
matches, err := filepath.Glob(filepath.Join(beadsDir, "*.db"))
|
matches, err := filepath.Glob(filepath.Join(beadsDir, "*.db"))
|
||||||
if err == nil && len(matches) > 0 {
|
if err == nil && len(matches) > 0 {
|
||||||
// Filter out backup files
|
// Filter out backup files
|
||||||
var validDBs []string
|
var validDBs []string
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
baseName := filepath.Base(match)
|
baseName := filepath.Base(match)
|
||||||
// Skip backup files (e.g., beads.db.backup, bd.db.backup)
|
// Skip backup files (e.g., beads.db.backup, bd.db.backup)
|
||||||
if filepath.Ext(baseName) != ".backup" {
|
if filepath.Ext(baseName) != ".backup" {
|
||||||
validDBs = append(validDBs, match)
|
validDBs = append(validDBs, match)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(validDBs) > 1 {
|
|
||||||
// Multiple databases found - this is ambiguous
|
|
||||||
// Print error to stderr but return the first one for backward compatibility
|
|
||||||
fmt.Fprintf(os.Stderr, "Warning: Multiple database files found in %s:\n", beadsDir)
|
|
||||||
for _, db := range validDBs {
|
|
||||||
fmt.Fprintf(os.Stderr, " - %s\n", filepath.Base(db))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "Run 'bd init' to migrate to beads.db or manually remove old databases.\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(validDBs) > 0 {
|
|
||||||
return validDBs[0]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(validDBs) > 1 {
|
||||||
|
// Multiple databases found - this is ambiguous
|
||||||
|
// Print error to stderr but return the first one for backward compatibility
|
||||||
|
fmt.Fprintf(os.Stderr, "Warning: Multiple database files found in %s:\n", beadsDir)
|
||||||
|
for _, db := range validDBs {
|
||||||
|
fmt.Fprintf(os.Stderr, " - %s\n", filepath.Base(db))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "Run 'bd init' to migrate to %s or manually remove old databases.\n\n", CanonicalDatabaseName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(validDBs) > 0 {
|
||||||
|
// Check if using legacy name and warn
|
||||||
|
dbName := filepath.Base(validDBs[0])
|
||||||
|
if dbName != CanonicalDatabaseName {
|
||||||
|
isLegacy := false
|
||||||
|
for _, legacy := range LegacyDatabaseNames {
|
||||||
|
if dbName == legacy {
|
||||||
|
isLegacy = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isLegacy {
|
||||||
|
fmt.Fprintf(os.Stderr, "WARNING: Using legacy database name: %s\n", dbName)
|
||||||
|
fmt.Fprintf(os.Stderr, "Run 'bd migrate' to upgrade to canonical name: %s\n\n", CanonicalDatabaseName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return validDBs[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move up one directory
|
// Move up one directory
|
||||||
|
|||||||
@@ -1162,11 +1162,23 @@ func runDaemonLoop(interval time.Duration, autoCommit, autoPush bool, logPath, p
|
|||||||
for _, db := range validDBs {
|
for _, db := range validDBs {
|
||||||
log.log(" - %s", filepath.Base(db))
|
log.log(" - %s", filepath.Base(db))
|
||||||
}
|
}
|
||||||
log.log("Run 'bd init' to migrate to beads.db or manually remove old databases")
|
log.log("")
|
||||||
|
log.log("Beads requires a single canonical database: %s", beads.CanonicalDatabaseName)
|
||||||
|
log.log("Run 'bd init' to migrate legacy databases")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate using canonical name
|
||||||
|
dbBaseName := filepath.Base(daemonDBPath)
|
||||||
|
if dbBaseName != beads.CanonicalDatabaseName {
|
||||||
|
log.log("Error: Non-canonical database name: %s", dbBaseName)
|
||||||
|
log.log("Expected: %s", beads.CanonicalDatabaseName)
|
||||||
|
log.log("")
|
||||||
|
log.log("Run 'bd init' to migrate to canonical name")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
log.log("Using database: %s", daemonDBPath)
|
log.log("Using database: %s", daemonDBPath)
|
||||||
|
|
||||||
store, err := sqlite.New(daemonDBPath)
|
store, err := sqlite.New(daemonDBPath)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/steveyegge/beads"
|
||||||
"github.com/steveyegge/beads/internal/configfile"
|
"github.com/steveyegge/beads/internal/configfile"
|
||||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||||
)
|
)
|
||||||
@@ -48,7 +49,7 @@ and database file. Optionally specify a custom issue prefix.`,
|
|||||||
// Use global dbPath if set via --db flag or BEADS_DB env var, otherwise default to .beads/beads.db
|
// Use global dbPath if set via --db flag or BEADS_DB env var, otherwise default to .beads/beads.db
|
||||||
initDBPath := dbPath
|
initDBPath := dbPath
|
||||||
if initDBPath == "" {
|
if initDBPath == "" {
|
||||||
initDBPath = filepath.Join(".beads", "beads.db")
|
initDBPath = filepath.Join(".beads", beads.CanonicalDatabaseName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate old database files if they exist
|
// Migrate old database files if they exist
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/steveyegge/beads"
|
||||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
@@ -73,7 +74,7 @@ This command:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if beads.db exists and is current
|
// Check if beads.db exists and is current
|
||||||
targetPath := filepath.Join(beadsDir, "beads.db")
|
targetPath := filepath.Join(beadsDir, beads.CanonicalDatabaseName)
|
||||||
var currentDB *dbInfo
|
var currentDB *dbInfo
|
||||||
var oldDBs []*dbInfo
|
var oldDBs []*dbInfo
|
||||||
|
|
||||||
@@ -271,7 +272,7 @@ This command:
|
|||||||
if jsonOutput {
|
if jsonOutput {
|
||||||
outputJSON(map[string]interface{}{
|
outputJSON(map[string]interface{}{
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"current_database": "beads.db",
|
"current_database": beads.CanonicalDatabaseName,
|
||||||
"version": Version,
|
"version": Version,
|
||||||
"migrated": needsMigration,
|
"migrated": needsMigration,
|
||||||
"version_updated": needsVersionUpdate,
|
"version_updated": needsVersionUpdate,
|
||||||
|
|||||||
Reference in New Issue
Block a user