mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-01-06 19:49:56 -06:00
Interfaces for core functionality
This commit is contained in:
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
var debugMode bool = false
|
||||
var backend phylumfs.PhylumFs
|
||||
var backend phylumfs.Backend
|
||||
|
||||
func Setup() {
|
||||
viper.SetEnvPrefix("phylum")
|
||||
@@ -51,9 +51,6 @@ func Setup() {
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("Unable to parse db connection String: %v\n", err))
|
||||
}
|
||||
if debugMode {
|
||||
config.Tracer = phylumTracer{}
|
||||
}
|
||||
conn, err = pgx.ConnectConfig(context.Background(), config)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("Unable to connect to database: %v\n", err))
|
||||
@@ -71,14 +68,3 @@ func Setup() {
|
||||
rootCmd.AddCommand([]*cobra.Command{setupServeCommand(), setupAdminCommand()}...)
|
||||
rootCmd.Execute()
|
||||
}
|
||||
|
||||
type phylumTracer struct {
|
||||
}
|
||||
|
||||
func (p phylumTracer) TraceQueryStart(ctx context.Context, conn *pgx.Conn, data pgx.TraceQueryStartData) context.Context {
|
||||
log.Trace(fmt.Sprintf("%+v\n", data))
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (p phylumTracer) TraceQueryEnd(ctx context.Context, conn *pgx.Conn, data pgx.TraceQueryEndData) {
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package cmds
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
webdav "github.com/emersion/go-webdav"
|
||||
"github.com/fvbock/endless"
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shroff/phylum/server/internal/pgfs"
|
||||
"github.com/shroff/phylum/server/internal/webdav"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
@@ -54,41 +51,18 @@ func setupServeCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
func setupWebdav(r *gin.RouterGroup) {
|
||||
log.Info(fmt.Sprintf("Setting up WebDAV access at %s", r.BasePath()))
|
||||
|
||||
webdavHandler := webdav.Handler{
|
||||
FileSystem: pgfs.New(backend, r.BasePath()),
|
||||
}
|
||||
handler := func(c *gin.Context) {
|
||||
path := c.Params.ByName("path")
|
||||
path = strings.TrimLeft(path, "/")
|
||||
if path == "" {
|
||||
// No path specified
|
||||
c.Writer.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
index := strings.Index(path, "/")
|
||||
if index != -1 {
|
||||
path = path[0:index]
|
||||
}
|
||||
_, err := backend.FindRoot(context.Background(), path)
|
||||
if err != nil {
|
||||
c.Writer.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
webdavHandler.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
r.Handle("OPTIONS", "/*path", handler)
|
||||
r.Handle("GET", "/*path", handler)
|
||||
r.Handle("PUT", "/*path", handler)
|
||||
r.Handle("HEAD", "/*path", handler)
|
||||
r.Handle("POST", "/*path", handler)
|
||||
r.Handle("DELETE", "/*path", handler)
|
||||
r.Handle("MOVE", "/*path", handler)
|
||||
r.Handle("COPY", "/*path", handler)
|
||||
r.Handle("MKCOL", "/*path", handler)
|
||||
r.Handle("PROPFIND", "/*path", handler)
|
||||
r.Handle("PROPPATCH", "/*path", handler)
|
||||
handler := webdav.NewHandler(backend, r.BasePath())
|
||||
r.Handle("OPTIONS", "/*path", handler.HandleRequest)
|
||||
r.Handle("GET", "/*path", handler.HandleRequest)
|
||||
r.Handle("PUT", "/*path", handler.HandleRequest)
|
||||
r.Handle("HEAD", "/*path", handler.HandleRequest)
|
||||
r.Handle("POST", "/*path", handler.HandleRequest)
|
||||
r.Handle("DELETE", "/*path", handler.HandleRequest)
|
||||
r.Handle("MOVE", "/*path", handler.HandleRequest)
|
||||
r.Handle("COPY", "/*path", handler.HandleRequest)
|
||||
r.Handle("MKCOL", "/*path", handler.HandleRequest)
|
||||
r.Handle("PROPFIND", "/*path", handler.HandleRequest)
|
||||
r.Handle("PROPPATCH", "/*path", handler.HandleRequest)
|
||||
}
|
||||
|
||||
func createEngine(corsEnabled bool, corsOrigins []string) *gin.Engine {
|
||||
|
||||
56
internal/phylumfs/backend.go
Normal file
56
internal/phylumfs/backend.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package phylumfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/shroff/phylum/server/internal/sql"
|
||||
)
|
||||
|
||||
type Backend interface {
|
||||
FindRoot(ctx context.Context, name string) (Fs, error)
|
||||
Mkroot(ctx context.Context, id uuid.UUID, name string) error
|
||||
Rmroot(ctx context.Context, name string) error
|
||||
}
|
||||
|
||||
type pgxBackend struct {
|
||||
queries sql.Queries
|
||||
cs contentStore
|
||||
}
|
||||
|
||||
func New(conn *pgx.Conn) Backend {
|
||||
queries := *sql.New(conn)
|
||||
cs, err := newLocalContentStore("srv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return pgxBackend{queries: queries, cs: cs}
|
||||
}
|
||||
|
||||
func (b pgxBackend) FindRoot(ctx context.Context, name string) (Fs, error) {
|
||||
// TODO: Permissions checks
|
||||
root, err := b.queries.FindRoot(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pgxFs{queries: b.queries, root: root.ID, cs: b.cs}, nil
|
||||
}
|
||||
|
||||
func (b pgxBackend) Mkroot(ctx context.Context, id uuid.UUID, name string) error {
|
||||
if _, err := b.queries.FindRoot(ctx, name); err == nil {
|
||||
return fmt.Errorf("root directory already exists: %s", name)
|
||||
} else {
|
||||
return b.queries.CreateResource(ctx, sql.CreateResourceParams{ID: id, Parent: nil, Name: name, Dir: true})
|
||||
}
|
||||
}
|
||||
|
||||
func (b pgxBackend) Rmroot(ctx context.Context, name string) error {
|
||||
if fs, err := b.FindRoot(ctx, name); err == nil {
|
||||
return fs.DeleteRecursive(ctx, fs.rootId())
|
||||
} else {
|
||||
return fmt.Errorf("root directory does not exist: %s", name)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ContentStore interface {
|
||||
type contentStore interface {
|
||||
Open(id uuid.UUID) (io.ReadCloser, error)
|
||||
Create(id uuid.UUID, callback func(hash.Hash, int, error)) (io.WriteCloser, error)
|
||||
Delete(id uuid.UUID) error
|
||||
88
internal/phylumfs/fs.go
Normal file
88
internal/phylumfs/fs.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package phylumfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"hash"
|
||||
"io"
|
||||
iofs "io/fs"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/shroff/phylum/server/internal/sql"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type Fs interface {
|
||||
rootId() uuid.UUID
|
||||
Open(id uuid.UUID) (io.ReadCloser, error)
|
||||
ReadDir(ctx context.Context, id uuid.UUID, recursive bool) ([]sql.ReadDirRow, error)
|
||||
DeleteRecursive(ctx context.Context, id uuid.UUID) error
|
||||
CreateResource(ctx context.Context, id uuid.UUID, parent uuid.UUID, name string, dir bool) error
|
||||
UpdateContents(ctx context.Context, id uuid.UUID) (io.WriteCloser, error)
|
||||
ResourceByPath(ctx context.Context, path string) (*sql.ResourceByPathRow, error)
|
||||
}
|
||||
|
||||
type pgxFs struct {
|
||||
queries sql.Queries
|
||||
root uuid.UUID
|
||||
cs contentStore
|
||||
}
|
||||
|
||||
func (fs pgxFs) rootId() uuid.UUID {
|
||||
return fs.root
|
||||
}
|
||||
|
||||
func (fs pgxFs) Open(id uuid.UUID) (io.ReadCloser, error) {
|
||||
return fs.cs.Open(id)
|
||||
}
|
||||
|
||||
func (fs pgxFs) ReadDir(ctx context.Context, id uuid.UUID, recursive bool) ([]sql.ReadDirRow, error) {
|
||||
return fs.queries.ReadDir(ctx, sql.ReadDirParams{ID: id, Recursive: recursive})
|
||||
}
|
||||
|
||||
func (fs pgxFs) DeleteRecursive(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := fs.queries.DeleteRecursive(ctx, id)
|
||||
// TODO: Delete Contents
|
||||
return err
|
||||
}
|
||||
|
||||
func (fs pgxFs) CreateResource(ctx context.Context, id uuid.UUID, parent uuid.UUID, name string, dir bool) error {
|
||||
return fs.queries.CreateResource(ctx, sql.CreateResourceParams{ID: id, Parent: &parent, Name: name, Dir: dir})
|
||||
}
|
||||
|
||||
func (fs pgxFs) UpdateContents(ctx context.Context, id uuid.UUID) (io.WriteCloser, error) {
|
||||
return fs.cs.Create(id, func(h hash.Hash, len int, err error) {
|
||||
if err == nil {
|
||||
etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
err = fs.queries.UpdateResourceContents(ctx, sql.UpdateResourceContentsParams{
|
||||
ID: id,
|
||||
Size: pgtype.Int4{Int32: int32(len), Valid: true},
|
||||
Etag: pgtype.Text{String: string(etag), Valid: true},
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Warn("Unable to update contents: " + err.Error())
|
||||
fs.cs.Delete(id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (fs pgxFs) ResourceByPath(ctx context.Context, path string) (*sql.ResourceByPathRow, error) {
|
||||
logrus.Trace("PhylumFs.ResourceByPath called with " + path)
|
||||
segments := strings.Split(strings.Trim(path, "/"), "/")
|
||||
if len(segments) == 0 {
|
||||
return nil, iofs.ErrInvalid
|
||||
}
|
||||
|
||||
res, err := fs.queries.ResourceByPath(ctx, sql.ResourceByPathParams{Search: segments, Root: fs.root})
|
||||
if err != nil {
|
||||
return nil, iofs.ErrNotExist
|
||||
}
|
||||
logrus.Trace(res)
|
||||
|
||||
//TODO: Permissions checks
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type LocalContentStore string
|
||||
type localContentStore string
|
||||
|
||||
type contentWriter struct {
|
||||
file *os.File
|
||||
@@ -37,19 +37,19 @@ func (c contentWriter) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func NewLocalContentStore(root string) (ContentStore, error) {
|
||||
func newLocalContentStore(root string) (contentStore, error) {
|
||||
err := os.MkdirAll(root, 0750)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return LocalContentStore(root), nil
|
||||
return localContentStore(root), nil
|
||||
}
|
||||
|
||||
func (l LocalContentStore) Open(id uuid.UUID) (io.ReadCloser, error) {
|
||||
func (l localContentStore) Open(id uuid.UUID) (io.ReadCloser, error) {
|
||||
return os.Open(l.path(id))
|
||||
}
|
||||
|
||||
func (l LocalContentStore) Create(id uuid.UUID, callback func(hash.Hash, int, error)) (io.WriteCloser, error) {
|
||||
func (l localContentStore) Create(id uuid.UUID, callback func(hash.Hash, int, error)) (io.WriteCloser, error) {
|
||||
file, err := os.Create(l.path(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -59,10 +59,10 @@ func (l LocalContentStore) Create(id uuid.UUID, callback func(hash.Hash, int, er
|
||||
return contentWriter{file, md5.New(), &addr, callback}, nil
|
||||
}
|
||||
|
||||
func (l LocalContentStore) Delete(id uuid.UUID) error {
|
||||
func (l localContentStore) Delete(id uuid.UUID) error {
|
||||
return os.Remove(filepath.Join(string(l), id.String()))
|
||||
}
|
||||
|
||||
func (l LocalContentStore) path(id uuid.UUID) string {
|
||||
func (l localContentStore) path(id uuid.UUID) string {
|
||||
return filepath.Join(string(l), id.String())
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package phylumfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"io/fs"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/shroff/phylum/server/internal/sql"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type PhylumFs struct {
|
||||
queries sql.Queries
|
||||
cs ContentStore
|
||||
}
|
||||
|
||||
func New(conn *pgx.Conn) PhylumFs {
|
||||
queries := *sql.New(conn)
|
||||
cs, err := NewLocalContentStore("srv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return PhylumFs{queries: queries, cs: cs}
|
||||
}
|
||||
|
||||
func (p PhylumFs) FindRoot(ctx context.Context, name string) (sql.Resource, error) {
|
||||
// TODO: Permissions checks
|
||||
return p.queries.FindRoot(ctx, name)
|
||||
}
|
||||
|
||||
func (p PhylumFs) Mkroot(ctx context.Context, id uuid.UUID, name string) error {
|
||||
if _, err := p.queries.FindRoot(ctx, name); err == nil {
|
||||
return fmt.Errorf("root directory already exists: %s", name)
|
||||
} else {
|
||||
return p.queries.CreateResource(ctx, sql.CreateResourceParams{ID: id, Parent: nil, Name: name, Dir: true})
|
||||
}
|
||||
}
|
||||
|
||||
func (p PhylumFs) Rmroot(ctx context.Context, name string) error {
|
||||
if root, err := p.queries.FindRoot(ctx, name); err == nil {
|
||||
return p.DeleteRecursive(ctx, root.ID)
|
||||
} else {
|
||||
return fmt.Errorf("root directory does not exist: %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (p PhylumFs) Open(id uuid.UUID) (io.ReadCloser, error) {
|
||||
return p.cs.Open(id)
|
||||
}
|
||||
|
||||
func (p PhylumFs) ReadDir(ctx context.Context, id uuid.UUID, recursive bool) ([]sql.ReadDirRow, error) {
|
||||
return p.queries.ReadDir(ctx, sql.ReadDirParams{ID: id, Recursive: recursive})
|
||||
}
|
||||
|
||||
func (p PhylumFs) DeleteRecursive(ctx context.Context, id uuid.UUID) error {
|
||||
_, err := p.queries.DeleteRecursive(ctx, id)
|
||||
// TODO: Delete Contents
|
||||
return err
|
||||
}
|
||||
|
||||
func (p PhylumFs) CreateResource(ctx context.Context, id uuid.UUID, parent uuid.UUID, name string, dir bool) error {
|
||||
return p.queries.CreateResource(ctx, sql.CreateResourceParams{ID: id, Parent: &parent, Name: name, Dir: dir})
|
||||
}
|
||||
|
||||
func (p PhylumFs) UpdateContents(ctx context.Context, id uuid.UUID) (io.WriteCloser, error) {
|
||||
return p.cs.Create(id, func(h hash.Hash, len int, err error) {
|
||||
if err == nil {
|
||||
etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
err = p.queries.UpdateResourceContents(ctx, sql.UpdateResourceContentsParams{
|
||||
ID: id,
|
||||
Size: pgtype.Int4{Int32: int32(len), Valid: true},
|
||||
Etag: pgtype.Text{String: string(etag), Valid: true},
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Warn(fmt.Sprintf("Unable to update contents: %s", err))
|
||||
p.cs.Delete(id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (p PhylumFs) ResourceByPath(ctx context.Context, path string) (*sql.ResourceByPathRow, error) {
|
||||
segments := strings.Split(strings.TrimRight(path, "/"), "/")
|
||||
if len(segments) == 0 {
|
||||
return nil, fs.ErrInvalid
|
||||
}
|
||||
|
||||
root, err := p.queries.FindRoot(ctx, segments[0])
|
||||
if err != nil {
|
||||
return nil, fs.ErrNotExist
|
||||
}
|
||||
|
||||
res, err := p.queries.ResourceByPath(ctx, sql.ResourceByPathParams{Search: segments, Root: root.ID})
|
||||
if err != nil {
|
||||
return nil, fs.ErrNotExist
|
||||
}
|
||||
|
||||
//TODO: Permissions checks
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
51
internal/webdav/handler.go
Normal file
51
internal/webdav/handler.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package webdav
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
webdav "github.com/emersion/go-webdav"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shroff/phylum/server/internal/phylumfs"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
backend phylumfs.Backend
|
||||
prefix string
|
||||
}
|
||||
|
||||
func NewHandler(backend phylumfs.Backend, prefix string) *handler {
|
||||
logrus.Info("Setting up WebDAV access at " + prefix)
|
||||
return &handler{
|
||||
backend: backend,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) HandleRequest(c *gin.Context) {
|
||||
path := c.Params.ByName("path")
|
||||
path = strings.TrimLeft(path, "/")
|
||||
if path == "" {
|
||||
// No path specified
|
||||
c.Writer.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
index := strings.Index(path, "/")
|
||||
if index != -1 {
|
||||
path = path[0:index]
|
||||
}
|
||||
root, err := h.backend.FindRoot(context.Background(), path)
|
||||
if err != nil {
|
||||
c.Writer.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
|
||||
webdavHandler := webdav.Handler{
|
||||
FileSystem: adapter{
|
||||
fs: root,
|
||||
prefix: h.prefix,
|
||||
},
|
||||
}
|
||||
webdavHandler.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package pgfs
|
||||
package webdav
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/fs"
|
||||
iofs "io/fs"
|
||||
"strings"
|
||||
|
||||
webdav "github.com/emersion/go-webdav"
|
||||
@@ -12,24 +12,20 @@ import (
|
||||
"github.com/shroff/phylum/server/internal/sql"
|
||||
)
|
||||
|
||||
type Pgfs struct {
|
||||
p phylumfs.PhylumFs
|
||||
type adapter struct {
|
||||
fs phylumfs.Fs
|
||||
prefix string
|
||||
}
|
||||
|
||||
func New(p phylumfs.PhylumFs, prefix string) Pgfs {
|
||||
return Pgfs{p: p, prefix: prefix}
|
||||
}
|
||||
|
||||
func (p Pgfs) Open(ctx context.Context, name string) (io.ReadCloser, error) {
|
||||
func (p adapter) Open(ctx context.Context, name string) (io.ReadCloser, error) {
|
||||
resource, err := p.resourceByPath(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.p.Open(resource.ID)
|
||||
return p.fs.Open(resource.ID)
|
||||
}
|
||||
|
||||
func (p Pgfs) Stat(ctx context.Context, name string) (*webdav.FileInfo, error) {
|
||||
func (p adapter) Stat(ctx context.Context, name string) (*webdav.FileInfo, error) {
|
||||
resource, err := p.resourceByPath(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -44,15 +40,15 @@ func (p Pgfs) Stat(ctx context.Context, name string) (*webdav.FileInfo, error) {
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
func (p Pgfs) ReadDir(ctx context.Context, name string, recursive bool) ([]webdav.FileInfo, error) {
|
||||
func (p adapter) ReadDir(ctx context.Context, name string, recursive bool) ([]webdav.FileInfo, error) {
|
||||
dir, err := p.resourceByPath(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !dir.Dir {
|
||||
return nil, fs.ErrInvalid
|
||||
return nil, iofs.ErrInvalid
|
||||
}
|
||||
children, err := p.p.ReadDir(ctx, dir.ID, recursive)
|
||||
children, err := p.fs.ReadDir(ctx, dir.ID, recursive)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -71,7 +67,7 @@ func (p Pgfs) ReadDir(ctx context.Context, name string, recursive bool) ([]webda
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
func (p Pgfs) Create(ctx context.Context, name string) (io.WriteCloser, error) {
|
||||
func (p adapter) Create(ctx context.Context, name string) (io.WriteCloser, error) {
|
||||
var id uuid.UUID
|
||||
if resource, err := p.resourceByPath(ctx, name); err == nil {
|
||||
id = resource.ID
|
||||
@@ -81,52 +77,52 @@ func (p Pgfs) Create(ctx context.Context, name string) (io.WriteCloser, error) {
|
||||
parentPath := name[0:index]
|
||||
parent, err := p.resourceByPath(ctx, parentPath)
|
||||
if err != nil {
|
||||
return nil, fs.ErrNotExist
|
||||
return nil, iofs.ErrNotExist
|
||||
}
|
||||
fileName := name[index+1:]
|
||||
id = uuid.New()
|
||||
if err = p.p.CreateResource(ctx, id, parent.ID, fileName, false); err != nil {
|
||||
if err = p.fs.CreateResource(ctx, id, parent.ID, fileName, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return p.p.UpdateContents(ctx, id)
|
||||
return p.fs.UpdateContents(ctx, id)
|
||||
}
|
||||
|
||||
func (p Pgfs) RemoveAll(ctx context.Context, name string) error {
|
||||
func (p adapter) RemoveAll(ctx context.Context, name string) error {
|
||||
resource, _ := p.resourceByPath(ctx, name)
|
||||
if resource == nil {
|
||||
return fs.ErrNotExist
|
||||
return iofs.ErrNotExist
|
||||
}
|
||||
err := p.p.DeleteRecursive(ctx, resource.ID)
|
||||
err := p.fs.DeleteRecursive(ctx, resource.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p Pgfs) Mkdir(ctx context.Context, name string) error {
|
||||
func (p adapter) Mkdir(ctx context.Context, name string) error {
|
||||
resource, _ := p.resourceByPath(ctx, name)
|
||||
if resource != nil {
|
||||
return fs.ErrExist
|
||||
return iofs.ErrExist
|
||||
}
|
||||
name = strings.TrimRight(name, "/")
|
||||
index := strings.LastIndex(name, "/")
|
||||
parentPath := name[0:index]
|
||||
parent, err := p.resourceByPath(ctx, parentPath)
|
||||
if err != nil {
|
||||
return fs.ErrNotExist
|
||||
return iofs.ErrNotExist
|
||||
}
|
||||
dirName := name[index+1:]
|
||||
err = p.p.CreateResource(ctx, uuid.New(), parent.ID, dirName, true)
|
||||
err = p.fs.CreateResource(ctx, uuid.New(), parent.ID, dirName, true)
|
||||
return err
|
||||
}
|
||||
func (p Pgfs) Copy(ctx context.Context, name, dest string, options *webdav.CopyOptions) (created bool, err error) {
|
||||
func (p adapter) Copy(ctx context.Context, name, dest string, options *webdav.CopyOptions) (created bool, err error) {
|
||||
// TODO: Implement
|
||||
return false, nil
|
||||
}
|
||||
func (p Pgfs) Move(ctx context.Context, name, dest string, options *webdav.MoveOptions) (created bool, err error) {
|
||||
func (p adapter) Move(ctx context.Context, name, dest string, options *webdav.MoveOptions) (created bool, err error) {
|
||||
// TODO: Implement
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (p Pgfs) resourceByPath(ctx context.Context, name string) (res *sql.ResourceByPathRow, err error) {
|
||||
return p.p.ResourceByPath(ctx, strings.TrimPrefix(name, p.prefix+"/"))
|
||||
func (p adapter) resourceByPath(ctx context.Context, name string) (res *sql.ResourceByPathRow, err error) {
|
||||
return p.fs.ResourceByPath(ctx, strings.TrimPrefix(name, p.prefix+"/"))
|
||||
}
|
||||
Reference in New Issue
Block a user