forked from open-policy-agent/opa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilefs.go
116 lines (96 loc) · 2.64 KB
/
filefs.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
//go:build go1.16
// +build go1.16
package bundle
import (
"fmt"
"io"
"io/fs"
"path/filepath"
"sync"
"github.com/open-policy-agent/opa/loader/filter"
)
const (
defaultFSLoaderRoot = "."
)
type dirLoaderFS struct {
sync.Mutex
filesystem fs.FS
files []string
idx int
filter filter.LoaderFilter
root string
pathFormat PathFormat
}
// NewFSLoader returns a basic DirectoryLoader implementation
// that will load files from a fs.FS interface
func NewFSLoader(filesystem fs.FS) (DirectoryLoader, error) {
return NewFSLoaderWithRoot(filesystem, defaultFSLoaderRoot), nil
}
// NewFSLoaderWithRoot returns a basic DirectoryLoader implementation
// that will load files from a fs.FS interface at the supplied root
func NewFSLoaderWithRoot(filesystem fs.FS, root string) DirectoryLoader {
d := dirLoaderFS{
filesystem: filesystem,
root: normalizeRootDirectory(root),
pathFormat: Chrooted,
}
return &d
}
func (d *dirLoaderFS) walkDir(path string, dirEntry fs.DirEntry, err error) error {
if err != nil {
return err
}
if dirEntry != nil {
info, err := dirEntry.Info()
if err != nil {
return err
}
if dirEntry.Type().IsRegular() {
if d.filter != nil && d.filter(filepath.ToSlash(path), info, getdepth(path, false)) {
return nil
}
d.files = append(d.files, path)
} else if dirEntry.Type().IsDir() {
if d.filter != nil && d.filter(filepath.ToSlash(path), info, getdepth(path, true)) {
return fs.SkipDir
}
}
}
return nil
}
// WithFilter specifies the filter object to use to filter files while loading bundles
func (d *dirLoaderFS) WithFilter(filter filter.LoaderFilter) DirectoryLoader {
d.filter = filter
return d
}
// WithPathFormat specifies how a path is formatted in a Descriptor
func (d *dirLoaderFS) WithPathFormat(pathFormat PathFormat) DirectoryLoader {
d.pathFormat = pathFormat
return d
}
// NextFile iterates to the next file in the directory tree
// and returns a file Descriptor for the file.
func (d *dirLoaderFS) NextFile() (*Descriptor, error) {
d.Lock()
defer d.Unlock()
if d.files == nil {
err := fs.WalkDir(d.filesystem, d.root, d.walkDir)
if err != nil {
return nil, fmt.Errorf("failed to list files: %w", err)
}
}
// If done reading files then just return io.EOF
// errors for each NextFile() call
if d.idx >= len(d.files) {
return nil, io.EOF
}
fileName := d.files[d.idx]
d.idx++
fh, err := d.filesystem.Open(fileName)
if err != nil {
return nil, fmt.Errorf("failed to open file %s: %w", fileName, err)
}
cleanedPath := formatPath(fileName, d.root, d.pathFormat)
f := newDescriptor(cleanedPath, cleanedPath, fh).withCloser(fh)
return f, nil
}