func GetBundleTimeStamp() time.Time {
	return time.Now().UTC()
}
GetBundleTimeStamp yields the current UTC time
package model
import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"time"
	"github.com/oneconcern/datamon/pkg/cafs"
)
type BundleDescriptor struct {
	LeafSize               uint32        `json:"leafSize" yaml:"leafSize"`                                
	ID                     string        `json:"id" yaml:"id"`                                            
	Message                string        `json:"message" yaml:"message"`                                  
	Parents                []string      `json:"parents,omitempty" yaml:"parents,omitempty"`              
	Timestamp              time.Time     `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`          
	Contributors           []Contributor `json:"contributors" yaml:"contributors"`                        
	BundleEntriesFileCount uint64        `json:"count" yaml:"count"`                                      
	Version                uint64        `json:"version,omitempty" yaml:"version,omitempty"`              
	Deduplication          string        `json:"deduplication,omitempty" yaml:"deduplication,omitempty"`  
	RunStage               string        `json:"runstage,omitempty" yaml:"runstage,omitempty"`            
	_                      struct{}
}
func defaultBundleDescriptor() *BundleDescriptor {
	return &BundleDescriptor{
		LeafSize:      cafs.DefaultLeafSize,  
		Timestamp:     GetBundleTimeStamp(),
		Version:       CurrentBundleVersion,
		Deduplication: cafs.DeduplicationBlake,
	}
}
func NewBundleDescriptor(opts ...BundleDescriptorOption) *BundleDescriptor {
	bd := defaultBundleDescriptor()
	for _, apply := range opts {
		apply(bd)
	}
	return bd
}
type BundleDescriptors []BundleDescriptor
func (b BundleDescriptors) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}
func (b BundleDescriptors) Len() int {
	return len(b)
}
func (b BundleDescriptors) Less(i, j int) bool {
	return b[i].ID < b[j].ID
}
func (b BundleDescriptors) Last() BundleDescriptor {
	return b[len(b)-1]
}
type BundleEntries struct {
	BundleEntries []BundleEntry `json:"BundleEntries" yaml:"BundleEntries"`
	_             struct{}
}
type BundleEntry struct {
	Hash         string      `json:"hash" yaml:"hash"`
	NameWithPath string      `json:"name" yaml:"name"`
	FileMode     os.FileMode `json:"mode" yaml:"mode"`
	Size         uint64      `json:"size" yaml:"size"`
	Timestamp    time.Time   `json:"timestamp,omitempty" yaml:"timestamp,omitempty"`  
	_            struct{}
}
const (
	ConsumableStorePathTypeDescriptor byte = iota
	ConsumableStorePathTypeFileList
)
type ConsumableStorePathMetadata struct {
	Type     byte
	BundleID string
	Index    uint64
}
func GetConsumableStorePathMetadata(path string) (ConsumableStorePathMetadata, error) {
	info := ConsumableStorePathMetadata{}
	metaMatch := metaRe.FindStringSubmatch(path)
	if metaMatch == nil {
		return ConsumableStorePathMetadata{},
			ConsumableStorePathMetadataErr{msg: fmt.Sprintf("not a metadata path '%v'", path)}
	}
	metaName := metaMatch[1]
	flMatch := flRe.FindStringSubmatch(metaName)
	if flMatch == nil {
		info.Type = ConsumableStorePathTypeDescriptor
		info.BundleID = metaName
	} else {
		info.Type = ConsumableStorePathTypeFileList
		info.BundleID = flMatch[1]
		index, err := strconv.Atoi(flMatch[2])
		if err != nil {
			return ConsumableStorePathMetadata{}, err
		}
		info.Index = uint64(index)
	}
	return info, nil
}
func GetConsumablePathToBundle(bundleID string) string {
	path := fmt.Sprint(".datamon/", bundleID, ".yaml")
	info, err := GetConsumableStorePathMetadata(path)
	if err != nil {
		panic(fmt.Errorf("path not valid against inverse function (programming error): %v", err))
	}
	if info.Type != ConsumableStorePathTypeDescriptor {
		panic(fmt.Errorf("unexpected type from inverse function (programming error)"))
	}
	if info.BundleID != bundleID {
		panic(fmt.Errorf("inverse function bundle id '%v' does not match provided id '%v' (programming error)",
			info.BundleID, bundleID))
	}
	return path
}
func GetConsumablePathToBundleFileList(bundleID string, index uint64) string {
	path := fmt.Sprint(".datamon/", bundleID, "-bundle-files-", index, ".yaml")
	info, err := GetConsumableStorePathMetadata(path)
	if err != nil {
		panic(fmt.Errorf("path not valid against inverse function (programming error): %v", err))
	}
	if info.Type != ConsumableStorePathTypeFileList {
		panic(fmt.Errorf("unexpected type from inverse function (programming error)"))
	}
	if info.BundleID != bundleID {
		panic(fmt.Errorf("inverse function bundle id '%v' does not match provided id '%v' (programming error)",
			info.BundleID, bundleID))
	}
	if info.Index != index {
		panic(fmt.Errorf("inverse function index '%v' does not match provided index '%v' (programming error)",
			info.Index, index))
	}
	return path
}
func GetArchivePathToBundle(repo string, bundleID string) string {
	return fmt.Sprint(getArchivePathToBundles(), repo, "/", bundleID, "/", bundleDescriptorFile)
}
func GetArchivePathPrefixToBundles(repo string) string {
	return fmt.Sprint(getArchivePathToBundles(), repo+"/")
}
func getArchivePathToBundles() string {
	return "bundles/"
}
func GetArchivePathToBundleFileList(repo string, bundleID string, index uint64) string {
	return fmt.Sprint(getArchivePathToBundles(), repo, "/", bundleID, "/", bundleFilesIndexPrefix, index, ".yaml")
}
var metaRe, flRe, genFileRe *regexp.Regexp