b0dc6d0c09
CI / test (pull_request) Successful in 14s
CI / review (gpt-4.1, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 23s
CI / review (gpt-5, security, SECURITY_REVIEW.md, SONNET_REVIEW_TOKEN) (pull_request) Successful in 55s
CI / review (gpt-5, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m42s
- Hunk headers without comma ("@@ -1 +1 @@") now parse correctly by
splitting on comma OR space instead of comma only
- Explicit skip for "\ No newline at end of file" lines (was already
safe but now documents intent)
- Tests added for both edge cases (TDD: tests written first, confirmed
failure, then fixed)
Addresses sonnet findings #1 and #2 from PR #26 review.
86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
package gitea
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// DiffLineRanges maps filenames to the set of new-file line numbers present in the diff.
|
|
type DiffLineRanges struct {
|
|
files map[string]map[int]bool
|
|
}
|
|
|
|
// Contains reports whether the given file+line is within the diff hunks.
|
|
func (d *DiffLineRanges) Contains(file string, line int) bool {
|
|
if d == nil || d.files == nil {
|
|
return false
|
|
}
|
|
lines, ok := d.files[file]
|
|
if !ok {
|
|
return false
|
|
}
|
|
return lines[line]
|
|
}
|
|
|
|
// ParseDiffNewLines parses a unified diff and extracts the new-file line numbers
|
|
// that appear in each hunk (both added and context lines).
|
|
func ParseDiffNewLines(diff string) *DiffLineRanges {
|
|
result := &DiffLineRanges{files: make(map[string]map[int]bool)}
|
|
|
|
var currentFile string
|
|
var newLine int
|
|
|
|
for _, line := range strings.Split(diff, "\n") {
|
|
// Track current file from +++ header
|
|
if strings.HasPrefix(line, "+++ b/") {
|
|
currentFile = strings.TrimPrefix(line, "+++ b/")
|
|
if result.files[currentFile] == nil {
|
|
result.files[currentFile] = make(map[int]bool)
|
|
}
|
|
continue
|
|
}
|
|
if strings.HasPrefix(line, "+++ /dev/null") {
|
|
currentFile = ""
|
|
continue
|
|
}
|
|
|
|
// Parse hunk header: @@ -old,count +new,count @@ or @@ -old +new @@
|
|
if strings.HasPrefix(line, "@@") && currentFile != "" {
|
|
// Extract the +N part — handle both "+10,8" and "+1" forms
|
|
parts := strings.Split(line, "+")
|
|
if len(parts) >= 2 {
|
|
// Take everything before comma or space
|
|
numStr := parts[1]
|
|
if idx := strings.IndexAny(numStr, ", "); idx != -1 {
|
|
numStr = numStr[:idx]
|
|
}
|
|
n, err := strconv.Atoi(numStr)
|
|
if err == nil {
|
|
newLine = n
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
if currentFile == "" {
|
|
continue
|
|
}
|
|
|
|
// Skip diff metadata lines
|
|
if strings.HasPrefix(line, "\\") {
|
|
continue
|
|
}
|
|
|
|
// Count lines in hunk
|
|
if strings.HasPrefix(line, "+") || strings.HasPrefix(line, " ") {
|
|
result.files[currentFile][newLine] = true
|
|
newLine++
|
|
} else if strings.HasPrefix(line, "-") {
|
|
// Removed lines don't advance new line counter
|
|
continue
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|