...
1 package gitignore
2
3 import (
4 "bufio"
5 "io"
6 "os"
7 "path/filepath"
8 "strings"
9 )
10
11 type IgnoreMatcher interface {
12 Match(path string, isDir bool) bool
13 }
14
15 type DummyIgnoreMatcher bool
16
17 func (d DummyIgnoreMatcher) Match(path string, isDir bool) bool {
18 return bool(d)
19 }
20
21 type gitIgnore struct {
22 ignorePatterns scanStrategy
23 acceptPatterns scanStrategy
24 path string
25 }
26
27 func NewGitIgnore(gitignore string, base ...string) (IgnoreMatcher, error) {
28 var path string
29 if len(base) > 0 {
30 path = base[0]
31 } else {
32 path = filepath.Dir(gitignore)
33 }
34
35 file, err := os.Open(gitignore)
36 if err != nil {
37 return nil, err
38 }
39 defer file.Close()
40
41 return NewGitIgnoreFromReader(path, file), nil
42 }
43
44 func NewGitIgnoreFromReader(path string, r io.Reader) IgnoreMatcher {
45 g := gitIgnore{
46 ignorePatterns: newIndexScanPatterns(),
47 acceptPatterns: newIndexScanPatterns(),
48 path: path,
49 }
50 scanner := bufio.NewScanner(r)
51 for scanner.Scan() {
52 line := strings.Trim(scanner.Text(), " ")
53 if len(line) == 0 || strings.HasPrefix(line, "#") {
54 continue
55 }
56 if strings.HasPrefix(line, `\#`) {
57 line = strings.TrimPrefix(line, `\`)
58 }
59
60 if strings.HasPrefix(line, "!") {
61 g.acceptPatterns.add(strings.TrimPrefix(line, "!"))
62 } else {
63 g.ignorePatterns.add(line)
64 }
65 }
66 return g
67 }
68
69 func (g gitIgnore) Match(path string, isDir bool) bool {
70 relativePath, err := filepath.Rel(g.path, path)
71 if err != nil {
72 return false
73 }
74 relativePath = filepath.ToSlash(relativePath)
75
76 if g.acceptPatterns.match(relativePath, isDir) {
77 return false
78 }
79 return g.ignorePatterns.match(relativePath, isDir)
80 }
81
View as plain text