fix(beads): also fix FindJSONLPath to skip deletions.jsonl (bd-tqo)
Code review follow-up: - Fix misleading docstring in FindJSONLInDir (does not return empty) - Fix same bug in beads.FindJSONLPath (also fell back to matches[0]) - Add comprehensive tests for FindJSONLPath skipping deletions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -298,7 +298,7 @@ func CheckStaleness(ctx context.Context, store storage.Storage, dbPath string) (
|
|||||||
// FindJSONLInDir finds the JSONL file in the given directory.
|
// FindJSONLInDir finds the JSONL file in the given directory.
|
||||||
// It prefers issues.jsonl over other .jsonl files to prevent accidentally
|
// It prefers issues.jsonl over other .jsonl files to prevent accidentally
|
||||||
// reading/writing to deletions.jsonl or merge artifacts (bd-tqo fix).
|
// reading/writing to deletions.jsonl or merge artifacts (bd-tqo fix).
|
||||||
// Returns empty string if no suitable JSONL file is found.
|
// Always returns a path (defaults to issues.jsonl if nothing suitable found).
|
||||||
func FindJSONLInDir(dbDir string) string {
|
func FindJSONLInDir(dbDir string) string {
|
||||||
pattern := filepath.Join(dbDir, "*.jsonl")
|
pattern := filepath.Join(dbDir, "*.jsonl")
|
||||||
matches, err := filepath.Glob(pattern)
|
matches, err := filepath.Glob(pattern)
|
||||||
|
|||||||
@@ -281,8 +281,24 @@ func FindJSONLPath(dbPath string) string {
|
|||||||
return match
|
return match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return the first .jsonl file found if issues.jsonl not present
|
// bd-tqo: Fall back to beads.jsonl for legacy support
|
||||||
return matches[0]
|
for _, match := range matches {
|
||||||
|
if filepath.Base(match) == "beads.jsonl" {
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// bd-tqo: Skip deletions.jsonl and merge artifacts to prevent corruption
|
||||||
|
for _, match := range matches {
|
||||||
|
base := filepath.Base(match)
|
||||||
|
if base == "deletions.jsonl" ||
|
||||||
|
base == "beads.base.jsonl" ||
|
||||||
|
base == "beads.left.jsonl" ||
|
||||||
|
base == "beads.right.jsonl" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
// If only deletions/merge files exist, fall through to default
|
||||||
}
|
}
|
||||||
|
|
||||||
// bd-6xd: Default to issues.jsonl (canonical name)
|
// bd-6xd: Default to issues.jsonl (canonical name)
|
||||||
|
|||||||
@@ -220,6 +220,68 @@ func TestFindJSONLPathMultipleFiles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFindJSONLPathSkipsDeletions verifies that FindJSONLPath skips deletions.jsonl
|
||||||
|
// and merge artifacts to prevent corruption (bd-tqo fix)
|
||||||
|
func TestFindJSONLPathSkipsDeletions(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
files []string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "prefers issues.jsonl over deletions.jsonl",
|
||||||
|
files: []string{"deletions.jsonl", "issues.jsonl"},
|
||||||
|
expected: "issues.jsonl",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "skips deletions.jsonl when only option",
|
||||||
|
files: []string{"deletions.jsonl"},
|
||||||
|
expected: "issues.jsonl", // Falls back to default
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "skips merge artifacts",
|
||||||
|
files: []string{"beads.base.jsonl", "beads.left.jsonl", "issues.jsonl"},
|
||||||
|
expected: "issues.jsonl",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prefers issues over beads",
|
||||||
|
files: []string{"beads.jsonl", "issues.jsonl"},
|
||||||
|
expected: "issues.jsonl",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "uses beads.jsonl as legacy fallback",
|
||||||
|
files: []string{"beads.jsonl", "deletions.jsonl"},
|
||||||
|
expected: "beads.jsonl",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tmpDir, err := os.MkdirTemp("", "beads-jsonl-test-*")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
// Create test files
|
||||||
|
for _, file := range tt.files {
|
||||||
|
path := filepath.Join(tmpDir, file)
|
||||||
|
if err := os.WriteFile(path, []byte("{}"), 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbPath := filepath.Join(tmpDir, "test.db")
|
||||||
|
result := FindJSONLPath(dbPath)
|
||||||
|
expected := filepath.Join(tmpDir, tt.expected)
|
||||||
|
|
||||||
|
if result != expected {
|
||||||
|
t.Errorf("FindJSONLPath() = %q, want %q", result, expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFindDatabasePathHomeDefault(t *testing.T) {
|
func TestFindDatabasePathHomeDefault(t *testing.T) {
|
||||||
// This test verifies that if no database is found, it falls back to home directory
|
// This test verifies that if no database is found, it falls back to home directory
|
||||||
// We can't reliably test this without modifying the home directory, so we'll skip
|
// We can't reliably test this without modifying the home directory, so we'll skip
|
||||||
|
|||||||
Reference in New Issue
Block a user