diff --git a/database.go b/database.go index 6e8ae06..e212044 100644 --- a/database.go +++ b/database.go @@ -27,6 +27,7 @@ import ( "io/ioutil" "path" "path/filepath" + "sort" ) // @@ -35,7 +36,7 @@ import ( type database struct { base string - vers []*version + vers versionList } func newDatabase(dir string) (*database, error) { @@ -75,14 +76,14 @@ func (this *database) save() error { return nil } -func (this *database) buildVersions(base string) ([]*version, error) { +func (this *database) buildVersions(base string) (versionList, error) { nodes, err := ioutil.ReadDir(base) if err != nil { return nil, err } - var prev *version - var vers []*version + var parent *version + var vers versionList for _, node := range nodes { if !node.IsDir() { @@ -94,15 +95,16 @@ func (this *database) buildVersions(base string) ([]*version, error) { return nil, err } - ver, err := newVersion(path.Join(base, node.Name()), timestamp, prev) + ver, err := newVersion(path.Join(base, node.Name()), timestamp, this, parent) if err != nil { return nil, err } vers = append(vers, ver) - prev = ver + parent = ver } + sort.Sort(vers) return vers, nil } diff --git a/dir.go b/dir.go index e343806..cb23cb8 100644 --- a/dir.go +++ b/dir.go @@ -26,6 +26,7 @@ import ( "bazil.org/fuse" "bazil.org/fuse/fs" "golang.org/x/net/context" + "log" "os" "path" ) @@ -40,6 +41,7 @@ type versionedDir struct { node *versionedNode inode uint64 parent *versionedDir + dirty bool } func newVersionedDir(node *versionedNode, parent *versionedDir) *versionedDir { @@ -48,7 +50,35 @@ func newVersionedDir(node *versionedNode, parent *versionedDir) *versionedDir { files: make(map[string]*versionedFile), node: node, inode: allocInode(), - parent: parent} + parent: parent, + dirty: false} +} + +func (this *versionedDir) version() error { + if this.dirty { + log.Printf("not dirty") + return nil + } + + version := this.node.ver.db.lastVersion() + rebasedPath := version.rebasePath(this.node.path) + + if err := os.MkdirAll(rebasedPath, 0755); err != nil { + log.Printf("cannot create directory %s", rebasedPath) + return err + } + + node, err := newVersionedNode(this.node.path, version, this.node) + if err != nil { + log.Printf("cannot create versioned node for %s", rebasedPath) + return err + } + + this.node = node + this.dirty = true + + log.Printf("created directory for %s, %s", version.base, rebasedPath) + return nil } func (this *versionedDir) createDir(name string) (*versionedDir, error) { @@ -109,6 +139,10 @@ func (this *versionedDir) Setattr(ctx context.Context, req *fuse.SetattrRequest, } func (this *versionedDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) { + if err := this.version(); err != nil { + return nil, nil, err + } + if req.Mode.IsDir() { dir, err := this.createDir(req.Name) if err != nil { diff --git a/version.go b/version.go index a0be196..2c77dab 100644 --- a/version.go +++ b/version.go @@ -46,9 +46,10 @@ type version struct { timestamp time.Time meta *versionMetadata root *versionedDir + db *database } -func newVersion(base string, timestamp time.Time, parent *version) (*version, error) { +func newVersion(base string, timestamp time.Time, db *database, parent *version) (*version, error) { meta, err := newVersionMetadata(filepath.Join(base, "meta.json")) if err != nil { return nil, err @@ -58,7 +59,8 @@ func newVersion(base string, timestamp time.Time, parent *version) (*version, er base: base, parent: parent, timestamp: timestamp, - meta: meta} + meta: meta, + db: db} return ver, nil } @@ -171,6 +173,20 @@ func (this *version) Root() (fs.Node, error) { // version helpers // +type versionList []*version + +func (this versionList) Len() int { + return len(this) +} + +func (this versionList) Swap(i, j int) { + this[i], this[j] = this[j], this[i] +} + +func (this versionList) Less(i, j int) bool { + return this[i].timestamp.Unix() < this[j].timestamp.Unix() +} + func buildNewVersion(base string) error { name := buildVerName(time.Now())