This repository has been archived by the owner on Jul 20, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ignore.go
116 lines (91 loc) · 2.26 KB
/
ignore.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"bufio"
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"github.com/gobwas/glob"
)
type IgnoreSet struct {
Entries []IgnoreEntry
}
type IgnoreEntry interface{}
type IgnoreEntryMatch struct {
OriginalPattern string
Pattern string
Glob glob.Glob
}
func (is *IgnoreSet) LoadDirectoryIfExists(dirPath string) error {
filePath := path.Join(dirPath, ".evcli-ignore")
return is.LoadFileIfExists(filePath)
}
func (is *IgnoreSet) LoadFileIfExists(filePath string) error {
data, err := ioutil.ReadFile(filePath)
if errors.Is(err, os.ErrNotExist) {
return nil
} else if err != nil {
return fmt.Errorf("cannot read %s: %w", filePath, err)
}
p.Debug(1, "loading ignore set from %s", filePath)
return is.LoadData(data)
}
func (is *IgnoreSet) LoadData(data []byte) error {
scanner := bufio.NewScanner(bytes.NewReader(data))
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
line := scanner.Text()
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
if line[0] == '#' {
continue
}
if err := is.addPattern(line); err != nil {
return fmt.Errorf("invalid ignore entry %q: %w", line, err)
}
}
return nil
}
func (is *IgnoreSet) addPattern(s0 string) error {
s := s0
if s[0] != '/' && !strings.HasPrefix(s, "**/") {
// "foo/bar" matches "bar" files in a "foo" directory at any depth
// level. We can expand it to "**/foo/bar.
s = "**/" + s
}
if s[len(s)-1] == '/' && !strings.HasSuffix(s, "/**/") {
// "/foo/bar/" means "recursively match all files in the /foo/bar/
// directory". Therefore the glob pattern is "/foo/bar/**".
s += "**"
}
glob, err := glob.Compile(s, '/')
if err != nil {
return fmt.Errorf("invalid glob pattern %q: %w", s, err)
}
entry := IgnoreEntryMatch{
OriginalPattern: s0,
Pattern: s,
Glob: glob,
}
is.Entries = append(is.Entries, entry)
return nil
}
func (is *IgnoreSet) Match(filePath string) (bool, string) {
for _, e := range is.Entries {
switch v := e.(type) {
case IgnoreEntryMatch:
if v.Glob.Match(filePath) {
why := fmt.Sprintf("matches pattern %q", v.OriginalPattern)
return true, why
}
default:
panic(fmt.Errorf("unhandled ignore set entry of type %T", e))
}
}
return false, ""
}