Add storage backends and safety checks

This commit is contained in:
2026-05-31 02:00:24 +00:00
parent 29dbad2967
commit 3c2f36a6e5
10 changed files with 1582 additions and 0 deletions

128
internal/storage/errors.go Normal file
View File

@@ -0,0 +1,128 @@
package storage
import (
"errors"
"fmt"
)
type ErrorKind string
const (
ErrNotFound ErrorKind = "not_found"
ErrAlreadyExist ErrorKind = "already_exists"
ErrNotEmpty ErrorKind = "not_empty"
ErrInvalidPath ErrorKind = "invalid_path"
ErrConflict ErrorKind = "conflict"
ErrPermission ErrorKind = "permission"
ErrTemporary ErrorKind = "temporary"
ErrUnsupported ErrorKind = "unsupported"
ErrUnknown ErrorKind = "unknown"
)
const (
OpValidatePath = "validate path"
OpReadFile = "read file"
OpOpenReader = "open reader"
OpWriteFile = "write file"
OpWriteFrom = "write stream"
OpStat = "stat"
OpWalk = "walk"
OpHasAny = "has any"
OpDeleteManagedBundle = "delete managed bundle"
OpRegisterBackend = "register backend"
OpOpenBackend = "open backend"
)
type Error struct {
Op string
Backend string
Path string
Kind ErrorKind
Err error
}
func NewError(op, backend, path string, kind ErrorKind, err error) *Error {
return &Error{
Op: op,
Backend: backend,
Path: path,
Kind: kind,
Err: err,
}
}
func (e *Error) Error() string {
if e == nil {
return "<nil>"
}
message := e.Op
if e.Backend != "" {
message += " " + e.Backend
}
if e.Path != "" {
message += " " + e.Path
}
if e.Kind != "" {
message += ": " + string(e.Kind)
}
if e.Err != nil {
message += ": " + e.Err.Error()
}
return message
}
func (e *Error) Unwrap() error {
if e == nil {
return nil
}
return e.Err
}
func (e *Error) Is(target error) bool {
var targetError *Error
if !errors.As(target, &targetError) {
return false
}
return targetError.Kind == "" || e.Kind == targetError.Kind
}
func Errorf(op, backend, path string, kind ErrorKind, format string, args ...any) *Error {
return NewError(op, backend, path, kind, fmt.Errorf(format, args...))
}
func IsKind(err error, kind ErrorKind) bool {
var storageErr *Error
return errors.As(err, &storageErr) && storageErr.Kind == kind
}
func IsNotFound(err error) bool {
return IsKind(err, ErrNotFound)
}
func IsAlreadyExists(err error) bool {
return IsKind(err, ErrAlreadyExist)
}
func IsNotEmpty(err error) bool {
return IsKind(err, ErrNotEmpty)
}
func IsInvalidPath(err error) bool {
return IsKind(err, ErrInvalidPath)
}
func IsConflict(err error) bool {
return IsKind(err, ErrConflict)
}
func IsPermission(err error) bool {
return IsKind(err, ErrPermission)
}
func IsTemporary(err error) bool {
return IsKind(err, ErrTemporary)
}
func IsUnsupported(err error) bool {
return IsKind(err, ErrUnsupported)
}