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
|
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package tfconfig
import (
"io/fs"
"io/ioutil"
"os"
"time"
)
// FS is an interface used by [LoadModuleFromFilesystem].
//
// Unfortunately this package implemented a draft version of the io/fs.FS
// API before it was finalized and so this interface is not compatible with
// the final design. To use this package with the final filesystem API design,
// use [WrapFS] to wrap a standard filesystem implementation so that it
// implements this interface.
type FS interface {
Open(name string) (File, error)
ReadFile(name string) ([]byte, error)
ReadDir(dirname string) ([]os.FileInfo, error)
}
// File represents an open file in [FS].
type File interface {
Stat() (os.FileInfo, error)
Read([]byte) (int, error)
Close() error
}
// wrapFS is a rather regrettable adapter from the standard library filesystem
// interfaces to the one we have designed in this package, since we adopted
// a draft of that API before it was finalized and the final is incompatible.
type wrapFS struct {
wrapped fs.FS
}
// WrapFS wraps a standard library filesystem implementation so that it
// implements this package's own (slightly-incompatible) interface [FS].
func WrapFS(wrapped fs.FS) FS {
return wrapFS{wrapped}
}
func (wfs wrapFS) Open(name string) (File, error) {
return wfs.wrapped.Open(name)
}
func (wfs wrapFS) ReadFile(name string) ([]byte, error) {
return fs.ReadFile(wfs.wrapped, name)
}
func (wfs wrapFS) ReadDir(dirname string) ([]os.FileInfo, error) {
entries, err := fs.ReadDir(wfs.wrapped, dirname)
var ret []os.FileInfo
if len(entries) != 0 {
ret = make([]os.FileInfo, len(entries))
for i, entry := range entries {
ret[i] = wrapFileInfoDirEntry{entry}
}
}
return ret, err
}
type wrapFileInfoDirEntry struct {
wrapped fs.DirEntry
}
func (d wrapFileInfoDirEntry) IsDir() bool {
return d.wrapped.IsDir()
}
func (d wrapFileInfoDirEntry) ModTime() time.Time {
// this package doesn't actually care about modification times,
// so we don't need to implement this.
panic("unimplemented")
}
func (d wrapFileInfoDirEntry) Mode() fs.FileMode {
// this package doesn't actually care about file modes,
// so we don't need to implement this.
panic("unimplemented")
}
func (d wrapFileInfoDirEntry) Name() string {
return d.wrapped.Name()
}
func (d wrapFileInfoDirEntry) Size() int64 {
// this package doesn't actually care about file sizes,
// so we don't need to implement this.
panic("unimplemented")
}
func (d wrapFileInfoDirEntry) Sys() any {
return nil
}
type osFs struct{}
func (fs *osFs) Open(name string) (File, error) {
return os.Open(name)
}
func (fs *osFs) ReadFile(name string) ([]byte, error) {
return ioutil.ReadFile(name)
}
func (fs *osFs) ReadDir(dirname string) ([]os.FileInfo, error) {
return ioutil.ReadDir(dirname)
}
// NewOsFs provides a basic implementation of FS for an OS filesystem
func NewOsFs() FS {
return &osFs{}
}
|