mirror of https://gitlab.com/ngerakines/tavern.git
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package asset
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/ngerakines/tavern/errors"
|
|
)
|
|
|
|
type fileStorage struct {
|
|
Base string
|
|
}
|
|
|
|
const (
|
|
filePrefix = "file://"
|
|
)
|
|
|
|
func NewFileStorage(base string) (Storage, error) {
|
|
if !filepath.IsAbs(base) {
|
|
return nil, fmt.Errorf("base path is not absolute: %s", base)
|
|
}
|
|
return &fileStorage{
|
|
Base: base,
|
|
}, nil
|
|
}
|
|
|
|
var _ Storage = fileStorage{}
|
|
|
|
func (f fileStorage) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (f fileStorage) Create(ctx context.Context, fileName string, reader io.Reader) (string, error) {
|
|
fullPath := filepath.Join(f.Base, fileName)
|
|
prefixedPath := fmt.Sprintf("%s%s", filePrefix, fullPath)
|
|
|
|
exists, err := f.Exists(ctx, prefixedPath)
|
|
if err != nil {
|
|
return "", errors.NewAssetExistsError(err)
|
|
}
|
|
if exists {
|
|
return "", errors.NewAssetExistsError(nil)
|
|
}
|
|
|
|
out, err := os.Create(fullPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer out.Close()
|
|
|
|
_, err = io.Copy(out, reader)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return prefixedPath, err
|
|
}
|
|
|
|
func (f fileStorage) Delete(ctx context.Context, location string) error {
|
|
if !strings.HasPrefix(location, fmt.Sprintf("%s%s", filePrefix, f.Base)) {
|
|
return fmt.Errorf("invalid file storage location: %s", location)
|
|
}
|
|
location = strings.TrimPrefix(location, filePrefix)
|
|
|
|
return os.Remove(location)
|
|
}
|
|
|
|
func (f fileStorage) Exists(ctx context.Context, location string) (bool, error) {
|
|
if !strings.HasPrefix(location, fmt.Sprintf("%s%s", filePrefix, f.Base)) {
|
|
return false, fmt.Errorf("invalid file storage location: %s", location)
|
|
}
|
|
location = strings.TrimPrefix(location, filePrefix)
|
|
|
|
_, err := os.Stat(location)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (f fileStorage) Read(ctx context.Context, location string) (io.ReadCloser, error) {
|
|
if !strings.HasPrefix(location, fmt.Sprintf("%s%s", filePrefix, f.Base)) {
|
|
return nil, fmt.Errorf("invalid file storage location: %s", location)
|
|
}
|
|
location = strings.TrimPrefix(location, filePrefix)
|
|
|
|
return os.Open(location)
|
|
}
|
|
|
|
func (f fileStorage) Upload(ctx context.Context, checksum string, source string) (string, error) {
|
|
file, err := os.Open(source)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// TODO: handle this error
|
|
defer file.Close()
|
|
return f.Create(ctx, checksum, file)
|
|
}
|