func NewTree(store *Store, opts ...TreeOption) (*Tree, error) {
	debug.Assert(store.blockFactory != nil)
	t := &Tree{
		store:       store,
		rootName:    "root",
		readOnly:    true,
		blockSize:   config.BlockSize,
		lastTrimmed: time.Now(),
	}
	for _, o := range opts {
		if err := o(t); err != nil {
			return nil, fmt.Errorf("tree.NewTree: %v", err)
		}
	}
	if t.root == nil {
		parent := &Node{
			blockFactory: store.blockFactory,
			flags:        loaded,
			info:         NodeInfo{Mode: 0700 | DMDIR},
		}
		root, err := t.Add(parent, t.rootName, 0700|DMDIR)
		if err != nil {
			return nil, fmt.Errorf("tree.NewTree: %v", err)
		}
		t.root = root
		t.root.parent = nil
	} else if t.root.info.Name != t.rootName {
		t.root.info.Name = t.rootName
		t.root.markDirty()
	}
	return t, nil
}
NewTree constructs a new tree object using the given store, and
according to the given options (see the TreeOption section).
package tree
import (
	"errors"
	"fmt"
	"log"
	"path/filepath"
	godebug "runtime/debug"
	"strings"
	"time"
	"github.com/nicolagi/muscle/internal/config"
	"github.com/nicolagi/muscle/internal/debug"
	"github.com/nicolagi/muscle/internal/linuxerr"
	"github.com/nicolagi/muscle/internal/storage"
)
var ErrInUse = errors.New("in use")
type Tree struct {
	store *Store
	revision  storage.Pointer
	root      *Node
	blockSize uint32  
	rootName string
	readOnly bool
	ignored map[string]map[string]struct{}
	lastFlushed time.Time
	lastTrimmed time.Time
}