Ver Fonte

projection first step

kpmy há 8 anos atrás
pai
commit
c98750fb4a
3 ficheiros alterados com 290 adições e 6 exclusões
  1. 5 6
      dav_multiuser_cmd/userfs.go
  2. 278 0
      wdfs/projection/fs_sys.go
  3. 7 0
      wdfs/projection/simple_chain.go

+ 5 - 6
dav_multiuser_cmd/userfs.go

@@ -6,6 +6,7 @@ import (
 	"github.com/abbot/go-http-auth"
 	"github.com/kpmy/mipfs/ipfs_api"
 	"github.com/kpmy/mipfs/wdfs"
+	"github.com/kpmy/mipfs/wdfs/projection"
 	. "github.com/kpmy/ypk/tc"
 	"github.com/streamrail/concurrent-map"
 	"github.com/tv42/zbase32"
@@ -42,10 +43,10 @@ func writeRoot(ch chan string, user string) {
 		for p := range pinCh {
 			if p.pin {
 				ipfs_api.Shell().Pin(p.hash)
-				log.Println("pin", p.hash)
+				//log.Println("pin", p.hash)
 			} else if _, ok := importantHash[p.hash]; !ok {
 				ipfs_api.Shell().Unpin(p.hash)
-				log.Println("unpin", p.hash)
+				//log.Println("unpin", p.hash)
 			}
 		}
 	}()
@@ -114,15 +115,13 @@ func handler() http.Handler {
 				KV.Write(user+".root", []byte(defaultRoot))
 			}
 			rm.Set(user+".root", defaultRoot)
-			fs := wdfs.NewFS(func() string {
+			fl.fs, fl.ls = projection.NewPS(func() string {
 				r, _ := rm.Get(user + ".root")
 				return r.(string)
 			}, func(hash string) {
 				rm.Set(user+".root", hash)
 				rootWr <- hash
-			})
-			fl.fs = fs
-			fl.ls = wdfs.NewLS(fs)
+			}, projection.Active)
 			fl.dav = &webdav.Handler{
 				Prefix:     "/ipfs",
 				FileSystem: fl.fs,

+ 278 - 0
wdfs/projection/fs_sys.go

@@ -0,0 +1,278 @@
+package projection //import "github.com/kpmy/mipfs/wdfs/projection"
+
+import (
+	"fmt"
+	"github.com/kpmy/mipfs/ipfs_api"
+	"github.com/kpmy/mipfs/wdfs"
+	"github.com/streamrail/concurrent-map"
+	"golang.org/x/net/webdav"
+	"io"
+	"log"
+	"os"
+	"strings"
+	"time"
+)
+
+const Active = true
+
+const Passive = false
+
+const ProjectionRoot = ".fs"
+
+type Extension interface {
+	ConnectTo(root string)
+	Open(chain []string) (webdav.File, error)
+	os.FileInfo
+	webdav.File
+}
+
+type item struct {
+	name string
+}
+
+func (i *item) Size() int64 {
+	return 0
+}
+func (i *item) Mode() os.FileMode {
+	return 0
+}
+func (i *item) ModTime() time.Time {
+	return time.Now()
+}
+func (i *item) IsDir() bool {
+	return false
+}
+func (i *item) Sys() interface{} {
+	return nil
+}
+func (i *item) Close() error {
+	return nil
+}
+
+func (i *item) Read(p []byte) (n int, err error) {
+	return 0, io.EOF
+}
+
+func (i *item) Seek(offset int64, whence int) (int64, error) {
+	log.Println("seek")
+	return 0, nil
+}
+
+func (i *item) Write(p []byte) (n int, err error) {
+	return 0, webdav.ErrForbidden
+}
+func (i *item) Readdir(count int) (ret []os.FileInfo, err error) {
+	return nil, webdav.ErrForbidden
+}
+
+func (i *item) Stat() (os.FileInfo, error) {
+	return i, nil
+}
+
+func (i *item) Name() string {
+	return i.name
+}
+
+type locator struct {
+}
+
+func (l *locator) Size() int64 {
+	return 0
+}
+func (l *locator) Mode() os.FileMode {
+	return os.ModeDir
+}
+func (l *locator) ModTime() time.Time {
+	return time.Now()
+}
+func (l *locator) IsDir() bool {
+	return true
+}
+func (l *locator) Sys() interface{} {
+	return nil
+}
+func (l *locator) Close() error {
+	return nil
+}
+func (l *locator) Read(p []byte) (n int, err error) {
+	return 0, webdav.ErrForbidden
+}
+func (l *locator) Seek(offset int64, whence int) (int64, error) {
+	return 0, webdav.ErrForbidden
+}
+func (l *locator) Write(p []byte) (n int, err error) {
+	return 0, webdav.ErrForbidden
+}
+
+type ext struct {
+	locator
+	root string
+	name string
+}
+
+func (e *ext) Name() string {
+	return e.name
+}
+
+func (e *ext) Readdir(count int) (ret []os.FileInfo, err error) {
+	log.Println(e.root)
+	var ch <-chan string
+	if ch, err = ipfs_api.Shell().Refs(e.root, true); err == nil {
+		for s := range ch {
+			ret = append(ret, &item{name: s})
+		}
+	}
+	return
+}
+
+func (e *ext) Stat() (os.FileInfo, error) {
+	return e, nil
+}
+
+func (e *ext) Open(chain []string) (ret webdav.File, err error) {
+	if len(chain) == 1 {
+		i := &item{name: chain[0]}
+		ret = i
+	} else {
+		err = os.ErrPermission
+	}
+	return
+}
+
+func (e *ext) ConnectTo(root string) {
+	e.root = root
+}
+
+type cat struct {
+	locator
+	pl map[string]Extension
+}
+
+func (c *cat) Name() string {
+	return ProjectionRoot
+}
+
+func (c *cat) Readdir(count int) (ret []os.FileInfo, err error) {
+	for _, v := range c.pl {
+		ret = append(ret, v)
+	}
+	return
+}
+
+func (c *cat) Stat() (os.FileInfo, error) {
+	return c, nil
+}
+
+type projection struct {
+	inner webdav.FileSystem
+	root  string
+	cache cmap.ConcurrentMap
+	all   *cat
+
+	set func(string)
+	get func() string
+}
+
+func isProjection(split []string) bool {
+	return strings.ToLower(split[0]) == ProjectionRoot
+}
+
+func (p *projection) Mkdir(name string, perm os.FileMode) (err error) {
+	ls := splitPath(name)
+	switch {
+	case len(ls) > 1 && isProjection(ls):
+		err = os.ErrPermission
+	case len(ls) == 1 && isProjection(ls):
+		err = p.inner.Mkdir(strings.ToLower(name), perm)
+	default:
+		err = p.inner.Mkdir(name, perm)
+	}
+	return
+}
+
+func (p *projection) OpenFile(name string, flag int, perm os.FileMode) (ret webdav.File, err error) {
+	log.Println("open", name)
+	ls := splitPath(name)
+	switch {
+	case isProjection(ls) && len(ls) == 1:
+		ret = p.all
+	case isProjection(ls) && len(ls) > 1:
+		if e, ok := p.all.pl[ls[1]]; ok {
+			e.ConnectTo(p.root)
+			if len(ls) > 2 {
+				ret, err = e.Open(ls[2:])
+			} else {
+				ret = e
+			}
+		} else {
+			err = os.ErrNotExist
+		}
+	default:
+		ret, err = p.inner.OpenFile(name, flag, perm)
+	}
+	return
+}
+
+func (p *projection) RemoveAll(name string) (err error) {
+	ls := splitPath(name)
+	switch {
+	case isProjection(ls):
+		err = os.ErrPermission
+	default:
+		err = p.inner.RemoveAll(name)
+	}
+	return
+}
+
+func (p *projection) Rename(oldName, newName string) (err error) {
+	ls := splitPath(oldName)
+	switch {
+	case isProjection(ls):
+		err = os.ErrPermission
+	default:
+		err = p.inner.Rename(oldName, newName)
+	}
+	return
+}
+
+func (p *projection) Stat(name string) (fi os.FileInfo, err error) {
+	log.Println("stat", name)
+	ls := splitPath(name)
+	switch {
+	case isProjection(ls):
+		fi = &cat{}
+	default:
+		fi, err = p.inner.Stat(name)
+	}
+	return
+}
+
+func (p *projection) String() string {
+	return fmt.Sprint(p.inner)
+}
+
+func NewPS(get func() string, set func(string), active bool) (fs webdav.FileSystem, ls webdav.LockSystem) {
+	var pr *projection
+	if active {
+		pr = &projection{get: get}
+		pr.set = func(hash string) {
+			pr.root = hash
+			set(hash)
+		}
+		xs := wdfs.NewFS(pr.get, pr.set)
+		ls = wdfs.NewLS(xs)
+		pr.inner = xs
+
+		pr.cache = cmap.New()
+
+		pr.all = &cat{}
+		pr.all.pl = map[string]Extension{"all": &ext{name: "all"}}
+
+		fs = pr
+	} else {
+		xs := wdfs.NewFS(get, set)
+		ls = wdfs.NewLS(xs)
+		fs = xs
+	}
+	return
+}

+ 7 - 0
wdfs/projection/simple_chain.go

@@ -0,0 +1,7 @@
+package projection
+
+import "strings"
+
+func splitPath(filepath string) []string {
+	return strings.Split(strings.Trim(filepath, "/"), "/")
+}