-
Notifications
You must be signed in to change notification settings - Fork 288
/
path_matcher.go
151 lines (127 loc) · 3.99 KB
/
path_matcher.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package ignore
import (
"context"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/windmilleng/tilt/internal/dockerignore"
"github.com/windmilleng/tilt/internal/git"
"github.com/windmilleng/tilt/internal/model"
"github.com/windmilleng/tilt/internal/ospath"
)
type fileChangeFilter struct {
ignoreMatchers model.PathMatcher
}
func (fcf fileChangeFilter) Matches(f string, isDir bool) (bool, error) {
return fcf.ignoreMatchers.Matches(f, isDir)
}
type repoTarget interface {
LocalRepos() []model.LocalGitRepo
Dockerignores() []model.Dockerignore
TiltFilename() string
}
// Filter out files that should not be included in the build context.
func CreateBuildContextFilter(m repoTarget) model.PathMatcher {
matchers := []model.PathMatcher{}
if m.TiltFilename() != "" {
m, err := model.NewSimpleFileMatcher(m.TiltFilename())
if err == nil {
matchers = append(matchers, m)
}
}
for _, r := range m.LocalRepos() {
gim, err := git.NewRepoIgnoreTester(context.Background(), r.LocalPath)
if err == nil {
matchers = append(matchers, gim)
}
}
for _, r := range m.Dockerignores() {
dim, err := dockerignore.DockerIgnoreTesterFromContents(r.LocalPath, r.Contents)
if err == nil {
matchers = append(matchers, dim)
}
}
return model.NewCompositeMatcher(matchers)
}
type IgnorableTarget interface {
LocalRepos() []model.LocalGitRepo
Dockerignores() []model.Dockerignore
// These directories and their children will not trigger file change events
IgnoredLocalDirectories() []string
}
// Filter out files that should not trigger new builds.
func CreateFileChangeFilter(m IgnorableTarget) (model.PathMatcher, error) {
matchers := []model.PathMatcher{}
for _, r := range m.LocalRepos() {
gim, err := git.NewRepoIgnoreTester(context.Background(), r.LocalPath)
if err == nil {
matchers = append(matchers, gim)
}
}
for _, di := range m.Dockerignores() {
dim, err := dockerignore.DockerIgnoreTesterFromContents(di.LocalPath, di.Contents)
if err == nil {
matchers = append(matchers, dim)
}
}
for _, p := range m.IgnoredLocalDirectories() {
dm, err := newDirectoryMatcher(p)
if err != nil {
return nil, errors.Wrap(err, "creating directory matcher")
}
matchers = append(matchers, dm)
}
// Filter out spurious changes that we don't want to rebuild on, like IDE
// temp/lock files.
//
// This isn't an ideal solution. In an ideal world, the user would put
// everything to ignore in their tiltignore/dockerignore files. This is a
// stop-gap so they don't have a terrible experience if those files aren't
// there or aren't in the right places.
//
// https://app.clubhouse.io/windmill/story/691/filter-out-ephemeral-file-changes
matchers = append(matchers,
// GoLand
model.NewGlobMatcher("*___jb_old___", "*___jb_tmp___"),
// Emacs
tempBrokenSymlinkMatcher{},
)
ignoreMatcher := model.NewCompositeMatcher(matchers)
// TODO(maia): this doesn't have to be a composite matcher anymore since removing `configMatcher`?
return fileChangeFilter{
ignoreMatchers: ignoreMatcher,
}, nil
}
func CreateRunMatcher(r model.Run) (model.PathMatcher, error) {
dim, err := dockerignore.NewDockerPatternMatcher(r.Triggers.BaseDirectory, r.Triggers.Paths)
if err != nil {
return nil, err
}
return dim, nil
}
// Emacs temp files look like:
// .#a.txt -> [some garbage]
type tempBrokenSymlinkMatcher struct{}
func (m tempBrokenSymlinkMatcher) Matches(path string, isDir bool) (bool, error) {
if isDir {
return false, nil
}
if !strings.HasPrefix(filepath.Base(path), ".") {
return false, nil
}
return ospath.IsBrokenSymlink(path)
}
type directoryMatcher struct {
dir string
}
var _ model.PathMatcher = directoryMatcher{}
func newDirectoryMatcher(dir string) (directoryMatcher, error) {
dir, err := filepath.Abs(dir)
if err != nil {
return directoryMatcher{}, errors.Wrapf(err, "failed to get abs path of '%s'", dir)
}
return directoryMatcher{dir}, nil
}
func (d directoryMatcher) Matches(p string, isDir bool) (bool, error) {
return ospath.IsChild(d.dir, p), nil
}