feat: add doctor check for issues.jsonl git tracking (GH#796)
Safeguard for users with global gitignore patterns like *.jsonl that could cause issues.jsonl to be ignored, breaking bd sync. The check runs git check-ignore and warns if issues.jsonl would be ignored by any gitignore rule (global, parent directory, etc).
This commit is contained in:
@@ -401,6 +401,11 @@ func runDiagnostics(path string) doctorResult {
|
|||||||
result.Checks = append(result.Checks, gitignoreCheck)
|
result.Checks = append(result.Checks, gitignoreCheck)
|
||||||
// Don't fail overall check for gitignore, just warn
|
// Don't fail overall check for gitignore, just warn
|
||||||
|
|
||||||
|
// Check 14a: issues.jsonl tracking (catches global gitignore conflicts)
|
||||||
|
issuesTrackingCheck := convertWithCategory(doctor.CheckIssuesTracking(), doctor.CategoryGit)
|
||||||
|
result.Checks = append(result.Checks, issuesTrackingCheck)
|
||||||
|
// Don't fail overall check for tracking issues, just warn
|
||||||
|
|
||||||
// Check 15: Git merge driver configuration
|
// Check 15: Git merge driver configuration
|
||||||
mergeDriverCheck := convertWithCategory(doctor.CheckMergeDriver(path), doctor.CategoryGit)
|
mergeDriverCheck := convertWithCategory(doctor.CheckMergeDriver(path), doctor.CategoryGit)
|
||||||
result.Checks = append(result.Checks, mergeDriverCheck)
|
result.Checks = append(result.Checks, mergeDriverCheck)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package doctor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -120,3 +121,48 @@ func FixGitignore() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckIssuesTracking verifies that issues.jsonl is tracked by git.
|
||||||
|
// This catches cases where global gitignore patterns (e.g., *.jsonl) would
|
||||||
|
// cause issues.jsonl to be ignored, breaking bd sync.
|
||||||
|
func CheckIssuesTracking() DoctorCheck {
|
||||||
|
issuesPath := filepath.Join(".beads", "issues.jsonl")
|
||||||
|
|
||||||
|
// First check if the file exists
|
||||||
|
if _, err := os.Stat(issuesPath); os.IsNotExist(err) {
|
||||||
|
// File doesn't exist yet - not an error, bd init may not have been run
|
||||||
|
return DoctorCheck{
|
||||||
|
Name: "Issues Tracking",
|
||||||
|
Status: "ok",
|
||||||
|
Message: "No issues.jsonl yet (will be created on first issue)",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if git considers this file ignored
|
||||||
|
// git check-ignore exits 0 if ignored, 1 if not ignored, 128 if error
|
||||||
|
cmd := exec.Command("git", "check-ignore", "-q", issuesPath)
|
||||||
|
err := cmd.Run()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
// Exit code 0 means the file IS ignored - this is bad
|
||||||
|
// Get details about what's ignoring it
|
||||||
|
detailCmd := exec.Command("git", "check-ignore", "-v", issuesPath)
|
||||||
|
output, _ := detailCmd.Output()
|
||||||
|
detail := strings.TrimSpace(string(output))
|
||||||
|
|
||||||
|
return DoctorCheck{
|
||||||
|
Name: "Issues Tracking",
|
||||||
|
Status: "warning",
|
||||||
|
Message: "issues.jsonl is ignored by git (bd sync will fail)",
|
||||||
|
Detail: detail,
|
||||||
|
Fix: "Check global gitignore: git config --global core.excludesfile",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit code 1 means not ignored (good), any other error we ignore
|
||||||
|
return DoctorCheck{
|
||||||
|
Name: "Issues Tracking",
|
||||||
|
Status: "ok",
|
||||||
|
Message: "issues.jsonl is tracked by git",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user