internal/ignore/ignore.go
Ref: Size: 1.3 KiB
package ignore
import (
"os"
"path/filepath"
"slices"
"strings"
"sync"
gitignore "github.com/sabhiram/go-gitignore"
)
var hardExcludeDirs = []string{
".git", "node_modules", "dist", "build", "target", ".venv",
}
var hardExcludeSuffixes = []string{
".swp", ".tmp", ".lock",
}
type Matcher struct {
root string
mu sync.RWMutex
gi *gitignore.GitIgnore
}
func New(root string) (*Matcher, error) {
m := &Matcher{root: root}
if err := m.Reload(); err != nil {
return nil, err
}
return m, nil
}
func (m *Matcher) Reload() error {
path := filepath.Join(m.root, ".gitignore")
var gi *gitignore.GitIgnore
if _, err := os.Stat(path); err == nil {
loaded, err := gitignore.CompileIgnoreFile(path)
if err != nil {
return err
}
gi = loaded
}
m.mu.Lock()
m.gi = gi
m.mu.Unlock()
return nil
}
func (m *Matcher) ShouldIgnore(path string) bool {
rel, err := filepath.Rel(m.root, path)
if err != nil || strings.HasPrefix(rel, "..") {
return true
}
for p := range strings.SplitSeq(rel, string(filepath.Separator)) {
if slices.Contains(hardExcludeDirs, p) {
return true
}
}
base := filepath.Base(rel)
for _, sfx := range hardExcludeSuffixes {
if strings.HasSuffix(base, sfx) {
return true
}
}
m.mu.RLock()
gi := m.gi
m.mu.RUnlock()
if gi != nil && gi.MatchesPath(rel) {
return true
}
return false
}