Work in progress
This commit is contained in:
parent
4de3dcc799
commit
466ac8ec26
@ -57,7 +57,7 @@ func (this *database) load(dir string) error {
|
||||
}
|
||||
|
||||
if err := buildNewVersion(this.base); err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
this.vers, err = this.buildVersions(this.base)
|
||||
@ -109,10 +109,10 @@ func (this *database) buildVersions(base string) (versionList, error) {
|
||||
|
||||
sort.Sort(vers)
|
||||
|
||||
var parentVer *version
|
||||
var parVer *version
|
||||
for _, ver := range vers {
|
||||
ver.parent = parentVer
|
||||
parentVer = ver
|
||||
ver.parent = parVer
|
||||
parVer = ver
|
||||
}
|
||||
|
||||
return vers, nil
|
||||
|
38
dir.go
38
dir.go
@ -51,23 +51,17 @@ func newVersionedDir(node *versionedNode, parent *versionedDir) *versionedDir {
|
||||
}
|
||||
|
||||
func (this *versionedDir) version() error {
|
||||
if this.node.versioned {
|
||||
if this.node.flags&NodeFlagVer == NodeFlagVer {
|
||||
return nil
|
||||
}
|
||||
|
||||
version := this.node.ver.db.lastVersion()
|
||||
if err := os.MkdirAll(version.rebasePath(this.node.path), 0755); err != nil {
|
||||
node := newVersionedNode(this.node.path, this.node.ver.db.lastVersion(), this.node, NodeFlagDir|NodeFlagVer)
|
||||
|
||||
if err := os.MkdirAll(node.rebasedPath(), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
node, err := newVersionedNode(this.node.path, version, this.node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
node.versioned = true
|
||||
this.node = node
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -81,11 +75,7 @@ func (this *versionedDir) createDir(name string) (*versionedDir, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node, err := newVersionedNode(childPath, this.node.ver, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node := newVersionedNode(childPath, this.node.ver, nil, NodeFlagDir)
|
||||
dir := newVersionedDir(node, this)
|
||||
this.dirs[name] = dir
|
||||
|
||||
@ -103,11 +93,7 @@ func (this *versionedDir) createFile(name string, flags int) (*versionedFile, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node, err := newVersionedNode(childPath, this.node.ver, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node := newVersionedNode(childPath, this.node.ver, nil, 0)
|
||||
file := newVersionedFile(node, this)
|
||||
file.handle = handle
|
||||
this.files[name] = file
|
||||
@ -116,18 +102,16 @@ func (this *versionedDir) createFile(name string, flags int) (*versionedFile, er
|
||||
}
|
||||
|
||||
func (this *versionedDir) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
this.node.attr(attr)
|
||||
if err := this.node.attr(attr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attr.Inode = this.inode
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *versionedDir) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error {
|
||||
if err := this.node.sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.Attr(ctx, &resp.Attr)
|
||||
return nil
|
||||
return this.Attr(ctx, &resp.Attr)
|
||||
}
|
||||
|
||||
func (this *versionedDir) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
|
||||
|
28
file.go
28
file.go
@ -47,23 +47,17 @@ func newVersionedFile(node *versionedNode, parent *versionedDir) *versionedFile
|
||||
}
|
||||
|
||||
func (this *versionedFile) version() error {
|
||||
if this.node.versioned {
|
||||
if this.node.flags&NodeFlagVer == NodeFlagVer {
|
||||
return nil
|
||||
}
|
||||
|
||||
version := this.node.ver.db.lastVersion()
|
||||
if _, err := fileCopy(this.node.rebasedPath(), version.rebasePath(this.node.path)); err != nil {
|
||||
node := newVersionedNode(this.node.path, this.node.ver.db.lastVersion(), this.node, NodeFlagVer)
|
||||
|
||||
if _, err := fileCopy(this.node.rebasedPath(), node.rebasedPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
node, err := newVersionedNode(this.node.path, version, this.node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
node.versioned = true
|
||||
this.node = node
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -94,12 +88,7 @@ func (this *versionedFile) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
}
|
||||
|
||||
func (this *versionedFile) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error {
|
||||
if err := this.node.sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.Attr(ctx, &resp.Attr)
|
||||
return nil
|
||||
return this.Attr(ctx, &resp.Attr)
|
||||
}
|
||||
|
||||
func (this *versionedFile) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
|
||||
@ -124,7 +113,12 @@ func (this *versionedFile) ReadAll(ctx context.Context) ([]byte, error) {
|
||||
return nil, errors.New("attempted to read from unopened file")
|
||||
}
|
||||
|
||||
data := make([]byte, this.node.info.Size())
|
||||
info, err := os.Stat(this.node.rebasedPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make([]byte, info.Size())
|
||||
if _, err := this.handle.Read(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
93
node.go
93
node.go
@ -33,84 +33,68 @@ import (
|
||||
// versionedNode
|
||||
//
|
||||
|
||||
const (
|
||||
NodeFlagDir = 1 << iota
|
||||
NodeFlagVer
|
||||
)
|
||||
|
||||
type versionedNode struct {
|
||||
path string
|
||||
info os.FileInfo
|
||||
ver *version
|
||||
parent *versionedNode
|
||||
versioned bool
|
||||
path string
|
||||
ver *version
|
||||
parent *versionedNode
|
||||
flags int
|
||||
}
|
||||
|
||||
func newVersionedNode(path string, ver *version, parent *versionedNode) (*versionedNode, error) {
|
||||
info, err := os.Stat(ver.rebasePath(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newVersionedNodeStat(path, ver, parent, info), nil
|
||||
}
|
||||
|
||||
func newVersionedNodeStat(path string, ver *version, parent *versionedNode, info os.FileInfo) *versionedNode {
|
||||
return &versionedNode{path, info, ver, parent, false}
|
||||
func newVersionedNode(path string, ver *version, parent *versionedNode, flags int) *versionedNode {
|
||||
return &versionedNode{path, ver, parent, flags}
|
||||
}
|
||||
|
||||
func (this *versionedNode) setAttr(req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
|
||||
if err := this.attr(&resp.Attr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if req.Valid&fuse.SetattrMode != 0 {
|
||||
if err := os.Chmod(this.rebasedPath(), req.Mode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp.Attr.Mode = req.Mode
|
||||
}
|
||||
|
||||
if setGid, setUid := req.Valid&fuse.SetattrGid != 0, req.Valid&fuse.SetattrUid != 0; setGid || setUid {
|
||||
gid, uid := this.owner()
|
||||
if setGid {
|
||||
gid = req.Gid
|
||||
resp.Attr.Gid = req.Gid
|
||||
}
|
||||
if setUid {
|
||||
uid = req.Uid
|
||||
resp.Attr.Uid = req.Uid
|
||||
}
|
||||
|
||||
if err := os.Chown(this.rebasedPath(), int(uid), int(gid)); err != nil {
|
||||
if err := os.Chown(this.rebasedPath(), int(resp.Attr.Uid), int(resp.Attr.Gid)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if setAtime, setMtime := req.Valid&fuse.SetattrAtime != 0, req.Valid&fuse.SetattrMtime != 0; setAtime || setMtime {
|
||||
atime, mtime, _ := this.times()
|
||||
if setAtime {
|
||||
atime = req.Atime
|
||||
resp.Attr.Atime = req.Atime
|
||||
}
|
||||
if setMtime {
|
||||
mtime = req.Mtime
|
||||
resp.Attr.Mtime = req.Mtime
|
||||
}
|
||||
|
||||
if err := os.Chtimes(this.rebasedPath(), atime, mtime); err != nil {
|
||||
if err := os.Chtimes(this.rebasedPath(), resp.Attr.Atime, resp.Attr.Mtime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := this.sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.attr(&resp.Attr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *versionedNode) sync() error {
|
||||
info, err := os.Stat(this.rebasedPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
this.info = info
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *versionedNode) remove() error {
|
||||
ver := this.ver
|
||||
|
||||
if this.versioned {
|
||||
if this.flags&NodeFlagVer == NodeFlagVer {
|
||||
if err := os.Remove(this.rebasedPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -126,33 +110,36 @@ func (this *versionedNode) rebasedPath() string {
|
||||
return this.ver.rebasePath(this.path)
|
||||
}
|
||||
|
||||
func (this *versionedNode) owner() (gid, uid uint32) {
|
||||
stat := this.info.Sys().(*syscall.Stat_t)
|
||||
|
||||
func (this *versionedNode) owner(stat syscall.Stat_t) (gid, uid uint32) {
|
||||
gid = stat.Gid
|
||||
uid = stat.Uid
|
||||
return
|
||||
}
|
||||
|
||||
func (this *versionedNode) times() (atime, mtime, ctime time.Time) {
|
||||
stat := this.info.Sys().(*syscall.Stat_t)
|
||||
|
||||
func (this *versionedNode) times(stat syscall.Stat_t) (atime, mtime, ctime time.Time) {
|
||||
atime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
|
||||
mtime = this.info.ModTime()
|
||||
mtime = time.Unix(int64(stat.Mtim.Sec), int64(stat.Mtim.Nsec))
|
||||
ctime = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))
|
||||
return
|
||||
}
|
||||
|
||||
func (this *versionedNode) attr(attr *fuse.Attr) {
|
||||
stat := this.info.Sys().(*syscall.Stat_t)
|
||||
func (this *versionedNode) attr(attr *fuse.Attr) error {
|
||||
info, err := os.Stat(this.rebasedPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attr.Size = uint64(this.info.Size())
|
||||
stat := info.Sys().(*syscall.Stat_t)
|
||||
|
||||
attr.Size = uint64(stat.Size)
|
||||
attr.Blocks = uint64(stat.Blocks)
|
||||
attr.Atime, attr.Mtime, attr.Ctime = this.times()
|
||||
attr.Mode = this.info.Mode()
|
||||
attr.Atime, attr.Mtime, attr.Ctime = this.times(*stat)
|
||||
attr.Mode = info.Mode()
|
||||
attr.Nlink = uint32(stat.Nlink)
|
||||
attr.Gid, attr.Uid = this.owner()
|
||||
attr.Gid, attr.Uid = this.owner(*stat)
|
||||
attr.Rdev = uint32(stat.Rdev)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
29
version.go
29
version.go
@ -79,9 +79,15 @@ func (this *version) scanDir(path string) (versionedNodeMap, error) {
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
childFlags := 0
|
||||
if info.IsDir() {
|
||||
childFlags |= NodeFlagDir
|
||||
}
|
||||
|
||||
childName := info.Name()
|
||||
childPath := filepath.Join(path, childName)
|
||||
ownNodes[childName] = newVersionedNodeStat(childPath, this, nil, info)
|
||||
|
||||
ownNodes[childName] = newVersionedNode(childPath, this, nil, childFlags)
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,16 +106,16 @@ func (this *version) scanDir(path string) (versionedNodeMap, error) {
|
||||
return baseNodes, nil
|
||||
}
|
||||
|
||||
func (this *version) buildVerDir(dir *versionedDir) error {
|
||||
func (this *version) buildDir(dir *versionedDir) error {
|
||||
nodes, err := this.scanDir(dir.node.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for name, node := range nodes {
|
||||
if node.info.IsDir() {
|
||||
if node.flags&NodeFlagDir == NodeFlagDir {
|
||||
subDir := newVersionedDir(node, dir)
|
||||
if err := this.buildVerDir(subDir); err != nil {
|
||||
if err := this.buildDir(subDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -123,13 +129,10 @@ func (this *version) buildVerDir(dir *versionedDir) error {
|
||||
}
|
||||
|
||||
func (this *version) resolve() error {
|
||||
node, err := newVersionedNode("/", this, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
node := newVersionedNode("/", this, nil, NodeFlagDir)
|
||||
root := newVersionedDir(node, nil)
|
||||
if err = this.buildVerDir(root); err != nil {
|
||||
|
||||
if err := this.buildDir(root); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -178,11 +181,7 @@ func (this versionList) Less(i, j int) bool {
|
||||
|
||||
func buildNewVersion(base string) error {
|
||||
name := buildVerName(time.Now())
|
||||
|
||||
if err := os.Mkdir(path.Join(base, name), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Mkdir(path.Join(base, name, "root"), 0755); err != nil {
|
||||
if err := os.MkdirAll(path.Join(base, name, "root"), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user