fix: bd sync fails to copy local changes TO beads-sync worktree (#810)
The bug: In a bare repo + worktrees setup, jsonlRelPath was calculated relative to the project root (containing all worktrees), resulting in paths like "main/.beads/issues.jsonl". But the sync branch worktree uses sparse checkout for .beads/*, so files are at ".beads/issues.jsonl". This caused SyncJSONLToWorktreeWithOptions to write to the wrong location (e.g., worktree/main/.beads/ instead of worktree/.beads/), so changes made locally never reached the sync branch worktree. #785 fixed the reverse direction (worktree → local) by adding normalizeBeadsRelPath(), but the local → worktree direction was missed. Fix: - Export NormalizeBeadsRelPath() (uppercase) for cross-package use - Apply normalization in SyncJSONLToWorktreeWithOptions for dstPath - Apply normalization in daemon_sync_branch.go for worktreeJSONLPath in both commit and pull paths - Add unit tests for the normalization function 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1130,3 +1130,62 @@ func TestCreateBeadsWorktree_MissingButRegistered(t *testing.T) {
|
||||
t.Errorf("Recreated worktree should be valid: valid=%v, err=%v", valid, err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalizeBeadsRelPath tests path normalization for bare repo worktrees (GH#785, GH#810)
|
||||
func TestNormalizeBeadsRelPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "already normalized path",
|
||||
input: ".beads/issues.jsonl",
|
||||
expected: ".beads/issues.jsonl",
|
||||
},
|
||||
{
|
||||
name: "worktree prefix - main",
|
||||
input: "main/.beads/issues.jsonl",
|
||||
expected: ".beads/issues.jsonl",
|
||||
},
|
||||
{
|
||||
name: "worktree prefix - feature branch",
|
||||
input: "feat-tts-config/.beads/issues.jsonl",
|
||||
expected: ".beads/issues.jsonl",
|
||||
},
|
||||
{
|
||||
name: "nested worktree prefix",
|
||||
input: "worktrees/feature/.beads/issues.jsonl",
|
||||
expected: ".beads/issues.jsonl",
|
||||
},
|
||||
{
|
||||
name: "metadata file",
|
||||
input: "main/.beads/metadata.json",
|
||||
expected: ".beads/metadata.json",
|
||||
},
|
||||
{
|
||||
name: "no .beads in path",
|
||||
input: "some/other/path.jsonl",
|
||||
expected: "some/other/path.jsonl",
|
||||
},
|
||||
{
|
||||
name: "only .beads dir (no trailing slash - not normalized)",
|
||||
input: ".beads",
|
||||
expected: ".beads",
|
||||
},
|
||||
{
|
||||
name: "empty path",
|
||||
input: "",
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := NormalizeBeadsRelPath(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("NormalizeBeadsRelPath(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user