fix(git): handle non-tracked files gracefully in diff operations

- Return empty line ranges when git diff fails for non-tracked files
- Prevents hook failures on .claude/settings.local.json and similar files
- Improves robustness when processing files outside git tracking
This commit is contained in:
carraes
2025-07-05 23:44:10 -03:00
parent 20135b3a7f
commit 62790b245e
+6 -22
View File
@@ -9,8 +9,6 @@ import (
"strings"
)
func DetectRepo() (*GitStatus, error) {
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
output, err := cmd.Output()
@@ -25,7 +23,6 @@ func DetectRepo() (*GitStatus, error) {
}, nil
}
func GetStagedChanges() ([]FileChange, error) {
cmd := exec.Command("git", "diff", "--cached", "--name-only")
@@ -36,7 +33,7 @@ func GetStagedChanges() ([]FileChange, error) {
files := strings.Split(strings.TrimSpace(string(output)), "\n")
if len(files) == 1 && files[0] == "" {
return []FileChange{}, nil
return []FileChange{}, nil
}
var changes []FileChange
@@ -45,7 +42,6 @@ return []FileChange{}, nil
continue
}
lineRanges, err := getLineRangesFromDiff(file, true)
if err != nil {
return nil, fmt.Errorf("failed to get line ranges for %s: %v", file, err)
@@ -61,11 +57,9 @@ return []FileChange{}, nil
return changes, nil
}
func GetUnstagedChanges() ([]FileChange, error) {
var changes []FileChange
cmd := exec.Command("git", "diff", "--name-only")
output, err := cmd.Output()
if err != nil {
@@ -78,7 +72,6 @@ func GetUnstagedChanges() ([]FileChange, error) {
continue
}
lineRanges, err := getLineRangesFromDiff(file, false)
if err != nil {
return nil, fmt.Errorf("failed to get line ranges for %s: %v", file, err)
@@ -91,7 +84,6 @@ func GetUnstagedChanges() ([]FileChange, error) {
})
}
cmd = exec.Command("git", "ls-files", "--others", "--exclude-standard")
output, err = cmd.Output()
if err != nil {
@@ -104,18 +96,16 @@ func GetUnstagedChanges() ([]FileChange, error) {
continue
}
changes = append(changes, FileChange{
Path: file,
Status: StatusUntracked,
LineRanges: []LineRange{},
LineRanges: []LineRange{},
})
}
return changes, nil
}
func getLineRangesFromDiff(file string, staged bool) ([]LineRange, error) {
var cmd *exec.Cmd
if staged {
@@ -126,18 +116,17 @@ func getLineRangesFromDiff(file string, staged bool) ([]LineRange, error) {
output, err := cmd.Output()
if err != nil {
return nil, err
return []LineRange{}, nil
}
return ParseDiffUnified(string(output))
}
func ParseDiffUnified(diff string) ([]LineRange, error) {
var ranges []LineRange
headerRegex := regexp.MustCompile(`@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@`)
scanner := bufio.NewScanner(strings.NewReader(diff))
@@ -154,7 +143,7 @@ func ParseDiffUnified(diff string) ([]LineRange, error) {
var newCount int
if matches[4] == "" {
newCount = 1
newCount = 1
} else {
newCount, err = strconv.Atoi(matches[4])
if err != nil {
@@ -162,7 +151,6 @@ newCount = 1
}
}
if newCount > 0 {
ranges = append(ranges, LineRange{
Start: newStart,
@@ -175,7 +163,6 @@ newCount = 1
return ranges, scanner.Err()
}
func IsInLineRanges(lineNum int, ranges []LineRange) bool {
for _, r := range ranges {
if lineNum >= r.Start && lineNum <= r.End {
@@ -185,18 +172,15 @@ func IsInLineRanges(lineNum int, ranges []LineRange) bool {
return false
}
func GetChangesOnly() ([]FileChange, error) {
var allChanges []FileChange
staged, err := GetStagedChanges()
if err != nil {
return nil, fmt.Errorf("failed to get staged changes: %v", err)
}
allChanges = append(allChanges, staged...)
unstaged, err := GetUnstagedChanges()
if err != nil {
return nil, fmt.Errorf("failed to get unstaged changes: %v", err)