feat(editor,storage): storage library to abstract writabble file system
This commit is contained in:
98
editor/storage/local.go
Normal file
98
editor/storage/local.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
func Newlocal(
|
||||
root *os.Root,
|
||||
logger *slog.Logger,
|
||||
) Storage {
|
||||
return &local{
|
||||
log: logger,
|
||||
root: root,
|
||||
}
|
||||
}
|
||||
|
||||
type local struct {
|
||||
log *slog.Logger
|
||||
root *os.Root
|
||||
}
|
||||
|
||||
var _ Storage = (*local)(nil)
|
||||
|
||||
func (files *local) Exists(p string) bool {
|
||||
if _, err := files.root.Stat(p); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (files *local) Open(p string) (fs.File, error) {
|
||||
log := files.log.With(
|
||||
slog.String("path", p),
|
||||
slog.String("root", files.root.Name()))
|
||||
|
||||
log.Debug("Opening file")
|
||||
defer log.Debug("File opened")
|
||||
|
||||
f, err := files.root.Open(p)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, ErrNotExists
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (files *local) Write(p string, d []byte) (int, error) {
|
||||
log := files.log.With(
|
||||
slog.String("path", p),
|
||||
slog.String("root", files.root.Name()))
|
||||
|
||||
log.Debug("Writing file")
|
||||
defer log.Debug("File wrote")
|
||||
|
||||
if err := files.root.MkdirAll(path.Dir(p), os.ModePerm); err != nil {
|
||||
return 0, fmt.Errorf("file.local: failed to create parent directories %q: %w", path.Dir(p), err)
|
||||
}
|
||||
|
||||
err := files.root.WriteFile(p, d, os.ModePerm)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("file.local: failed to write file %q: %w", p, err)
|
||||
}
|
||||
|
||||
return len(d), nil
|
||||
}
|
||||
|
||||
func (files *local) WriteFrom(p string, r io.Reader) (int64, error) {
|
||||
log := files.log.With(
|
||||
slog.String("path", p),
|
||||
slog.String("root", files.root.Name()))
|
||||
|
||||
log.Debug("Writing file")
|
||||
defer log.Debug("File wrote")
|
||||
|
||||
if err := files.root.MkdirAll(path.Dir(p), os.ModePerm); err != nil {
|
||||
return 0, fmt.Errorf("file.local: failed to create parent directories %q: %w", path.Dir(p), err)
|
||||
}
|
||||
|
||||
f, err := files.root.Create(p)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("file.local: failed to create file %q: %w", p, err)
|
||||
}
|
||||
|
||||
n, err := f.ReadFrom(r)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("file.local: failed to write file %q: %w", p, err)
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
42
editor/storage/storage.go
Normal file
42
editor/storage/storage.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
Exists(p string) bool
|
||||
Open(p string) (fs.File, error)
|
||||
Write(p string, b []byte) (int, error)
|
||||
WriteFrom(p string, r io.Reader) (int64, error)
|
||||
}
|
||||
|
||||
type withRoot struct {
|
||||
root string
|
||||
Storage
|
||||
}
|
||||
|
||||
func WithRoot(rootDir string, s Storage) Storage {
|
||||
return &withRoot{root: rootDir, Storage: s}
|
||||
}
|
||||
|
||||
func (f *withRoot) Exists(p string) bool {
|
||||
return f.Storage.Exists(path.Join(f.root, p))
|
||||
}
|
||||
|
||||
func (f *withRoot) Open(p string) (fs.File, error) {
|
||||
return f.Storage.Open(path.Join(f.root, p))
|
||||
}
|
||||
|
||||
func (f *withRoot) Write(p string, b []byte) (int, error) {
|
||||
return f.Storage.Write(path.Join(f.root, p), b)
|
||||
}
|
||||
|
||||
func (f *withRoot) WriteFrom(p string, r io.Reader) (int64, error) {
|
||||
return f.Storage.WriteFrom(path.Join(f.root, p), r)
|
||||
}
|
||||
|
||||
var ErrNotExists = os.ErrNotExist
|
||||
Reference in New Issue
Block a user