func NewMemory(opts *MemRepoOptions) *MemRepo {
	if opts == nil {
		opts = &MemRepoOptions{}
	}
	if opts.ConfigF == nil {
		opts.ConfigF = defConfForType
	}
	if opts.Ds == nil {
		opts.Ds = dssync.MutexWrap(datastore.NewMapDatastore())
	}
	if opts.KeyStore == nil {
		opts.KeyStore = make(map[string]types.KeyInfo)
	}
	return &MemRepo{
		repoLock:   make(chan struct{}, 1),
		blockstore: blockstore.WrapIDStore(blockstore.NewTemporarySync()),
		datastore:  opts.Ds,
		configF:    opts.ConfigF,
		keystore:   opts.KeyStore,
	}
}
NewMemory creates new memory based repo with provided options.
opts can be nil, it  will be replaced with defaults.
Any field in opts can be nil, they will be replaced by defaults.
package repo
import (
	"context"
	"encoding/json"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"github.com/google/uuid"
	"github.com/ipfs/go-datastore"
	"github.com/ipfs/go-datastore/namespace"
	dssync "github.com/ipfs/go-datastore/sync"
	"github.com/multiformats/go-multiaddr"
	"golang.org/x/xerrors"
	"github.com/filecoin-project/lotus/chain/types"
	"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
	"github.com/filecoin-project/lotus/extern/sector-storage/stores"
	"github.com/filecoin-project/lotus/lib/blockstore"
	"github.com/filecoin-project/lotus/node/config"
)
type MemRepo struct {
	api struct {
		sync.Mutex
		ma    multiaddr.Multiaddr
		token []byte
	}
	repoLock chan struct{}
	token    *byte
	datastore  datastore.Datastore
	keystore   map[string]types.KeyInfo
	blockstore blockstore.Blockstore
	configF func(t RepoType) interface{}
	config struct {
		sync.Mutex
		val interface{}
	}
}
type lockedMemRepo struct {
	mem *MemRepo
	t   RepoType
	sync.RWMutex
	tempDir string
	token   *byte
	sc      *stores.StorageConfig
}
func (lmem *lockedMemRepo) GetStorage() (stores.StorageConfig, error) {
	if err := lmem.checkToken(); err != nil {
		return stores.StorageConfig{}, err
	}
	if lmem.sc == nil {
		lmem.sc = &stores.StorageConfig{StoragePaths: []stores.LocalPath{
			{Path: lmem.Path()},
		}}
	}
	return *lmem.sc, nil
}
func (lmem *lockedMemRepo) SetStorage(c func(*stores.StorageConfig)) error {
	if err := lmem.checkToken(); err != nil {
		return err
	}
	_, _ = lmem.GetStorage()
	c(lmem.sc)
	return nil
}
func (lmem *lockedMemRepo) Stat(path string) (fsutil.FsStat, error) {
	return fsutil.Statfs(path)
}
func (lmem *lockedMemRepo) DiskUsage(path string) (int64, error) {
	si, err := fsutil.FileSize(path)
	if err != nil {
		return 0, err
	}
	return si.OnDisk, nil
}
func (lmem *lockedMemRepo) Path() string {
	lmem.Lock()
	defer lmem.Unlock()
	if lmem.tempDir != "" {
		return lmem.tempDir
	}
	t, err := ioutil.TempDir(os.TempDir(), "lotus-memrepo-temp-")
	if err != nil {
		panic(err)  
	}
	if lmem.t == StorageMiner {
		if err := config.WriteStorageFile(filepath.Join(t, fsStorageConfig), stores.StorageConfig{
			StoragePaths: []stores.LocalPath{
				{Path: t},
			}}); err != nil {
			panic(err)
		}
		b, err := json.MarshalIndent(&stores.LocalStorageMeta{
			ID:       stores.ID(uuid.New().String()),
			Weight:   10,
			CanSeal:  true,
			CanStore: true,
		}, "", "  ")
		if err != nil {
			panic(err)
		}
		if err := ioutil.WriteFile(filepath.Join(t, "sectorstore.json"), b, 0644); err != nil {
			panic(err)
		}
	}
	lmem.tempDir = t
	return t
}
var _ Repo = &MemRepo{}
type MemRepoOptions struct {
	Ds       datastore.Datastore
	ConfigF  func(RepoType) interface{}
	KeyStore map[string]types.KeyInfo
}