Skip to content
Snippets Groups Projects
Commit edc968552f0a authored by Christophe de Vienne's avatar Christophe de Vienne
Browse files

Add a layered FS type that will be passed down to engines

parent 46de2830176a
No related branches found
No related tags found
No related merge requests found
lib/fs.go 0 → 100644
package redner
import (
"encoding/hex"
"io"
"os"
"slices"
"strings"
"orus.io/orus-io/go-orusapi/database"
"orus.io/orus-io/rednerd/models"
)
func ancestors(path string) []string {
segments := slices.Insert(strings.Split(strings.Trim(path, "/"), "/"), 0, "")
for i := range segments[1:] {
segments[i+1] = segments[i] + "/" + segments[i+1]
}
segments[0] = "/"
return segments
}
type fsLayer struct {
root string
files []*models.File
}
type FS struct {
db *database.SQLHelper
layers []fsLayer
masked []string
fileIndex map[string]*models.File
fileList []*models.File
fileRoot map[string]string
}
func NewFS(db *database.SQLHelper) *FS {
return &FS{db: db}
}
func (fs *FS) AddRoot(root string) error {
nodes, err := models.ListFiles(fs.db, root, "/")
if err != nil {
return err
}
files := make([]*models.File, len(nodes))
for i, node := range nodes {
files[i] = &models.File{
Path: node.Path,
Type: node.Mimetype,
Sha256: hex.EncodeToString(node.Sha256),
Size: node.Size,
}
}
fs.AddLayer(root, files)
return nil
}
func (fs *FS) AddLayer(root string, files []*models.File) {
nextMasked := slices.Clone(fs.masked)
for _, f := range files {
if slices.ContainsFunc(ancestors(f.Path), func(p string) bool {
return slices.Contains(fs.masked, p)
}) {
continue
}
if f.Type == "redner/mask" {
nextMasked = append(nextMasked, f.Path)
} else if _, exists := fs.fileIndex[f.Path]; !exists {
fs.fileRoot[f.Path] = root
fs.fileIndex[f.Path] = f
}
}
fs.masked = nextMasked
fs.layers = append(fs.layers, fsLayer{
root: root,
files: files,
})
fs.fileList = make([]*models.File, 0, len(fs.fileIndex))
for _, v := range fs.fileIndex {
fs.fileList = append(fs.fileList, v)
}
}
func (fs *FS) List() []*models.File {
return fs.fileList
}
func (fs *FS) Read(path string) (io.ReadCloser, error) {
f, ok := fs.fileIndex[path]
if !ok {
return nil, os.ErrNotExist
}
// root := fs.fileRoot[path]
return models.GetFileBody(fs.db, f.Sha256)
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import ( import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/hex"
"io" "io"
"slices" "slices"
"strings" "strings"
...@@ -39,6 +40,22 @@ ...@@ -39,6 +40,22 @@
return io.NopCloser(bytes.NewReader(data)), nil return io.NopCloser(bytes.NewReader(data)), nil
} }
func GetFileBody(db *database.SQLHelper, sha256Hex string) (io.ReadCloser, error) {
sha, err := hex.DecodeString(sha256Hex)
if err != nil {
return nil, err
}
var data []byte
if err := db.Get(
&data, squirrel.Select("body").From("fscontent").Where(squirrel.Eq{"sha256": sha}),
); err != nil {
return nil, err
}
return io.NopCloser(bytes.NewReader(data)), nil
}
func InsertFile(db *database.SQLHelper, node *FSNode, body []byte) error { func InsertFile(db *database.SQLHelper, node *FSNode, body []byte) error {
node.Path = "/" + strings.Trim(node.Path, "/") node.Path = "/" + strings.Trim(node.Path, "/")
...@@ -115,3 +132,26 @@ ...@@ -115,3 +132,26 @@
return nil return nil
} }
func ListFiles(db *database.SQLHelper, root string, path string) ([]FSNode, error) {
var files []FSNode
if err := db.Select(
&files,
squirrel.
Select(
Schema.FSNode.FQColumns(true)...,
).
From(Schema.FSNode.GetName()).
LeftJoin(
"fsclosure ON fsclosure.root = fsnode.root AND fsclosure.child_path = fsnode.path",
).
Where(squirrel.Eq{
"fsclosure.root": root,
"fsclosure.parent_path": path,
}),
); err != nil {
return nil, err
}
return files, nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment