79 lines
1.8 KiB
Go
79 lines
1.8 KiB
Go
package fs
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/fs"
|
|
|
|
"source.toby3d.me/toby3d/home/internal/domain"
|
|
"source.toby3d.me/toby3d/home/internal/resource"
|
|
)
|
|
|
|
type fileServerResourceRepository struct {
|
|
root fs.FS
|
|
}
|
|
|
|
func NewFileServerResourceRepository(root fs.FS) resource.Repository {
|
|
return &fileServerResourceRepository{
|
|
root: root,
|
|
}
|
|
}
|
|
|
|
func (repo *fileServerResourceRepository) Get(ctx context.Context, p string) (*domain.Resource, error) {
|
|
info, err := fs.Stat(repo.root, p)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot stat resource on path '%s': %w", p, err)
|
|
}
|
|
|
|
if info.IsDir() {
|
|
return nil, fmt.Errorf("cannot open resource on path '%s': %w", p, resource.ErrIsDir)
|
|
}
|
|
|
|
f, err := repo.root.Open(p)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot open resource on path '%s': %w", p, err)
|
|
}
|
|
defer f.Close()
|
|
|
|
return domain.NewResource(info.ModTime(), f, p), nil
|
|
}
|
|
|
|
func (repo *fileServerResourceRepository) Fetch(ctx context.Context, pattern string) (domain.Resources, int, error) {
|
|
var (
|
|
err error
|
|
matches []string
|
|
)
|
|
|
|
if pattern != "" {
|
|
if matches, err = fs.Glob(repo.root, pattern); err != nil {
|
|
return nil, 0, fmt.Errorf("cannot match any resource by pattern '%s': %w", pattern, err)
|
|
}
|
|
} else {
|
|
if err = fs.WalkDir(repo.root, ".", func(path string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return fmt.Errorf("catched error while walk: %w", err)
|
|
}
|
|
|
|
if d.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
matches = append(matches, path)
|
|
|
|
return nil
|
|
}); err != nil {
|
|
return nil, 0, fmt.Errorf("cannot walk through resource directories: %w", err)
|
|
}
|
|
}
|
|
|
|
out := make(domain.Resources, 0, len(matches))
|
|
|
|
for i := range matches {
|
|
if r, err := repo.Get(ctx, matches[i]); err == nil {
|
|
out = append(out, r)
|
|
}
|
|
}
|
|
|
|
return out, len(out), nil
|
|
}
|