mirror of
https://github.com/go-task/task.git
synced 2026-06-30 16:14:19 +00:00
93 lines
1.8 KiB
Go
93 lines
1.8 KiB
Go
package fingerprint
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
ignore "github.com/sabhiram/go-gitignore"
|
|
)
|
|
|
|
type gitignoreRule struct {
|
|
dir string
|
|
matcher *ignore.GitIgnore
|
|
}
|
|
|
|
// loadGitignoreRules walks up from dir collecting .gitignore files.
|
|
// Stops at the first .git (file or directory) found.
|
|
// Returns nil if no .git is found (not in a git repo).
|
|
func loadGitignoreRules(dir string) []gitignoreRule {
|
|
dir, _ = filepath.Abs(dir)
|
|
|
|
var rules []gitignoreRule
|
|
foundGit := false
|
|
current := dir
|
|
|
|
for {
|
|
lines := readGitignoreLines(filepath.Join(current, ".gitignore"))
|
|
if len(lines) > 0 {
|
|
rules = append(rules, gitignoreRule{
|
|
dir: current,
|
|
matcher: ignore.CompileIgnoreLines(lines...),
|
|
})
|
|
}
|
|
if _, err := os.Stat(filepath.Join(current, ".git")); err == nil {
|
|
foundGit = true
|
|
break
|
|
}
|
|
parent := filepath.Dir(current)
|
|
if parent == current {
|
|
break
|
|
}
|
|
current = parent
|
|
}
|
|
|
|
if !foundGit {
|
|
return nil
|
|
}
|
|
|
|
return rules
|
|
}
|
|
|
|
func readGitignoreLines(path string) []string {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer f.Close()
|
|
|
|
var lines []string
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if line != "" && !strings.HasPrefix(line, "#") {
|
|
lines = append(lines, line)
|
|
}
|
|
}
|
|
return lines
|
|
}
|
|
|
|
// filterGitignored removes entries from the file map that match gitignore rules.
|
|
func filterGitignored(files map[string]bool, dir string) map[string]bool {
|
|
rules := loadGitignoreRules(dir)
|
|
if len(rules) == 0 {
|
|
return files
|
|
}
|
|
|
|
for path := range files {
|
|
for _, rule := range rules {
|
|
relPath, err := filepath.Rel(rule.dir, path)
|
|
if err != nil || strings.HasPrefix(relPath, "..") {
|
|
continue
|
|
}
|
|
if rule.matcher.MatchesPath(filepath.ToSlash(relPath)) {
|
|
files[path] = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return files
|
|
}
|