Refactor: Extract path canonicalization into utils.CanonicalizePath()

Extracts duplicated path canonicalization logic (filepath.Abs + EvalSymlinks)
into a reusable helper function utils.CanonicalizePath() in internal/utils/path.go.

Changes:
- Add internal/utils/path.go with CanonicalizePath() function
- Add comprehensive tests in internal/utils/path_test.go
- Replace inline canonicalization in beads.go:131-140
- Replace inline canonicalization in cmd/bd/main.go:446-454
- Replace inline canonicalization in cmd/bd/nodb.go:25-33

The new helper maintains identical behavior:
1. Converts path to absolute form via filepath.Abs
2. Resolves symlinks via filepath.EvalSymlinks
3. Falls back gracefully on errors (returns absPath if EvalSymlinks fails,
   returns original path if Abs fails)

Fixes bd-efe8

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-11-02 18:51:25 -08:00
parent e5f1e4b971
commit 22756509cc
5 changed files with 145 additions and 28 deletions

View File

@@ -15,6 +15,7 @@ import (
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/storage/memory"
"github.com/steveyegge/beads/internal/storage/sqlite"
"github.com/steveyegge/beads/internal/utils"
)
// DaemonStatus captures daemon connection state for the current command
@@ -443,15 +444,7 @@ var rootCmd = &cobra.Command{
var beadsDir string
if envDir := os.Getenv("BEADS_DIR"); envDir != "" {
// Canonicalize the path
if absDir, err := filepath.Abs(envDir); err == nil {
if canonical, err := filepath.EvalSymlinks(absDir); err == nil {
beadsDir = canonical
} else {
beadsDir = absDir
}
} else {
beadsDir = envDir
}
beadsDir = utils.CanonicalizePath(envDir)
} else {
// Fall back to current directory
cwd, err := os.Getwd()

View File

@@ -12,6 +12,7 @@ import (
"github.com/steveyegge/beads/internal/config"
"github.com/steveyegge/beads/internal/storage/memory"
"github.com/steveyegge/beads/internal/types"
"github.com/steveyegge/beads/internal/utils"
)
// initializeNoDbMode sets up in-memory storage from JSONL file
@@ -23,15 +24,7 @@ func initializeNoDbMode() error {
// Check BEADS_DIR environment variable first
if envDir := os.Getenv("BEADS_DIR"); envDir != "" {
// Canonicalize the path
if absDir, err := filepath.Abs(envDir); err == nil {
if canonical, err := filepath.EvalSymlinks(absDir); err == nil {
beadsDir = canonical
} else {
beadsDir = absDir
}
} else {
beadsDir = envDir
}
beadsDir = utils.CanonicalizePath(envDir)
} else {
// Fall back to current directory
cwd, err := os.Getwd()