func NewMutableFS(bundle *core.Bundle, opts ...Option) (*MutableFS, error) {
	if err := checkBundle(bundle); err != nil {
		return nil, err
	}
	pathToStaging, err := localPath(bundle.ConsumableStore)
	if err != nil {
		return nil, err
	}
	fs := defaultMutableFS(bundle, pathToStaging)
	for _, bapply := range opts {
		bapply(fs)
	}
	fs.l = fs.l.With(zap.String("repo", bundle.RepoID))
	if bundle.BundleID != "" {
		fs.l = fs.l.With(zap.String("bundle", bundle.BundleID))
	}
	if fs.MetricsEnabled() {
		fs.m = fs.EnsureMetrics("fuse", &M{}).(*M)
	}
	fs.l.Info("mutable mount staging storage", zap.String("path", pathToStaging))
	err = fs.initRoot()
	if err != nil {
		return nil, err
	}
	return &MutableFS{
		mfs:        nil,
		fsInternal: fs,
		server:     fuseutil.NewFileSystemServer(fs),
	}, nil
}
NewMutableFS creates a new instance of the mutable datamon filesystem.
package fuse
import (
	"context"
	"fmt"
	"os"
	"strings"
	"time"
	"github.com/jacobsa/fuse/fuseops"
	"github.com/oneconcern/datamon/pkg/cafs"
	"github.com/oneconcern/datamon/pkg/core"
	"github.com/oneconcern/datamon/pkg/errors"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	jfuse "github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"
)
const (
	cacheYearLong                    = 365 * 24 * time.Hour
	dirLinkCount     uint32          = 2
	fileLinkCount    uint32          = 1
	rootPath                         = "/"
	firstINode       fuseops.InodeID = 1023
	dirDefaultMode                   = 0777 | os.ModeDir
	fileDefaultMode                  = 0666
	dirReadOnlyMode                  = 0555 | os.ModeDir
	fileReadOnlyMode                 = 0444
	defaultUID                       = 0
	defaultGID                       = 0
	dirInitialSize                   = 64
)
type MountableFS interface {
	Mount(string, ...MountOption) error
	Unmount(string) error
}
var _ MountableFS = &ReadOnlyFS{}
var _ MountableFS = &MutableFS{}
type ReadOnlyFS struct {
	mfs        *jfuse.MountedFileSystem  
	fsInternal *readOnlyFsInternal       
	server     jfuse.Server              
}
type MutableFS struct {
	mfs        *jfuse.MountedFileSystem  
	fsInternal *fsMutable                
	server     jfuse.Server              
}
func checkBundle(bundle *core.Bundle) error {
	if bundle == nil {
		return fmt.Errorf("bundle is nil")
	}
	return nil
}
func NewReadOnlyFS(bundle *core.Bundle, opts ...Option) (*ReadOnlyFS, error) {
	if err := checkBundle(bundle); err != nil {
		return nil, err
	}
	fs := defaultReadOnlyFS(bundle)
	for _, bapply := range opts {
		bapply(fs)
	}
	if fs.MetricsEnabled() {
		fs.m = fs.EnsureMetrics("fuse", &M{}).(*M)
	}
	if fs.streamed {
		cafs, err := cafs.New(
			cafs.LeafSize(bundle.BundleDescriptor.LeafSize),
			cafs.LeafTruncation(bundle.BundleDescriptor.Version < 1),
			cafs.Backend(bundle.BlobStore()),
			cafs.Logger(fs.l),
			cafs.CacheSize(fs.lruSize),
			cafs.Prefetch(fs.prefetch),
			cafs.VerifyHash(fs.withVerifyHash),
			cafs.WithMetrics(fs.MetricsEnabled()),
		)
		if err != nil {
			return nil, err
		}
		fs.cafs = cafs
	}
	fs.l = fs.l.With(zap.String("repo", bundle.RepoID), zap.String("bundle", bundle.BundleID))
	if fs.streamed {
		err := core.PublishMetadata(context.Background(), fs.bundle)
		if err != nil {
			fs.l.Error("Failed to publish bundle metadata", zap.String("id", bundle.BundleID), zap.Error(err))
			return nil, err
		}
	} else {
		err := core.Publish(context.Background(), fs.bundle)
		if err != nil {
			fs.l.Error("Failed to publish bundle", zap.String("id", bundle.BundleID), zap.Error(err))
			return nil, err
		}
	}
	return fs.populateFS(bundle)
}
func localPath(consumable fmt.Stringer) (string, error) {
	fullPath := consumable.String()
	parts := strings.Split(fullPath, "@")
	if len(parts) < 2 || parts[0] != "localfs" {
		return "", errors.New("bundle doesn't have localfs consumable store to provide local cache for mutable fs")
	}
	return parts[1], nil
}