ソースを参照

настоящее чтение сохранение удаление свойств, тесты проходит

kpmy 8 年 前
コミット
7e3bd223dd
4 ファイル変更119 行追加16 行削除
  1. 16 8
      dav_cmd/main.go
  2. 76 6
      wdfs/file.go
  3. 1 1
      wdfs/loc.go
  4. 26 1
      wdfs/prop.go

+ 16 - 8
dav_cmd/main.go

@@ -4,11 +4,11 @@ import (
 	"log"
 	"log"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
-	"time"
 
 
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 
 
+	"bytes"
 	"github.com/kpmy/mipfs/ipfs_api"
 	"github.com/kpmy/mipfs/ipfs_api"
 	"github.com/kpmy/mipfs/wdfs"
 	"github.com/kpmy/mipfs/wdfs"
 	"github.com/kpmy/ypk/fn"
 	"github.com/kpmy/ypk/fn"
@@ -32,11 +32,11 @@ func init() {
 
 
 func main() {
 func main() {
 	log.Println(os.Getwd())
 	log.Println(os.Getwd())
-	root := "QmbuSdtGUUfL7DSvvA9DmiGSRqAzkHEjWtsxZDRPBWcawg"
+	defaultRoot := "QmbuSdtGUUfL7DSvvA9DmiGSRqAzkHEjWtsxZDRPBWcawg"
 	if r, err := KV.Read("root"); err == nil && len(r) > 0 {
 	if r, err := KV.Read("root"); err == nil && len(r) > 0 {
-		root = string(r)
+		defaultRoot = string(r)
 	} else {
 	} else {
-		KV.Write("root", []byte(root))
+		KV.Write("root", []byte(defaultRoot))
 	}
 	}
 
 
 	if r, err := KV.Read("ipfs"); err == nil {
 	if r, err := KV.Read("ipfs"); err == nil {
@@ -50,7 +50,13 @@ func main() {
 			for s := range ch {
 			for s := range ch {
 				if s != "" {
 				if s != "" {
 					if old, err := KV.Read("root"); err == nil && s != string(old) {
 					if old, err := KV.Read("root"); err == nil && s != string(old) {
-						KV.Write(fmt.Sprint("root.", time.Now().UnixNano(), ".", i), old)
+						history := new(bytes.Buffer)
+						if hs, err := KV.Read("root.history"); err == nil {
+							history.Write(hs)
+							history.Write([]byte("\n"))
+						}
+						history.Write(old)
+						KV.Write("root.history", history.Bytes())
 						i++
 						i++
 					}
 					}
 					KV.Write("root", []byte(s))
 					KV.Write("root", []byte(s))
@@ -64,7 +70,7 @@ func main() {
 	var fs webdav.FileSystem
 	var fs webdav.FileSystem
 	var ls webdav.LockSystem
 	var ls webdav.LockSystem
 	if nodeID, err := ipfs_api.Shell().ID(); err == nil {
 	if nodeID, err := ipfs_api.Shell().ID(); err == nil {
-		fs = wdfs.NewFS(nodeID, root)
+		fs = wdfs.NewFS(nodeID, defaultRoot)
 		ls = wdfs.NewLS(fs)
 		ls = wdfs.NewLS(fs)
 	} else {
 	} else {
 		log.Fatal(err)
 		log.Fatal(err)
@@ -94,8 +100,10 @@ func main() {
 		http.Handle("/ipfs", h)
 		http.Handle("/ipfs", h)
 	}
 	}
 	http.HandleFunc("/hash", func(resp http.ResponseWriter, req *http.Request) {
 	http.HandleFunc("/hash", func(resp http.ResponseWriter, req *http.Request) {
-		if r, err := KV.Read("root"); err == nil {
-			resp.Write(r)
+		if rh, err := KV.Read("root"); err == nil {
+			rootHash := string(rh)
+			tpl := "<html><body><a href='http://o.ocsf.in:8080/ipfs/" + rootHash + "'>" + rootHash + "</a></body></html>"
+			resp.Write([]byte(tpl))
 		}
 		}
 	})
 	})
 	const addr = "0.0.0.0:6001"
 	const addr = "0.0.0.0:6001"

+ 76 - 6
wdfs/file.go

@@ -11,11 +11,13 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"bytes"
 	"github.com/kpmy/ypk/dom"
 	"github.com/kpmy/ypk/dom"
 	. "github.com/kpmy/ypk/tc"
 	. "github.com/kpmy/ypk/tc"
 	"golang.org/x/net/webdav"
 	"golang.org/x/net/webdav"
 	"io"
 	"io"
 	"log"
 	"log"
+	"reflect"
 	"strings"
 	"strings"
 )
 )
 
 
@@ -178,22 +180,90 @@ func (f *file) Write(p []byte) (n int, err error) {
 	return n, nil
 	return n, nil
 }
 }
 
 
-func (f *file) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
-	log.Println("file prop get")
+func (f *file) readPropsObject() (props map[xml.Name]dom.Element, err error) {
 	if !strings.HasPrefix(f.ch.name, "*") {
 	if !strings.HasPrefix(f.ch.name, "*") {
 		ls, _ := ipfs_api.Shell().FileList(f.ch.up.Hash)
 		ls, _ := ipfs_api.Shell().FileList(f.ch.up.Hash)
-		pm := propsMap(ls)
+		pm := propLinksMap(ls)
 		if p, ok := pm[f.ch.name]; ok {
 		if p, ok := pm[f.ch.name]; ok {
 			rd, _ := ipfs_api.Shell().Cat(p.Hash)
 			rd, _ := ipfs_api.Shell().Cat(p.Hash)
 			if el, err := dom.Decode(rd); err == nil {
 			if el, err := dom.Decode(rd); err == nil {
-				log.Println("file props", el.Model())
+				props = readProps(el.Model())
+			}
+		}
+	}
+	return
+}
+
+func (f *file) writePropsObject(props map[xml.Name]dom.Element) {
+	if !strings.HasPrefix(f.ch.name, "*") {
+		el := writeProps(props)
+		propHash, _ := ipfs_api.Shell().Add(dom.Encode(el))
+		for tail := f.ch.up; tail != nil; tail = tail.up {
+			if tail.down.Hash == f.ch.Hash {
+				tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, "*"+f.ch.name, propHash, false)
+			} else {
+				tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, tail.down.name, tail.down.Hash, false)
 			}
 			}
 		}
 		}
+		head := f.ch.head()
+		head.link.update(head.Hash)
+	}
+}
+
+func (f *file) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
+	log.Println("file prop get")
+	ret = make(map[xml.Name]webdav.Property)
+	pm, _ := f.readPropsObject()
+	for k, v := range pm {
+		p := webdav.Property{XMLName: k}
+		buf := new(bytes.Buffer)
+		Assert(v.ChildrenCount() == 1, 40)
+		c0 := v.Children()[0]
+		switch c := c0.(type) {
+		case dom.Element:
+			rd := dom.Encode(c)
+			io.Copy(buf, rd)
+		case dom.Text:
+			xml.EscapeText(buf, []byte(c.Data()))
+		default:
+			Halt(100, reflect.TypeOf(c))
+		}
+		p.InnerXML = buf.Bytes()
+		ret[k] = p
 	}
 	}
+	log.Println("read file props", ret)
 	return
 	return
 }
 }
 
 
-func (f *file) Patch(patch []webdav.Proppatch) ([]webdav.Propstat, error) {
+func (f *file) Patch(patch []webdav.Proppatch) (ret []webdav.Propstat, err error) {
 	log.Println("file prop patch", patch)
 	log.Println("file prop patch", patch)
-	return nil, nil
+	ret = []webdav.Propstat{}
+	pe, _ := f.readPropsObject()
+	for _, pl := range patch {
+		ps := webdav.Propstat{}
+		for _, p := range pl.Props {
+			if pl.Remove {
+				delete(pe, p.XMLName)
+			} else {
+				el := dom.Elem("prop")
+				el.Attr("local", p.XMLName.Local)
+				el.Attr("space", p.XMLName.Space)
+				e, _ := dom.Decode(bytes.NewBuffer(p.InnerXML))
+				if !fn.IsNil(e.Model()) {
+					el.AppendChild(e.Model())
+				} else if !fn.IsNil(e.Data()) {
+					el.AppendChild(e.Data())
+				} else {
+					Halt(100)
+				}
+				pe[p.XMLName] = el
+			}
+			ps.Props = append(ps.Props, p)
+		}
+		ps.Status = 200
+		ret = append(ret, ps)
+	}
+	log.Println("write file props", pe)
+	f.writePropsObject(pe)
+	return
 }
 }

+ 1 - 1
wdfs/loc.go

@@ -55,7 +55,7 @@ func (l *loc) Write(p []byte) (n int, err error) {
 
 
 func (l *loc) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
 func (l *loc) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
 	ls, _ := ipfs_api.Shell().FileList(l.ch.Hash)
 	ls, _ := ipfs_api.Shell().FileList(l.ch.Hash)
-	pm := propsMap(ls)
+	pm := propLinksMap(ls)
 	ret = make(map[xml.Name]webdav.Property)
 	ret = make(map[xml.Name]webdav.Property)
 	if p, ok := pm["*"]; ok {
 	if p, ok := pm["*"]; ok {
 		rd, _ := ipfs_api.Shell().Cat(p.Hash)
 		rd, _ := ipfs_api.Shell().Cat(p.Hash)

+ 26 - 1
wdfs/prop.go

@@ -1,8 +1,11 @@
 package wdfs
 package wdfs
 
 
 import (
 import (
+	"encoding/xml"
 	"github.com/ipfs/go-ipfs-api"
 	"github.com/ipfs/go-ipfs-api"
 	"github.com/kpmy/ypk/dom"
 	"github.com/kpmy/ypk/dom"
+	. "github.com/kpmy/ypk/tc"
+	"reflect"
 	"strings"
 	"strings"
 )
 )
 
 
@@ -11,7 +14,29 @@ func newProps() (ret dom.Element) {
 	return
 	return
 }
 }
 
 
-func propsMap(obj *shell.UnixLsObject) (ret map[string]*shell.UnixLsLink) {
+func readProps(model dom.Element) (ret map[xml.Name]dom.Element) {
+	ret = make(map[xml.Name]dom.Element)
+	for _, _e := range model.Children() {
+		switch e := _e.(type) {
+		case dom.Element:
+			xn := xml.Name{Local: e.Attr("local"), Space: e.Attr("space")}
+			ret[xn] = e
+		default:
+			Halt(100, reflect.TypeOf(e))
+		}
+	}
+	return
+}
+
+func writeProps(props map[xml.Name]dom.Element) (ret dom.Element) {
+	ret = dom.Elem("props")
+	for _, v := range props {
+		ret.AppendChild(v)
+	}
+	return
+}
+
+func propLinksMap(obj *shell.UnixLsObject) (ret map[string]*shell.UnixLsLink) {
 	ret = make(map[string]*shell.UnixLsLink)
 	ret = make(map[string]*shell.UnixLsLink)
 	for _, lo := range obj.Links {
 	for _, lo := range obj.Links {
 		if lo.Type == "File" {
 		if lo.Type == "File" {