Files
gh-commit/internal/diff/filter.go
T
t 9647c854c9 feat: rewrite gh-commit in Go with local Ollama backend
Replaces the Python/Crush/DuckDB implementation with a CGO-free Go binary:
cobra CLI, modernc.org/sqlite storage, huh/lipgloss UI, and speed-tuned raw
/api/generate calls (think:false, keep_alive, capped num_predict) against a
local qwen3.5:2b. Ships as a gh extension via cli/gh-extension-precompile.
2026-08-15 19:10:16 -04:00

102 lines
2.8 KiB
Go

// Package diff filters git diffs before they reach the model: lock/generated
// files lose their hunk bodies, JSON changes are capped, and every other file
// is truncated. Behavior is a verbatim port of the Python filter_diff.
package diff
import (
"fmt"
"regexp"
"strings"
)
var lockPattern = regexp.MustCompile(
`(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb|` +
`go\.sum|go\.mod|Cargo\.lock|poetry\.lock|composer\.lock|Gemfile\.lock|` +
`.*\.min\.(js|css)|.*\.bundle\.js|.*\.map|` +
`dist/.*|build/.*|\.next/.*|node_modules/.*|vendor/.*|__pycache__/.*|\.pyc$|target/.*)`,
)
var (
fileNameRe = regexp.MustCompile(`b/([^ ]+)`)
headerRe = regexp.MustCompile(`^(index|---|\+\+\+|@@)`)
)
const (
// MaxDiffLines caps the per-file line count for regular files.
MaxDiffLines = 200
// MaxJSONLines caps the +/- line count for JSON files.
MaxJSONLines = 50
)
// Filter rewrites a raw git diff for prompt consumption.
func Filter(diff string) string {
var lines []string
inFiltered, inJSON := false, false
lineCount, jsonCount := 0, 0
for _, line := range strings.Split(diff, "\n") {
if strings.HasPrefix(line, "diff --git") {
lineCount, jsonCount = 0, 0
filename := ""
if m := fileNameRe.FindStringSubmatch(line); m != nil {
filename = m[1]
}
switch {
case lockPattern.MatchString(filename):
inFiltered, inJSON = true, false
lines = append(lines, line)
continue
case strings.HasSuffix(filename, ".json"):
inFiltered, inJSON = false, true
lines = append(lines, line)
continue
default:
inFiltered, inJSON = false, false
}
}
// Lock/generated files: keep headers, replace each hunk body with a
// marker. (The Python original stopped filtering after the first @@,
// leaking hunk bodies; the spec requires bodies replaced, so filtering
// holds until the next "diff --git".)
if inFiltered {
if headerRe.MatchString(line) {
lines = append(lines, line)
if strings.HasPrefix(line, "@@") {
lines = append(lines, "[Generated/lock file - content filtered]")
}
}
continue
}
if inJSON {
if headerRe.MatchString(line) {
lines = append(lines, line)
continue
}
if strings.HasPrefix(line, "+") || strings.HasPrefix(line, "-") {
jsonCount++
if jsonCount <= MaxJSONLines {
lines = append(lines, line)
} else if jsonCount == MaxJSONLines+1 {
lines = append(lines, fmt.Sprintf("[... JSON truncated after %d lines ...]", MaxJSONLines))
}
} else {
lines = append(lines, line)
}
continue
}
if lineCount < MaxDiffLines {
lines = append(lines, line)
lineCount++
} else if lineCount == MaxDiffLines {
lines = append(lines, fmt.Sprintf("[... truncated after %d lines ...]", MaxDiffLines))
lineCount++
}
}
return strings.Join(lines, "\n")
}