filesystem: Globally declared filesystems, fs directive (#5833)

This commit is contained in:
a
2024-01-13 14:12:43 -06:00
committed by GitHub
parent b359ca565c
commit c839a98ff5
30 changed files with 450 additions and 219 deletions

View File

@@ -0,0 +1,77 @@
package filesystems
import (
"io/fs"
"strings"
"sync"
)
const (
DefaultFilesystemKey = "default"
)
var DefaultFilesystem = &wrapperFs{key: DefaultFilesystemKey, FS: OsFS{}}
// wrapperFs exists so can easily add to wrapperFs down the line
type wrapperFs struct {
key string
fs.FS
}
// FilesystemMap stores a map of filesystems
// the empty key will be overwritten to be the default key
// it includes a default filesystem, based off the os fs
type FilesystemMap struct {
m sync.Map
}
// note that the first invocation of key cannot be called in a racy context.
func (f *FilesystemMap) key(k string) string {
if k == "" {
k = DefaultFilesystemKey
}
return k
}
// Register will add the filesystem with key to later be retrieved
// A call with a nil fs will call unregister, ensuring that a call to Default() will never be nil
func (f *FilesystemMap) Register(k string, v fs.FS) {
k = f.key(k)
if v == nil {
f.Unregister(k)
return
}
f.m.Store(k, &wrapperFs{key: k, FS: v})
}
// Unregister will remove the filesystem with key from the filesystem map
// if the key is the default key, it will set the default to the osFS instead of deleting it
// modules should call this on cleanup to be safe
func (f *FilesystemMap) Unregister(k string) {
k = f.key(k)
if k == DefaultFilesystemKey {
f.m.Store(k, DefaultFilesystem)
} else {
f.m.Delete(k)
}
}
// Get will get a filesystem with a given key
func (f *FilesystemMap) Get(k string) (v fs.FS, ok bool) {
k = f.key(k)
c, ok := f.m.Load(strings.TrimSpace(k))
if !ok {
if k == DefaultFilesystemKey {
f.m.Store(k, DefaultFilesystem)
return DefaultFilesystem, true
}
return nil, ok
}
return c.(fs.FS), true
}
// Default will get the default filesystem in the filesystem map
func (f *FilesystemMap) Default() fs.FS {
val, _ := f.Get(DefaultFilesystemKey)
return val
}

View File

@@ -0,0 +1,29 @@
package filesystems
import (
"io/fs"
"os"
"path/filepath"
)
// OsFS is a simple fs.FS implementation that uses the local
// file system. (We do not use os.DirFS because we do our own
// rooting or path prefixing without being constrained to a single
// root folder. The standard os.DirFS implementation is problematic
// since roots can be dynamic in our application.)
//
// OsFS also implements fs.StatFS, fs.GlobFS, fs.ReadDirFS, and fs.ReadFileFS.
type OsFS struct{}
func (OsFS) Open(name string) (fs.File, error) { return os.Open(name) }
func (OsFS) Stat(name string) (fs.FileInfo, error) { return os.Stat(name) }
func (OsFS) Glob(pattern string) ([]string, error) { return filepath.Glob(pattern) }
func (OsFS) ReadDir(name string) ([]fs.DirEntry, error) { return os.ReadDir(name) }
func (OsFS) ReadFile(name string) ([]byte, error) { return os.ReadFile(name) }
var (
_ fs.StatFS = (*OsFS)(nil)
_ fs.GlobFS = (*OsFS)(nil)
_ fs.ReadDirFS = (*OsFS)(nil)
_ fs.ReadFileFS = (*OsFS)(nil)
)