@@ -4,15 +4,12 @@ import (
44"io/fs"
55"path"
66"strings"
7-
8- "golang.org/x/xerrors"
97)
108
11- // overlayFS allows you to "join" together the template files tar file fs.FS
12- // with the Terraform modules tar file fs.FS. We could potentially turn this
13- // into something more parameterized/configurable, but the requirements here are
14- // a _bit_ odd, because every file in the modulesFS includes the
15- // .terraform/modules/ folder at the beginning of it's path.
9+ // overlayFS allows you to "join" together multiple fs.FS. Files in any specific
10+ // overlay will only be accessible if their path starts with the base path
11+ // provided for the overlay. eg. An overlay at the path .terraform/modules
12+ // should contain files with paths inside the .terraform/modules folder.
1613type overlayFS struct {
1714baseFS fs.FS
1815overlays []Overlay
@@ -23,64 +20,32 @@ type Overlay struct {
2320fs.FS
2421}
2522
26- func NewOverlayFS (baseFS fs.FS ,overlays []Overlay ) (fs.FS ,error ) {
27- if err := valid (baseFS );err != nil {
28- return nil ,xerrors .Errorf ("baseFS: %w" ,err )
29- }
30-
31- for _ ,overlay := range overlays {
32- if err := valid (overlay .FS );err != nil {
33- return nil ,xerrors .Errorf ("overlayFS: %w" ,err )
34- }
35- }
36-
23+ func NewOverlayFS (baseFS fs.FS ,overlays []Overlay ) fs.FS {
3724return overlayFS {
3825baseFS :baseFS ,
3926overlays :overlays ,
40- }, nil
27+ }
4128}
4229
43- func (f overlayFS )Open (p string ) (fs.File ,error ) {
30+ func (f overlayFS )target (p string ) fs.FS {
31+ target := f .baseFS
4432for _ ,overlay := range f .overlays {
4533if strings .HasPrefix (path .Clean (p ),overlay .Path ) {
46- return overlay .FS .Open (p )
34+ target = overlay .FS
35+ break
4736}
4837}
49- return f . baseFS . Open ( p )
38+ return target
5039}
5140
52- func (f overlayFS )ReadDir (p string ) ([]fs.DirEntry ,error ) {
53- for _ ,overlay := range f .overlays {
54- if strings .HasPrefix (path .Clean (p ),overlay .Path ) {
55- //nolint:forcetypeassert
56- return overlay .FS .(fs.ReadDirFS ).ReadDir (p )
57- }
58- }
59- //nolint:forcetypeassert
60- return f .baseFS .(fs.ReadDirFS ).ReadDir (p )
41+ func (f overlayFS )Open (p string ) (fs.File ,error ) {
42+ return f .target (p ).Open (p )
6143}
6244
63- func (f overlayFS )ReadFile (p string ) ([]byte ,error ) {
64- for _ ,overlay := range f .overlays {
65- if strings .HasPrefix (path .Clean (p ),overlay .Path ) {
66- //nolint:forcetypeassert
67- return overlay .FS .(fs.ReadFileFS ).ReadFile (p )
68- }
69- }
70- //nolint:forcetypeassert
71- return f .baseFS .(fs.ReadFileFS ).ReadFile (p )
45+ func (f overlayFS )ReadDir (p string ) ([]fs.DirEntry ,error ) {
46+ return fs .ReadDir (f .target (p ),p )
7247}
7348
74- // valid checks that the fs.FS implements the required interfaces.
75- // The fs.FS interface is not sufficient.
76- func valid (fsys fs.FS )error {
77- _ ,ok := fsys .(fs.ReadDirFS )
78- if ! ok {
79- return xerrors .New ("overlayFS does not implement ReadDirFS" )
80- }
81- _ ,ok = fsys .(fs.ReadFileFS )
82- if ! ok {
83- return xerrors .New ("overlayFS does not implement ReadFileFS" )
84- }
85- return nil
49+ func (f overlayFS )ReadFile (p string ) ([]byte ,error ) {
50+ return fs .ReadFile (f .target (p ),p )
8651}