cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.49.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/discovery/glob.go

151lines · modecode

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