Selaa lähdekoodia

сохранение и удаление свойств вместе с файлами,
обнаружена проблема пустого файла

kpmy 8 vuotta sitten
vanhempi
commit
b089f5d78b
7 muutettua tiedostoa jossa 94 lisäystä ja 12 poistoa
  1. 4 1
      .gitignore
  2. 1 1
      dav_test/Dockerfile
  3. 6 0
      wdfs/chain.go
  4. 24 3
      wdfs/file.go
  5. 28 3
      wdfs/fs.go
  6. 12 3
      wdfs/loc.go
  7. 19 1
      wdfs/prop.go

+ 4 - 1
.gitignore

@@ -27,4 +27,7 @@ _testmain.go
 *.iws
 .memo
 
-dav_cmd/.diskv/root
+dav_cmd/.diskv/root
+.diskv
+dav_test
+

+ 1 - 1
dav_test/Dockerfile

@@ -3,4 +3,4 @@ COPY . /usr/src/litmus
 WORKDIR /usr/src/litmus
 RUN ./configure
 RUN make install
-CMD litmus -k http://192.168.1.37:6001/ipfs/
+CMD bash

+ 6 - 0
wdfs/chain.go

@@ -18,6 +18,7 @@ type chain struct {
 func newChain(root *chain, filepath string) (ret *chain) {
 	ns := strings.Split(strings.Trim(filepath, "/"), "/")
 	Assert(ns[0] == root.Hash, 20)
+	root.name = root.Hash
 	ret = root
 	for i := 1; i < len(ns); i++ {
 		down := &chain{}
@@ -78,6 +79,11 @@ func (root *chain) mirror() (ret *chain) {
 	return
 }
 
+func (root *chain) update(hash string) {
+	Assert(hash != "", 20)
+	root.Hash = hash
+}
+
 func (c *chain) Name() string {
 	return c.name
 }

+ 24 - 3
wdfs/file.go

@@ -11,10 +11,12 @@ import (
 	"sync"
 	"time"
 
+	"github.com/kpmy/ypk/dom"
 	. "github.com/kpmy/ypk/tc"
 	"golang.org/x/net/webdav"
 	"io"
 	"log"
+	"strings"
 )
 
 type block struct {
@@ -61,6 +63,9 @@ func (f *file) Close() error {
 	if f.wr != nil {
 		close(f.wr)
 		f.wg.Wait()
+	} else if !f.ch.exists() {
+		log.Println("empty file close")
+		return os.ErrNotExist
 	}
 	return nil
 }
@@ -132,9 +137,15 @@ func (f *file) update(data io.ReadCloser) {
 	f.ch.Hash, _ = ipfs_api.Shell().Add(data)
 	for tail := f.ch.up; tail != nil; tail = tail.up {
 		tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, tail.down.name, tail.down.Hash, false)
+		if tail.down.Hash == f.ch.Hash {
+			//создадим пропы
+			prop := newProps()
+			propHash, _ := ipfs_api.Shell().Add(dom.EncodeWithHeader(prop))
+			tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, "*"+f.ch.name, propHash, false)
+		}
 	}
 	head := f.ch.head()
-	head.link.Hash = head.Hash
+	head.link.update(head.Hash)
 }
 
 func (f *file) Write(p []byte) (n int, err error) {
@@ -162,9 +173,19 @@ func (f *file) Write(p []byte) (n int, err error) {
 	return n, nil
 }
 
-func (f *file) DeadProps() (map[xml.Name]webdav.Property, error) {
+func (f *file) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
 	log.Println("file prop get")
-	return nil, nil
+	if !strings.HasPrefix(f.ch.name, "*") {
+		ls, _ := ipfs_api.Shell().FileList(f.ch.up.Hash)
+		pm := propsMap(ls)
+		if p, ok := pm[f.ch.name]; ok {
+			rd, _ := ipfs_api.Shell().Cat(p.Hash)
+			if el, err := dom.Decode(rd); err == nil {
+				log.Println("file props", el.Model())
+			}
+		}
+	}
+	return
 }
 
 func (f *file) Patch(patch []webdav.Proppatch) ([]webdav.Propstat, error) {

+ 28 - 3
wdfs/fs.go

@@ -43,7 +43,7 @@ func (f *filesystem) Mkdir(name string, perm os.FileMode) (err error) {
 			}
 			tail = tail.up
 		}
-		chain.link.Hash = chain.Hash
+		chain.link.update(chain.Hash)
 	} else {
 		err = os.ErrExist
 	}
@@ -79,31 +79,56 @@ func (f *filesystem) RemoveAll(name string) (err error) {
 	if tail := chain.tail(); tail.exists() {
 		tail = tail.up
 		tail.Hash, _ = ipfs_api.Shell().Patch(tail.Hash, "rm-link", tail.down.name)
+		if !tail.down.IsDir() {
+			//удалим пропы
+			if th, err := ipfs_api.Shell().Patch(tail.Hash, "rm-link", "*"+tail.down.name); err == nil {
+				tail.Hash = th
+			}
+		}
 		tail = tail.up
 		for tail != nil {
 			tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, tail.down.name, tail.down.Hash, false)
 			tail = tail.up
 		}
-		chain.link.Hash = chain.Hash
+		chain.link.update(chain.Hash)
 	}
 	return
 }
 
 func (f *filesystem) Rename(oldName, newName string) (err error) {
+	log.Println("rename", oldName, newName)
 	on := newChain(f.root.mirror(), f.root.Hash+"/"+strings.Trim(oldName, "/"))
+	var op *chain
+	if !on.tail().IsDir() {
+		propPath := ""
+		for x := on; x != nil; x = x.down {
+			if x.down == nil {
+				propPath = propPath + "/" + "*" + x.name
+			} else {
+				propPath = propPath + "/" + x.name
+			}
+		}
+		op = newChain(f.root.mirror(), propPath)
+	}
 	nn := newChain(f.root.mirror(), f.root.Hash+"/"+strings.Trim(newName, "/"))
 	if ot := on.tail(); ot.exists() {
 		if nt := nn.tail(); !nt.exists() {
 			Assert(ot.depth() == nt.depth(), 40)
 			tail := ot.up
 			tail.Hash, _ = ipfs_api.Shell().Patch(tail.Hash, "rm-link", ot.name)
+			if op != nil {
+				tail.Hash, _ = ipfs_api.Shell().Patch(tail.Hash, "rm-link", op.tail().name)
+			}
 			tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, nt.name, ot.Hash, false)
+			if op != nil {
+				tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, "*"+nt.name, op.tail().Hash, false)
+			}
 			tail = tail.up
 			for tail != nil {
 				tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, tail.down.name, tail.down.Hash, false)
 				tail = tail.up
 			}
-			on.link.Hash = on.Hash
+			on.link.update(on.Hash)
 		} else {
 			err = os.ErrExist
 		}

