From b844a3b656d90d7f2764fe66c0cb79db9e8179d1 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 10 Jan 2026 13:34:53 -0800 Subject: [PATCH] fix: Windows infinite loop in findLocalBeadsDir and findOriginalBeadsDir (GH#996) Same fix as PR #991 for FindBeadsDir() - the loop condition dir != "/" && dir != "." doesn't handle Windows drive roots. On Windows, filepath.Dir("C:\\") returns "C:\\", not "/" or ".". Changed both functions to check parent == dir to detect filesystem root, which works correctly on both Unix and Windows. Co-Authored-By: Claude Opus 4.5 --- cmd/bd/where.go | 12 +++++++++++- internal/beads/beads.go | 13 ++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cmd/bd/where.go b/cmd/bd/where.go index 9ad567b0..61ca8783 100644 --- a/cmd/bd/where.go +++ b/cmd/bd/where.go @@ -118,7 +118,7 @@ func findOriginalBeadsDir() string { } // Walk up directory tree looking for .beads with redirect - for dir := cwd; dir != "/" && dir != "."; dir = filepath.Dir(dir) { + for dir := cwd; dir != "/" && dir != "."; { beadsDir := filepath.Join(dir, ".beads") if info, err := os.Stat(beadsDir); err == nil && info.IsDir() { redirectFile := filepath.Join(beadsDir, beads.RedirectFileName) @@ -128,6 +128,16 @@ func findOriginalBeadsDir() string { // Found .beads without redirect - this is the actual location return "" } + + // Move up one directory + parent := filepath.Dir(dir) + if parent == dir { + // Reached filesystem root (works on both Unix and Windows) + // On Unix: filepath.Dir("/") returns "/" + // On Windows: filepath.Dir("C:\\") returns "C:\\" + break + } + dir = parent } return "" diff --git a/internal/beads/beads.go b/internal/beads/beads.go index d3761fb3..4219aa31 100644 --- a/internal/beads/beads.go +++ b/internal/beads/beads.go @@ -144,6 +144,7 @@ func findLocalBeadsDir() string { } // Check for worktree - use main repo's .beads + // Note: GetMainRepoRoot() is safe to call outside a git repo - it returns an error mainRepoRoot, err := git.GetMainRepoRoot() if err == nil && mainRepoRoot != "" { beadsDir := filepath.Join(mainRepoRoot, ".beads") @@ -158,11 +159,21 @@ func findLocalBeadsDir() string { return "" } - for dir := cwd; dir != "/" && dir != "."; dir = filepath.Dir(dir) { + for dir := cwd; dir != "/" && dir != "."; { beadsDir := filepath.Join(dir, ".beads") if info, err := os.Stat(beadsDir); err == nil && info.IsDir() { return beadsDir } + + // Move up one directory + parent := filepath.Dir(dir) + if parent == dir { + // Reached filesystem root (works on both Unix and Windows) + // On Unix: filepath.Dir("/") returns "/" + // On Windows: filepath.Dir("C:\\") returns "C:\\" + break + } + dir = parent } return ""