fix: bd sync fails with exit 128 in bare repo worktrees (GH#827)
Two fixes for bare repo worktree setups: 1. fork_protection.go: Use git.GetGitDir() instead of hardcoding .git In worktrees, .git is a file containing gitdir path, not a directory. Using GetGitDir() handles this correctly. 2. sync_git.go: Simplify gitHasBeadsChanges to use absolute paths The previous code used git -C main-repo-root status, but in bare repo worktrees GetMainRepoRoot() returns the parent of the bare repo which is not a valid working tree. Using absolute paths without -C lets git find the repo from cwd, which always works. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
95f14fa827
commit
363c5a3819
@@ -43,8 +43,15 @@ func ensureForkProtection() {
|
|||||||
return // Not a fork of beads, user's own project
|
return // Not a fork of beads, user's own project
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get actual git directory (handles worktrees where .git is a file) (GH#827)
|
||||||
|
gitDir, err := git.GetGitDir()
|
||||||
|
if err != nil {
|
||||||
|
debug.Printf("fork protection: failed to get git dir: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Check if already excluded
|
// Check if already excluded
|
||||||
excludePath := filepath.Join(gitRoot, ".git", "info", "exclude")
|
excludePath := filepath.Join(gitDir, "info", "exclude")
|
||||||
if isAlreadyExcluded(excludePath) {
|
if isAlreadyExcluded(excludePath) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ func getRepoRootForWorktree(_ context.Context) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// gitHasBeadsChanges checks if any tracked files in .beads/ have uncommitted changes
|
// gitHasBeadsChanges checks if any tracked files in .beads/ have uncommitted changes
|
||||||
|
// This function is worktree-aware and handles bare repo worktree setups (GH#827).
|
||||||
func gitHasBeadsChanges(ctx context.Context) (bool, error) {
|
func gitHasBeadsChanges(ctx context.Context) (bool, error) {
|
||||||
// Get the absolute path to .beads directory
|
// Get the absolute path to .beads directory
|
||||||
beadsDir := beads.FindBeadsDir()
|
beadsDir := beads.FindBeadsDir()
|
||||||
@@ -96,26 +97,12 @@ func gitHasBeadsChanges(ctx context.Context) (bool, error) {
|
|||||||
return false, fmt.Errorf("no .beads directory found")
|
return false, fmt.Errorf("no .beads directory found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the repository root (handles worktrees properly)
|
// Run git status with absolute path from current directory.
|
||||||
repoRoot := getRepoRootForWorktree(ctx)
|
// This is more robust than using -C with a repo root, because:
|
||||||
if repoRoot == "" {
|
// 1. In bare repo worktree setups, GetMainRepoRoot() returns the parent
|
||||||
return false, fmt.Errorf("cannot determine repository root")
|
// of the bare repo, which isn't a valid working tree (GH#827)
|
||||||
}
|
// 2. Git will find the repository from cwd, which is always valid
|
||||||
|
statusCmd := exec.CommandContext(ctx, "git", "status", "--porcelain", beadsDir) //nolint:gosec // G204: beadsDir from beads.FindBeadsDir()
|
||||||
// Compute relative path from repo root to .beads
|
|
||||||
relPath, err := filepath.Rel(repoRoot, beadsDir)
|
|
||||||
if err != nil {
|
|
||||||
// Fall back to absolute path if relative path fails
|
|
||||||
statusCmd := exec.CommandContext(ctx, "git", "status", "--porcelain", beadsDir) //nolint:gosec // G204: beadsDir from beads.FindBeadsDir()
|
|
||||||
statusOutput, err := statusCmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("git status failed: %w", err)
|
|
||||||
}
|
|
||||||
return len(strings.TrimSpace(string(statusOutput))) > 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run git status with relative path from repo root
|
|
||||||
statusCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "status", "--porcelain", relPath) //nolint:gosec // G204: paths from internal git helpers
|
|
||||||
statusOutput, err := statusCmd.Output()
|
statusOutput, err := statusCmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("git status failed: %w", err)
|
return false, fmt.Errorf("git status failed: %w", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user