+ 12 - 3
wdfs/loc.go

@@ -3,6 +3,7 @@ package wdfs
 import (
 	"encoding/xml"
 	"github.com/kpmy/mipfs/ipfs_api"
+	"github.com/kpmy/ypk/dom"
 	. "github.com/kpmy/ypk/tc"
 	"golang.org/x/net/webdav"
 	"log"
@@ -52,9 +53,17 @@ func (l *loc) Write(p []byte) (n int, err error) {
 	return 0, webdav.ErrForbidden
 }
 
-func (l *loc) DeadProps() (map[xml.Name]webdav.Property, error) {
-	log.Println("loc prop get")
-	return nil, nil
+func (l *loc) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
+	ls, _ := ipfs_api.Shell().FileList(l.ch.Hash)
+	pm := propsMap(ls)
+	ret = make(map[xml.Name]webdav.Property)
+	if p, ok := pm["*"]; ok {
+		rd, _ := ipfs_api.Shell().Cat(p.Hash)
+		if el, err := dom.Decode(rd); err == nil {
+			log.Println("loc props", el.Model())
+		}
+	}
+	return
 }
 
 func (l *loc) Patch(patch []webdav.Proppatch) ([]webdav.Propstat, error) {

+ 19 - 1
wdfs/prop.go

@@ -1,8 +1,26 @@
 package wdfs
 
-import "github.com/kpmy/ypk/dom"
+import (
+	"github.com/ipfs/go-ipfs-api"
+	"github.com/kpmy/ypk/dom"
+	"strings"
+)
 
 func newProps() (ret dom.Element) {
 	ret = dom.Elem("props")
 	return
 }
+
+func propsMap(obj *shell.UnixLsObject) (ret map[string]*shell.UnixLsLink) {
+	ret = make(map[string]*shell.UnixLsLink)
+	for _, lo := range obj.Links {
+		if lo.Type == "File" {
+			if lo.Name == "*" {
+				ret["*"] = lo
+			} else if strings.HasPrefix(lo.Name, "*") {
+				ret[strings.Trim(lo.Name, "*")] = lo
+			}
+		}
+	}
+	return
+}