cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.42.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/discovery/glob.go

150lines · modecode

1package discovery
2
3import (
4 "fmt"
5 "io/fs"
6 "os"
7 "path/filepath"
8 "regexp"
9)
10
11func NewGlobFinder(patterns []string, relaxed []*regexp.Regexp) GlobFinder {
12 return GlobFinder{
13 patterns: patterns,
14 relaxed: relaxed,
15 }
16}
17
18type GlobFinder struct {
19 patterns []string
20 relaxed []*regexp.Regexp
21}
22
23func (f GlobFinder) Find() (entries []Entry, err error) {
24 paths := filePaths{}
25 for _, p := range f.patterns {
26 matches, err := filepath.Glob(p)
27 if err != nil {
28 return nil, err
29 }
30
31 for _, path := range matches {
32 subpaths, err := findFiles(path)
33 if err != nil {
34 return nil, err
35 }
36 for _, subpath := range subpaths {
37 if !paths.hasPath(subpath.path) {
38 paths = append(paths, subpath)
39 }
40 }
41 }
42 }
43
44 if len(paths) == 0 {
45 return nil, fmt.Errorf("no matching files")
46 }
47
48 for _, fp := range paths {
49 fd, err := os.Open(fp.path)
50 if err != nil {
51 return nil, err
52 }
53 el, err := readRules(fp.target, fp.path, fd, !matchesAny(f.relaxed, fp.target))
54 if err != nil {
55 fd.Close()
56 return nil, fmt.Errorf("invalid file syntax: %w", err)
57 }
58 fd.Close()
59 for _, e := range el {
60 e.State = Noop
61 if len(e.ModifiedLines) == 0 {
62 e.ModifiedLines = e.Rule.Lines()
63 }
64 entries = append(entries, e)
65 }
66 }
67
68 return entries, nil
69}
70
71type filePath struct {
72 path string
73 target string
74}
75
76type filePaths []filePath
77
78func (fps filePaths) hasPath(p string) bool {
79 for _, fp := range fps {
80 if fp.path == p {
81 return true
82 }
83 }
84 return false
85}
86
87func findFiles(path string) (paths filePaths, err error) {
88 s, err := os.Stat(path)
89 if err != nil {
90 return nil, err
91 }
92
93 // nolint: exhaustive
94 switch {
95 case s.IsDir():
96 subpaths, err := walkDir(path)
97 if err != nil {
98 return nil, err
99 }
100 paths = append(paths, subpaths...)
101 default:
102 target, err := filepath.EvalSymlinks(path)
103 if err != nil {
104 return nil, err
105 }
106 paths = append(paths, filePath{path: path, target: target})
107 }
108
109 return paths, nil
110}
111
112func walkDir(dirname string) (paths filePaths, err error) {
113 err = filepath.WalkDir(dirname,
114 func(path string, d fs.DirEntry, err error) error {
115 if err != nil {
116 return err
117 }
118
119 // nolint: exhaustive
120 switch d.Type() {
121 case fs.ModeDir:
122 return nil
123 case fs.ModeSymlink:
124 dest, err := filepath.EvalSymlinks(path)
125 if err != nil {
126 return err
127 }
128
129 s, err := os.Stat(dest)
130 if err != nil {
131 return err
132 }
133 if s.IsDir() {
134 subpaths, err := findFiles(dest)
135 if err != nil {
136 return err
137 }
138 paths = append(paths, subpaths...)
139 } else {
140 paths = append(paths, filePath{path: path, target: dest})
141 }
142 default:
143 paths = append(paths, filePath{path: path, target: path})
144 }
145
146 return nil
147 })
148
149 return paths, err
150}