mirror of
https://github.com/mudler/luet.git
synced 2025-09-02 15:54:39 +00:00
Update gomod and vendor
This commit is contained in:
909
vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
generated
vendored
Normal file
909
vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
generated
vendored
Normal file
@@ -0,0 +1,909 @@
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
iradix "github.com/hashicorp/go-immutable-radix"
|
||||
"github.com/hashicorp/golang-lru/simplelru"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/cache/metadata"
|
||||
"github.com/moby/buildkit/snapshot"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tonistiigi/fsutil"
|
||||
fstypes "github.com/tonistiigi/fsutil/types"
|
||||
)
|
||||
|
||||
var errNotFound = errors.Errorf("not found")
|
||||
|
||||
var defaultManager *cacheManager
|
||||
var defaultManagerOnce sync.Once
|
||||
|
||||
const keyContentHash = "buildkit.contenthash.v0"
|
||||
|
||||
func getDefaultManager() *cacheManager {
|
||||
defaultManagerOnce.Do(func() {
|
||||
lru, _ := simplelru.NewLRU(20, nil) // error is impossible on positive size
|
||||
defaultManager = &cacheManager{lru: lru, locker: locker.New()}
|
||||
})
|
||||
return defaultManager
|
||||
}
|
||||
|
||||
// Layout in the radix tree: Every path is saved by cleaned absolute unix path.
|
||||
// Directories have 2 records, one contains digest for directory header, other
|
||||
// the recursive digest for directory contents. "/dir/" is the record for
|
||||
// header, "/dir" is for contents. For the root node "" (empty string) is the
|
||||
// key for root, "/" for the root header
|
||||
|
||||
func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
|
||||
return getDefaultManager().Checksum(ctx, ref, path, followLinks)
|
||||
}
|
||||
|
||||
func ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
|
||||
return getDefaultManager().ChecksumWildcard(ctx, ref, path, followLinks)
|
||||
}
|
||||
|
||||
func GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
||||
return getDefaultManager().GetCacheContext(ctx, md, idmap)
|
||||
}
|
||||
|
||||
func SetCacheContext(ctx context.Context, md *metadata.StorageItem, cc CacheContext) error {
|
||||
return getDefaultManager().SetCacheContext(ctx, md, cc)
|
||||
}
|
||||
|
||||
func ClearCacheContext(md *metadata.StorageItem) {
|
||||
getDefaultManager().clearCacheContext(md.ID())
|
||||
}
|
||||
|
||||
type CacheContext interface {
|
||||
Checksum(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
|
||||
ChecksumWildcard(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
|
||||
HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) error
|
||||
}
|
||||
|
||||
type Hashed interface {
|
||||
Digest() digest.Digest
|
||||
}
|
||||
|
||||
type Wildcard struct {
|
||||
Path string
|
||||
Record *CacheRecord
|
||||
}
|
||||
|
||||
type cacheManager struct {
|
||||
locker *locker.Locker
|
||||
lru *simplelru.LRU
|
||||
lruMu sync.Mutex
|
||||
}
|
||||
|
||||
func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
|
||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return cc.Checksum(ctx, ref, p, followLinks)
|
||||
}
|
||||
|
||||
func (cm *cacheManager) ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
|
||||
cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return cc.ChecksumWildcard(ctx, ref, p, followLinks)
|
||||
}
|
||||
|
||||
func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
|
||||
cm.locker.Lock(md.ID())
|
||||
cm.lruMu.Lock()
|
||||
v, ok := cm.lru.Get(md.ID())
|
||||
cm.lruMu.Unlock()
|
||||
if ok {
|
||||
cm.locker.Unlock(md.ID())
|
||||
v.(*cacheContext).linkMap = map[string][][]byte{}
|
||||
return v.(*cacheContext), nil
|
||||
}
|
||||
cc, err := newCacheContext(md, idmap)
|
||||
if err != nil {
|
||||
cm.locker.Unlock(md.ID())
|
||||
return nil, err
|
||||
}
|
||||
cm.lruMu.Lock()
|
||||
cm.lru.Add(md.ID(), cc)
|
||||
cm.lruMu.Unlock()
|
||||
cm.locker.Unlock(md.ID())
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func (cm *cacheManager) SetCacheContext(ctx context.Context, md *metadata.StorageItem, cci CacheContext) error {
|
||||
cc, ok := cci.(*cacheContext)
|
||||
if !ok {
|
||||
return errors.Errorf("invalid cachecontext: %T", cc)
|
||||
}
|
||||
if md.ID() != cc.md.ID() {
|
||||
cc = &cacheContext{
|
||||
md: md,
|
||||
tree: cci.(*cacheContext).tree,
|
||||
dirtyMap: map[string]struct{}{},
|
||||
linkMap: map[string][][]byte{},
|
||||
}
|
||||
} else {
|
||||
if err := cc.save(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cm.lruMu.Lock()
|
||||
cm.lru.Add(md.ID(), cc)
|
||||
cm.lruMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cm *cacheManager) clearCacheContext(id string) {
|
||||
cm.lruMu.Lock()
|
||||
cm.lru.Remove(id)
|
||||
cm.lruMu.Unlock()
|
||||
}
|
||||
|
||||
type cacheContext struct {
|
||||
mu sync.RWMutex
|
||||
md *metadata.StorageItem
|
||||
tree *iradix.Tree
|
||||
dirty bool // needs to be persisted to disk
|
||||
|
||||
// used in HandleChange
|
||||
txn *iradix.Txn
|
||||
node *iradix.Node
|
||||
dirtyMap map[string]struct{}
|
||||
linkMap map[string][][]byte
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
type mount struct {
|
||||
mountable cache.Mountable
|
||||
mountPath string
|
||||
unmount func() error
|
||||
}
|
||||
|
||||
func (m *mount) mount(ctx context.Context) (string, error) {
|
||||
if m.mountPath != "" {
|
||||
return m.mountPath, nil
|
||||
}
|
||||
mounts, err := m.mountable.Mount(ctx, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lm := snapshot.LocalMounter(mounts)
|
||||
|
||||
mp, err := lm.Mount()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
m.mountPath = mp
|
||||
m.unmount = lm.Unmount
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
func (m *mount) clean() error {
|
||||
if m.mountPath != "" {
|
||||
if err := m.unmount(); err != nil {
|
||||
return err
|
||||
}
|
||||
m.mountPath = ""
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newCacheContext(md *metadata.StorageItem, idmap *idtools.IdentityMapping) (*cacheContext, error) {
|
||||
cc := &cacheContext{
|
||||
md: md,
|
||||
tree: iradix.New(),
|
||||
dirtyMap: map[string]struct{}{},
|
||||
linkMap: map[string][][]byte{},
|
||||
idmap: idmap,
|
||||
}
|
||||
if err := cc.load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) load() error {
|
||||
dt, err := cc.md.GetExternal(keyContentHash)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var l CacheRecords
|
||||
if err := l.Unmarshal(dt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txn := cc.tree.Txn()
|
||||
for _, p := range l.Paths {
|
||||
txn.Insert([]byte(p.Path), p.Record)
|
||||
}
|
||||
cc.tree = txn.Commit()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) save() error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
if cc.txn != nil {
|
||||
cc.commitActiveTransaction()
|
||||
}
|
||||
|
||||
var l CacheRecords
|
||||
node := cc.tree.Root()
|
||||
node.Walk(func(k []byte, v interface{}) bool {
|
||||
l.Paths = append(l.Paths, &CacheRecordWithPath{
|
||||
Path: string(k),
|
||||
Record: v.(*CacheRecord),
|
||||
})
|
||||
return false
|
||||
})
|
||||
|
||||
dt, err := l.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cc.md.SetExternal(keyContentHash, dt)
|
||||
}
|
||||
|
||||
// HandleChange notifies the source about a modification operation
|
||||
func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) (retErr error) {
|
||||
p = path.Join("/", filepath.ToSlash(p))
|
||||
if p == "/" {
|
||||
p = ""
|
||||
}
|
||||
k := convertPathToKey([]byte(p))
|
||||
|
||||
deleteDir := func(cr *CacheRecord) {
|
||||
if cr.Type == CacheRecordTypeDir {
|
||||
cc.node.WalkPrefix(append(k, 0), func(k []byte, v interface{}) bool {
|
||||
cc.txn.Delete(k)
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
if cc.txn == nil {
|
||||
cc.txn = cc.tree.Txn()
|
||||
cc.node = cc.tree.Root()
|
||||
|
||||
// root is not called by HandleChange. need to fake it
|
||||
if _, ok := cc.node.Get([]byte{0}); !ok {
|
||||
cc.txn.Insert([]byte{0}, &CacheRecord{
|
||||
Type: CacheRecordTypeDirHeader,
|
||||
Digest: digest.FromBytes(nil),
|
||||
})
|
||||
cc.txn.Insert([]byte(""), &CacheRecord{
|
||||
Type: CacheRecordTypeDir,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if kind == fsutil.ChangeKindDelete {
|
||||
v, ok := cc.txn.Delete(k)
|
||||
if ok {
|
||||
deleteDir(v.(*CacheRecord))
|
||||
}
|
||||
d := path.Dir(p)
|
||||
if d == "/" {
|
||||
d = ""
|
||||
}
|
||||
cc.dirtyMap[d] = struct{}{}
|
||||
return
|
||||
}
|
||||
|
||||
stat, ok := fi.Sys().(*fstypes.Stat)
|
||||
if !ok {
|
||||
return errors.Errorf("%s invalid change without stat information", p)
|
||||
}
|
||||
|
||||
h, ok := fi.(Hashed)
|
||||
if !ok {
|
||||
return errors.Errorf("invalid fileinfo: %s", p)
|
||||
}
|
||||
|
||||
v, ok := cc.node.Get(k)
|
||||
if ok {
|
||||
deleteDir(v.(*CacheRecord))
|
||||
}
|
||||
|
||||
cr := &CacheRecord{
|
||||
Type: CacheRecordTypeFile,
|
||||
}
|
||||
if fi.Mode()&os.ModeSymlink != 0 {
|
||||
cr.Type = CacheRecordTypeSymlink
|
||||
cr.Linkname = filepath.ToSlash(stat.Linkname)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
cr.Type = CacheRecordTypeDirHeader
|
||||
cr2 := &CacheRecord{
|
||||
Type: CacheRecordTypeDir,
|
||||
}
|
||||
cc.txn.Insert(k, cr2)
|
||||
k = append(k, 0)
|
||||
p += "/"
|
||||
}
|
||||
cr.Digest = h.Digest()
|
||||
|
||||
// if we receive a hardlink just use the digest of the source
|
||||
// note that the source may be called later because data writing is async
|
||||
if fi.Mode()&os.ModeSymlink == 0 && stat.Linkname != "" {
|
||||
ln := path.Join("/", filepath.ToSlash(stat.Linkname))
|
||||
v, ok := cc.txn.Get(convertPathToKey([]byte(ln)))
|
||||
if ok {
|
||||
cp := *v.(*CacheRecord)
|
||||
cr = &cp
|
||||
}
|
||||
cc.linkMap[ln] = append(cc.linkMap[ln], k)
|
||||
}
|
||||
|
||||
cc.txn.Insert(k, cr)
|
||||
if !fi.IsDir() {
|
||||
if links, ok := cc.linkMap[p]; ok {
|
||||
for _, l := range links {
|
||||
pp := convertKeyToPath(l)
|
||||
cc.txn.Insert(l, cr)
|
||||
d := path.Dir(string(pp))
|
||||
if d == "/" {
|
||||
d = ""
|
||||
}
|
||||
cc.dirtyMap[d] = struct{}{}
|
||||
}
|
||||
delete(cc.linkMap, p)
|
||||
}
|
||||
}
|
||||
|
||||
d := path.Dir(p)
|
||||
if d == "/" {
|
||||
d = ""
|
||||
}
|
||||
cc.dirtyMap[d] = struct{}{}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
|
||||
m := &mount{mountable: mountable}
|
||||
defer m.clean()
|
||||
|
||||
wildcards, err := cc.wildcards(ctx, m, p)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if followLinks {
|
||||
for i, w := range wildcards {
|
||||
if w.Record.Type == CacheRecordTypeSymlink {
|
||||
dgst, err := cc.checksumFollow(ctx, m, w.Path, followLinks)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wildcards[i].Record = &CacheRecord{Digest: dgst}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(wildcards) == 0 {
|
||||
return digest.FromBytes([]byte{}), nil
|
||||
}
|
||||
|
||||
if len(wildcards) > 1 {
|
||||
digester := digest.Canonical.Digester()
|
||||
for i, w := range wildcards {
|
||||
if i != 0 {
|
||||
digester.Hash().Write([]byte{0})
|
||||
}
|
||||
digester.Hash().Write([]byte(w.Record.Digest))
|
||||
}
|
||||
return digester.Digest(), nil
|
||||
} else {
|
||||
return wildcards[0].Record.Digest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
|
||||
m := &mount{mountable: mountable}
|
||||
defer m.clean()
|
||||
|
||||
return cc.checksumFollow(ctx, m, p, followLinks)
|
||||
}
|
||||
|
||||
func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string, follow bool) (digest.Digest, error) {
|
||||
const maxSymlinkLimit = 255
|
||||
i := 0
|
||||
for {
|
||||
if i > maxSymlinkLimit {
|
||||
return "", errors.Errorf("too many symlinks: %s", p)
|
||||
}
|
||||
cr, err := cc.checksumNoFollow(ctx, m, p)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if cr.Type == CacheRecordTypeSymlink && follow {
|
||||
link := cr.Linkname
|
||||
if !path.IsAbs(cr.Linkname) {
|
||||
link = path.Join(path.Dir(p), link)
|
||||
}
|
||||
i++
|
||||
p = link
|
||||
} else {
|
||||
return cr.Digest, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cc *cacheContext) wildcards(ctx context.Context, m *mount, p string) ([]*Wildcard, error) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
if cc.txn != nil {
|
||||
cc.commitActiveTransaction()
|
||||
}
|
||||
|
||||
root := cc.tree.Root()
|
||||
scan, err := cc.needsScan(root, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if scan {
|
||||
if err := cc.scanPath(ctx, m, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if cc.dirty {
|
||||
go cc.save()
|
||||
cc.dirty = false
|
||||
}
|
||||
}()
|
||||
|
||||
p = path.Join("/", filepath.ToSlash(p))
|
||||
if p == "/" {
|
||||
p = ""
|
||||
}
|
||||
|
||||
wildcards := make([]*Wildcard, 0, 2)
|
||||
|
||||
txn := cc.tree.Txn()
|
||||
root = txn.Root()
|
||||
var updated bool
|
||||
|
||||
iter := root.Seek([]byte{})
|
||||
for {
|
||||
k, _, ok := iter.Next()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if len(k) > 0 && k[len(k)-1] == byte(0) {
|
||||
continue
|
||||
}
|
||||
fn := convertKeyToPath(k)
|
||||
b, err := path.Match(p, string(fn))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !b {
|
||||
continue
|
||||
}
|
||||
|
||||
cr, upt, err := cc.checksum(ctx, root, txn, m, k, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if upt {
|
||||
updated = true
|
||||
}
|
||||
|
||||
wildcards = append(wildcards, &Wildcard{Path: string(fn), Record: cr})
|
||||
|
||||
if cr.Type == CacheRecordTypeDir {
|
||||
iter = root.Seek(append(k, 0, 0xff))
|
||||
}
|
||||
}
|
||||
|
||||
cc.tree = txn.Commit()
|
||||
cc.dirty = updated
|
||||
|
||||
return wildcards, nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) checksumNoFollow(ctx context.Context, m *mount, p string) (*CacheRecord, error) {
|
||||
p = path.Join("/", filepath.ToSlash(p))
|
||||
if p == "/" {
|
||||
p = ""
|
||||
}
|
||||
|
||||
cc.mu.RLock()
|
||||
if cc.txn == nil {
|
||||
root := cc.tree.Root()
|
||||
cc.mu.RUnlock()
|
||||
v, ok := root.Get(convertPathToKey([]byte(p)))
|
||||
if ok {
|
||||
cr := v.(*CacheRecord)
|
||||
if cr.Digest != "" {
|
||||
return cr, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cc.mu.RUnlock()
|
||||
}
|
||||
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
if cc.txn != nil {
|
||||
cc.commitActiveTransaction()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if cc.dirty {
|
||||
go cc.save()
|
||||
cc.dirty = false
|
||||
}
|
||||
}()
|
||||
|
||||
return cc.lazyChecksum(ctx, m, p)
|
||||
}
|
||||
|
||||
func (cc *cacheContext) commitActiveTransaction() {
|
||||
for d := range cc.dirtyMap {
|
||||
addParentToMap(d, cc.dirtyMap)
|
||||
}
|
||||
for d := range cc.dirtyMap {
|
||||
k := convertPathToKey([]byte(d))
|
||||
if _, ok := cc.txn.Get(k); ok {
|
||||
cc.txn.Insert(k, &CacheRecord{Type: CacheRecordTypeDir})
|
||||
}
|
||||
}
|
||||
cc.tree = cc.txn.Commit()
|
||||
cc.node = nil
|
||||
cc.dirtyMap = map[string]struct{}{}
|
||||
cc.txn = nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*CacheRecord, error) {
|
||||
root := cc.tree.Root()
|
||||
scan, err := cc.needsScan(root, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if scan {
|
||||
if err := cc.scanPath(ctx, m, p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
k := convertPathToKey([]byte(p))
|
||||
txn := cc.tree.Txn()
|
||||
root = txn.Root()
|
||||
cr, updated, err := cc.checksum(ctx, root, txn, m, k, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cc.tree = txn.Commit()
|
||||
cc.dirty = updated
|
||||
return cr, err
|
||||
}
|
||||
|
||||
func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, follow bool) (*CacheRecord, bool, error) {
|
||||
origk := k
|
||||
k, cr, err := getFollowLinks(root, k, follow)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if cr == nil {
|
||||
return nil, false, errors.Wrapf(errNotFound, "%q not found", convertKeyToPath(origk))
|
||||
}
|
||||
if cr.Digest != "" {
|
||||
return cr, false, nil
|
||||
}
|
||||
var dgst digest.Digest
|
||||
|
||||
switch cr.Type {
|
||||
case CacheRecordTypeDir:
|
||||
h := sha256.New()
|
||||
next := append(k, 0)
|
||||
iter := root.Seek(next)
|
||||
subk := next
|
||||
ok := true
|
||||
for {
|
||||
if !ok || !bytes.HasPrefix(subk, next) {
|
||||
break
|
||||
}
|
||||
h.Write(bytes.TrimPrefix(subk, k))
|
||||
|
||||
subcr, _, err := cc.checksum(ctx, root, txn, m, subk, true)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
h.Write([]byte(subcr.Digest))
|
||||
|
||||
if subcr.Type == CacheRecordTypeDir { // skip subfiles
|
||||
next := append(subk, 0, 0xff)
|
||||
iter = root.Seek(next)
|
||||
}
|
||||
subk, _, ok = iter.Next()
|
||||
}
|
||||
dgst = digest.NewDigest(digest.SHA256, h)
|
||||
|
||||
default:
|
||||
p := string(convertKeyToPath(bytes.TrimSuffix(k, []byte{0})))
|
||||
|
||||
target, err := m.mount(ctx)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// no FollowSymlinkInScope because invalid paths should not be inserted
|
||||
fp := filepath.Join(target, filepath.FromSlash(p))
|
||||
|
||||
fi, err := os.Lstat(fp)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
dgst, err = prepareDigest(fp, p, fi)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
cr2 := &CacheRecord{
|
||||
Digest: dgst,
|
||||
Type: cr.Type,
|
||||
Linkname: cr.Linkname,
|
||||
}
|
||||
|
||||
txn.Insert(k, cr2)
|
||||
|
||||
return cr2, true, nil
|
||||
}
|
||||
|
||||
// needsScan returns false if path is in the tree or a parent path is in tree
|
||||
// and subpath is missing
|
||||
func (cc *cacheContext) needsScan(root *iradix.Node, p string) (bool, error) {
|
||||
var linksWalked int
|
||||
return cc.needsScanFollow(root, p, &linksWalked)
|
||||
}
|
||||
|
||||
func (cc *cacheContext) needsScanFollow(root *iradix.Node, p string, linksWalked *int) (bool, error) {
|
||||
if p == "/" {
|
||||
p = ""
|
||||
}
|
||||
if v, ok := root.Get(convertPathToKey([]byte(p))); !ok {
|
||||
if p == "" {
|
||||
return true, nil
|
||||
}
|
||||
return cc.needsScanFollow(root, path.Clean(path.Dir(p)), linksWalked)
|
||||
} else {
|
||||
cr := v.(*CacheRecord)
|
||||
if cr.Type == CacheRecordTypeSymlink {
|
||||
if *linksWalked > 255 {
|
||||
return false, errTooManyLinks
|
||||
}
|
||||
*linksWalked++
|
||||
link := path.Clean(cr.Linkname)
|
||||
if !path.IsAbs(cr.Linkname) {
|
||||
link = path.Join("/", path.Dir(p), link)
|
||||
}
|
||||
return cc.needsScanFollow(root, link, linksWalked)
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retErr error) {
|
||||
p = path.Join("/", p)
|
||||
d, _ := path.Split(p)
|
||||
|
||||
mp, err := m.mount(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := cc.tree.Root()
|
||||
txn := cc.tree.Txn()
|
||||
|
||||
parentPath, err := rootPath(mp, filepath.FromSlash(d), func(p, link string) error {
|
||||
cr := &CacheRecord{
|
||||
Type: CacheRecordTypeSymlink,
|
||||
Linkname: filepath.ToSlash(link),
|
||||
}
|
||||
k := []byte(filepath.Join("/", filepath.ToSlash(p)))
|
||||
k = convertPathToKey(k)
|
||||
txn.Insert(k, cr)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = filepath.Walk(parentPath, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to walk %s", path)
|
||||
}
|
||||
rel, err := filepath.Rel(mp, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
k := []byte(filepath.Join("/", filepath.ToSlash(rel)))
|
||||
if string(k) == "/" {
|
||||
k = []byte{}
|
||||
}
|
||||
k = convertPathToKey(k)
|
||||
if _, ok := n.Get(k); !ok {
|
||||
cr := &CacheRecord{
|
||||
Type: CacheRecordTypeFile,
|
||||
}
|
||||
if fi.Mode()&os.ModeSymlink != 0 {
|
||||
cr.Type = CacheRecordTypeSymlink
|
||||
link, err := os.Readlink(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cr.Linkname = filepath.ToSlash(link)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
cr.Type = CacheRecordTypeDirHeader
|
||||
cr2 := &CacheRecord{
|
||||
Type: CacheRecordTypeDir,
|
||||
}
|
||||
txn.Insert(k, cr2)
|
||||
k = append(k, 0)
|
||||
}
|
||||
txn.Insert(k, cr)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cc.tree = txn.Commit()
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFollowLinks(root *iradix.Node, k []byte, follow bool) ([]byte, *CacheRecord, error) {
|
||||
var linksWalked int
|
||||
return getFollowLinksWalk(root, k, follow, &linksWalked)
|
||||
}
|
||||
|
||||
func getFollowLinksWalk(root *iradix.Node, k []byte, follow bool, linksWalked *int) ([]byte, *CacheRecord, error) {
|
||||
v, ok := root.Get(k)
|
||||
if ok {
|
||||
return k, v.(*CacheRecord), nil
|
||||
}
|
||||
if !follow || len(k) == 0 {
|
||||
return k, nil, nil
|
||||
}
|
||||
|
||||
dir, file := splitKey(k)
|
||||
|
||||
k, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if parent != nil {
|
||||
if parent.Type == CacheRecordTypeSymlink {
|
||||
*linksWalked++
|
||||
if *linksWalked > 255 {
|
||||
return nil, nil, errors.Errorf("too many links")
|
||||
}
|
||||
dirPath := path.Clean(string(convertKeyToPath(dir)))
|
||||
if dirPath == "." || dirPath == "/" {
|
||||
dirPath = ""
|
||||
}
|
||||
link := path.Clean(parent.Linkname)
|
||||
if !path.IsAbs(link) {
|
||||
link = path.Join("/", path.Join(path.Dir(dirPath), link))
|
||||
}
|
||||
return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked)
|
||||
}
|
||||
}
|
||||
k = append(k, file...)
|
||||
v, ok = root.Get(k)
|
||||
if ok {
|
||||
return k, v.(*CacheRecord), nil
|
||||
}
|
||||
return k, nil, nil
|
||||
}
|
||||
|
||||
func prepareDigest(fp, p string, fi os.FileInfo) (digest.Digest, error) {
|
||||
h, err := NewFileHash(fp, fi)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create hash for %s", p)
|
||||
}
|
||||
if fi.Mode().IsRegular() && fi.Size() > 0 {
|
||||
// TODO: would be nice to put the contents to separate hash first
|
||||
// so it can be cached for hardlinks
|
||||
f, err := os.Open(fp)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to open %s", p)
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := poolsCopy(h, f); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to copy file data for %s", p)
|
||||
}
|
||||
}
|
||||
return digest.NewDigest(digest.SHA256, h), nil
|
||||
}
|
||||
|
||||
func addParentToMap(d string, m map[string]struct{}) {
|
||||
if d == "" {
|
||||
return
|
||||
}
|
||||
d = path.Dir(d)
|
||||
if d == "/" {
|
||||
d = ""
|
||||
}
|
||||
m[d] = struct{}{}
|
||||
addParentToMap(d, m)
|
||||
}
|
||||
|
||||
func ensureOriginMetadata(md *metadata.StorageItem) *metadata.StorageItem {
|
||||
v := md.Get("cache.equalMutable") // TODO: const
|
||||
if v == nil {
|
||||
return md
|
||||
}
|
||||
var mutable string
|
||||
if err := v.Unmarshal(&mutable); err != nil {
|
||||
return md
|
||||
}
|
||||
si, ok := md.Storage().Get(mutable)
|
||||
if ok {
|
||||
return si
|
||||
}
|
||||
return md
|
||||
}
|
||||
|
||||
var pool32K = sync.Pool{
|
||||
New: func() interface{} { return make([]byte, 32*1024) }, // 32K
|
||||
}
|
||||
|
||||
func poolsCopy(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||
buf := pool32K.Get().([]byte)
|
||||
written, err = io.CopyBuffer(dst, src, buf)
|
||||
pool32K.Put(buf)
|
||||
return
|
||||
}
|
||||
|
||||
func convertPathToKey(p []byte) []byte {
|
||||
return bytes.Replace([]byte(p), []byte("/"), []byte{0}, -1)
|
||||
}
|
||||
|
||||
func convertKeyToPath(p []byte) []byte {
|
||||
return bytes.Replace([]byte(p), []byte{0}, []byte("/"), -1)
|
||||
}
|
||||
|
||||
func splitKey(k []byte) ([]byte, []byte) {
|
||||
foundBytes := false
|
||||
i := len(k) - 1
|
||||
for {
|
||||
if i <= 0 || foundBytes && k[i] == 0 {
|
||||
break
|
||||
}
|
||||
if k[i] != 0 {
|
||||
foundBytes = true
|
||||
}
|
||||
i--
|
||||
}
|
||||
return append([]byte{}, k[:i]...), k[i:]
|
||||
}
|
864
vendor/github.com/moby/buildkit/cache/contenthash/checksum.pb.go
generated
vendored
Normal file
864
vendor/github.com/moby/buildkit/cache/contenthash/checksum.pb.go
generated
vendored
Normal file
@@ -0,0 +1,864 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: checksum.proto
|
||||
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type CacheRecordType int32
|
||||
|
||||
const (
|
||||
CacheRecordTypeFile CacheRecordType = 0
|
||||
CacheRecordTypeDir CacheRecordType = 1
|
||||
CacheRecordTypeDirHeader CacheRecordType = 2
|
||||
CacheRecordTypeSymlink CacheRecordType = 3
|
||||
)
|
||||
|
||||
var CacheRecordType_name = map[int32]string{
|
||||
0: "FILE",
|
||||
1: "DIR",
|
||||
2: "DIR_HEADER",
|
||||
3: "SYMLINK",
|
||||
}
|
||||
|
||||
var CacheRecordType_value = map[string]int32{
|
||||
"FILE": 0,
|
||||
"DIR": 1,
|
||||
"DIR_HEADER": 2,
|
||||
"SYMLINK": 3,
|
||||
}
|
||||
|
||||
func (x CacheRecordType) String() string {
|
||||
return proto.EnumName(CacheRecordType_name, int32(x))
|
||||
}
|
||||
|
||||
func (CacheRecordType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_843938c28b799986, []int{0}
|
||||
}
|
||||
|
||||
type CacheRecord struct {
|
||||
Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
|
||||
Type CacheRecordType `protobuf:"varint,2,opt,name=type,proto3,enum=contenthash.CacheRecordType" json:"type,omitempty"`
|
||||
Linkname string `protobuf:"bytes,3,opt,name=linkname,proto3" json:"linkname,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CacheRecord) Reset() { *m = CacheRecord{} }
|
||||
func (m *CacheRecord) String() string { return proto.CompactTextString(m) }
|
||||
func (*CacheRecord) ProtoMessage() {}
|
||||
func (*CacheRecord) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_843938c28b799986, []int{0}
|
||||
}
|
||||
func (m *CacheRecord) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *CacheRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_CacheRecord.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *CacheRecord) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CacheRecord.Merge(m, src)
|
||||
}
|
||||
func (m *CacheRecord) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *CacheRecord) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CacheRecord.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CacheRecord proto.InternalMessageInfo
|
||||
|
||||
func (m *CacheRecord) GetType() CacheRecordType {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return CacheRecordTypeFile
|
||||
}
|
||||
|
||||
func (m *CacheRecord) GetLinkname() string {
|
||||
if m != nil {
|
||||
return m.Linkname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CacheRecordWithPath struct {
|
||||
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
|
||||
Record *CacheRecord `protobuf:"bytes,2,opt,name=record,proto3" json:"record,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CacheRecordWithPath) Reset() { *m = CacheRecordWithPath{} }
|
||||
func (m *CacheRecordWithPath) String() string { return proto.CompactTextString(m) }
|
||||
func (*CacheRecordWithPath) ProtoMessage() {}
|
||||
func (*CacheRecordWithPath) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_843938c28b799986, []int{1}
|
||||
}
|
||||
func (m *CacheRecordWithPath) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *CacheRecordWithPath) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_CacheRecordWithPath.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *CacheRecordWithPath) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CacheRecordWithPath.Merge(m, src)
|
||||
}
|
||||
func (m *CacheRecordWithPath) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *CacheRecordWithPath) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CacheRecordWithPath.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CacheRecordWithPath proto.InternalMessageInfo
|
||||
|
||||
func (m *CacheRecordWithPath) GetPath() string {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CacheRecordWithPath) GetRecord() *CacheRecord {
|
||||
if m != nil {
|
||||
return m.Record
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CacheRecords struct {
|
||||
Paths []*CacheRecordWithPath `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CacheRecords) Reset() { *m = CacheRecords{} }
|
||||
func (m *CacheRecords) String() string { return proto.CompactTextString(m) }
|
||||
func (*CacheRecords) ProtoMessage() {}
|
||||
func (*CacheRecords) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_843938c28b799986, []int{2}
|
||||
}
|
||||
func (m *CacheRecords) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *CacheRecords) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_CacheRecords.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *CacheRecords) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CacheRecords.Merge(m, src)
|
||||
}
|
||||
func (m *CacheRecords) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *CacheRecords) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CacheRecords.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CacheRecords proto.InternalMessageInfo
|
||||
|
||||
func (m *CacheRecords) GetPaths() []*CacheRecordWithPath {
|
||||
if m != nil {
|
||||
return m.Paths
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("contenthash.CacheRecordType", CacheRecordType_name, CacheRecordType_value)
|
||||
proto.RegisterType((*CacheRecord)(nil), "contenthash.CacheRecord")
|
||||
proto.RegisterType((*CacheRecordWithPath)(nil), "contenthash.CacheRecordWithPath")
|
||||
proto.RegisterType((*CacheRecords)(nil), "contenthash.CacheRecords")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("checksum.proto", fileDescriptor_843938c28b799986) }
|
||||
|
||||
var fileDescriptor_843938c28b799986 = []byte{
|
||||
// 426 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x6a, 0x13, 0x41,
|
||||
0x18, 0xc7, 0x77, 0x9a, 0x18, 0xf5, 0x8b, 0xd4, 0x30, 0x85, 0x76, 0x19, 0xca, 0x64, 0xcc, 0xc5,
|
||||
0x50, 0xec, 0xa6, 0x44, 0xf0, 0x6e, 0xdd, 0x84, 0x46, 0xab, 0xc8, 0x54, 0x10, 0xf1, 0x20, 0x9b,
|
||||
0xcd, 0xb8, 0xb3, 0xb4, 0xd9, 0x59, 0x76, 0x27, 0x87, 0xbc, 0x81, 0xec, 0xc9, 0x17, 0xd8, 0x93,
|
||||
0x82, 0xef, 0xe0, 0x5d, 0xe8, 0xb1, 0x47, 0xf1, 0x50, 0x24, 0x79, 0x11, 0xd9, 0xd9, 0x2a, 0xcb,
|
||||
0x4a, 0x4e, 0xf3, 0x7d, 0x33, 0xbf, 0xef, 0xff, 0xff, 0xcf, 0x30, 0xb0, 0xed, 0x4b, 0xe1, 0x9f,
|
||||
0xa7, 0x8b, 0xb9, 0x13, 0x27, 0x4a, 0x2b, 0xdc, 0xf6, 0x55, 0xa4, 0x45, 0xa4, 0xa5, 0x97, 0x4a,
|
||||
0x72, 0x18, 0x84, 0x5a, 0x2e, 0xa6, 0x8e, 0xaf, 0xe6, 0x83, 0x40, 0x05, 0x6a, 0x60, 0x98, 0xe9,
|
||||
0xe2, 0xa3, 0xe9, 0x4c, 0x63, 0xaa, 0x72, 0xb6, 0xf7, 0x0d, 0x41, 0xfb, 0x99, 0xe7, 0x4b, 0xc1,
|
||||
0x85, 0xaf, 0x92, 0x19, 0x7e, 0x0e, 0xad, 0x59, 0x18, 0x88, 0x54, 0xdb, 0x88, 0xa1, 0xfe, 0xdd,
|
||||
0xe3, 0xe1, 0xe5, 0x75, 0xd7, 0xfa, 0x75, 0xdd, 0x3d, 0xa8, 0xc8, 0xaa, 0x58, 0x44, 0x85, 0xa5,
|
||||
0x17, 0x46, 0x22, 0x49, 0x07, 0x81, 0x3a, 0x2c, 0x47, 0x1c, 0xd7, 0x2c, 0xfc, 0x46, 0x01, 0x1f,
|
||||
0x41, 0x53, 0x2f, 0x63, 0x61, 0x6f, 0x31, 0xd4, 0xdf, 0x1e, 0xee, 0x3b, 0x95, 0x98, 0x4e, 0xc5,
|
||||
0xf3, 0xcd, 0x32, 0x16, 0xdc, 0x90, 0x98, 0xc0, 0x9d, 0x8b, 0x30, 0x3a, 0x8f, 0xbc, 0xb9, 0xb0,
|
||||
0x1b, 0x85, 0x3f, 0xff, 0xd7, 0xf7, 0xde, 0xc3, 0x4e, 0x65, 0xe8, 0x6d, 0xa8, 0xe5, 0x6b, 0x4f,
|
||||
0x4b, 0x8c, 0xa1, 0x19, 0x7b, 0x5a, 0x96, 0x71, 0xb9, 0xa9, 0xf1, 0x11, 0xb4, 0x12, 0x43, 0x19,
|
||||
0xeb, 0xf6, 0xd0, 0xde, 0x64, 0xcd, 0x6f, 0xb8, 0xde, 0x18, 0xee, 0x55, 0xb6, 0x53, 0xfc, 0x04,
|
||||
0x6e, 0x15, 0x4a, 0xa9, 0x8d, 0x58, 0xa3, 0xdf, 0x1e, 0xb2, 0x4d, 0x02, 0x7f, 0x63, 0xf0, 0x12,
|
||||
0x3f, 0xf8, 0x81, 0xe0, 0x7e, 0xed, 0x6a, 0xf8, 0x01, 0x34, 0xc7, 0x93, 0xd3, 0x51, 0xc7, 0x22,
|
||||
0x7b, 0x59, 0xce, 0x76, 0x6a, 0xc7, 0xe3, 0xf0, 0x42, 0xe0, 0x2e, 0x34, 0xdc, 0x09, 0xef, 0x20,
|
||||
0xb2, 0x9b, 0xe5, 0x0c, 0xd7, 0x08, 0x37, 0x4c, 0xf0, 0x23, 0x00, 0x77, 0xc2, 0x3f, 0x9c, 0x8c,
|
||||
0x9e, 0xba, 0x23, 0xde, 0xd9, 0x22, 0xfb, 0x59, 0xce, 0xec, 0xff, 0xb9, 0x13, 0xe1, 0xcd, 0x44,
|
||||
0x82, 0x1f, 0xc2, 0xed, 0xb3, 0x77, 0x2f, 0x4f, 0x27, 0xaf, 0x5e, 0x74, 0x1a, 0x84, 0x64, 0x39,
|
||||
0xdb, 0xad, 0xa1, 0x67, 0xcb, 0x79, 0xf1, 0xae, 0x64, 0xef, 0xd3, 0x17, 0x6a, 0x7d, 0xff, 0x4a,
|
||||
0xeb, 0x99, 0x8f, 0xed, 0xcb, 0x15, 0x45, 0x57, 0x2b, 0x8a, 0x7e, 0xaf, 0x28, 0xfa, 0xbc, 0xa6,
|
||||
0xd6, 0xd5, 0x9a, 0x5a, 0x3f, 0xd7, 0xd4, 0x9a, 0xb6, 0xcc, 0xbf, 0x79, 0xfc, 0x27, 0x00, 0x00,
|
||||
0xff, 0xff, 0xfd, 0xd7, 0xd8, 0x37, 0x85, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *CacheRecord) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *CacheRecord) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *CacheRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Linkname) > 0 {
|
||||
i -= len(m.Linkname)
|
||||
copy(dAtA[i:], m.Linkname)
|
||||
i = encodeVarintChecksum(dAtA, i, uint64(len(m.Linkname)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.Type != 0 {
|
||||
i = encodeVarintChecksum(dAtA, i, uint64(m.Type))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
}
|
||||
if len(m.Digest) > 0 {
|
||||
i -= len(m.Digest)
|
||||
copy(dAtA[i:], m.Digest)
|
||||
i = encodeVarintChecksum(dAtA, i, uint64(len(m.Digest)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *CacheRecordWithPath) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *CacheRecordWithPath) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *CacheRecordWithPath) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Record != nil {
|
||||
{
|
||||
size, err := m.Record.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintChecksum(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Path) > 0 {
|
||||
i -= len(m.Path)
|
||||
copy(dAtA[i:], m.Path)
|
||||
i = encodeVarintChecksum(dAtA, i, uint64(len(m.Path)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *CacheRecords) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *CacheRecords) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *CacheRecords) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Paths) > 0 {
|
||||
for iNdEx := len(m.Paths) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Paths[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintChecksum(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintChecksum(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovChecksum(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *CacheRecord) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Digest)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovChecksum(uint64(l))
|
||||
}
|
||||
if m.Type != 0 {
|
||||
n += 1 + sovChecksum(uint64(m.Type))
|
||||
}
|
||||
l = len(m.Linkname)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovChecksum(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *CacheRecordWithPath) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Path)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovChecksum(uint64(l))
|
||||
}
|
||||
if m.Record != nil {
|
||||
l = m.Record.Size()
|
||||
n += 1 + l + sovChecksum(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *CacheRecords) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Paths) > 0 {
|
||||
for _, e := range m.Paths {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovChecksum(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovChecksum(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozChecksum(x uint64) (n int) {
|
||||
return sovChecksum(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *CacheRecord) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: CacheRecord: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: CacheRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Digest", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Digest = github_com_opencontainers_go_digest.Digest(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
m.Type = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Type |= CacheRecordType(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Linkname", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Linkname = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipChecksum(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *CacheRecordWithPath) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: CacheRecordWithPath: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: CacheRecordWithPath: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Path = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Record", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Record == nil {
|
||||
m.Record = &CacheRecord{}
|
||||
}
|
||||
if err := m.Record.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipChecksum(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *CacheRecords) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: CacheRecords: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: CacheRecords: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Paths", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Paths = append(m.Paths, &CacheRecordWithPath{})
|
||||
if err := m.Paths[len(m.Paths)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipChecksum(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthChecksum
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipChecksum(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowChecksum
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthChecksum
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupChecksum
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthChecksum
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthChecksum = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowChecksum = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupChecksum = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
30
vendor/github.com/moby/buildkit/cache/contenthash/checksum.proto
generated
vendored
Normal file
30
vendor/github.com/moby/buildkit/cache/contenthash/checksum.proto
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package contenthash;
|
||||
|
||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
enum CacheRecordType {
|
||||
option (gogoproto.goproto_enum_prefix) = false;
|
||||
option (gogoproto.enum_customname) = "CacheRecordType";
|
||||
|
||||
FILE = 0 [(gogoproto.enumvalue_customname) = "CacheRecordTypeFile"];
|
||||
DIR = 1 [(gogoproto.enumvalue_customname) = "CacheRecordTypeDir"];
|
||||
DIR_HEADER = 2 [(gogoproto.enumvalue_customname) = "CacheRecordTypeDirHeader"];
|
||||
SYMLINK = 3 [(gogoproto.enumvalue_customname) = "CacheRecordTypeSymlink"];
|
||||
}
|
||||
|
||||
message CacheRecord {
|
||||
string digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
CacheRecordType type = 2;
|
||||
string linkname = 3;
|
||||
}
|
||||
|
||||
message CacheRecordWithPath {
|
||||
string path = 1;
|
||||
CacheRecord record = 2;
|
||||
}
|
||||
|
||||
message CacheRecords {
|
||||
repeated CacheRecordWithPath paths = 1;
|
||||
}
|
101
vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
generated
vendored
Normal file
101
vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
fstypes "github.com/tonistiigi/fsutil/types"
|
||||
)
|
||||
|
||||
// NewFileHash returns new hash that is used for the builder cache keys
|
||||
func NewFileHash(path string, fi os.FileInfo) (hash.Hash, error) {
|
||||
var link string
|
||||
if fi.Mode()&os.ModeSymlink != 0 {
|
||||
var err error
|
||||
link, err = os.Readlink(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
stat := &fstypes.Stat{
|
||||
Mode: uint32(fi.Mode()),
|
||||
Size_: fi.Size(),
|
||||
ModTime: fi.ModTime().UnixNano(),
|
||||
Linkname: link,
|
||||
}
|
||||
|
||||
if fi.Mode()&os.ModeSymlink != 0 {
|
||||
stat.Mode = stat.Mode | 0777
|
||||
}
|
||||
|
||||
if err := setUnixOpt(path, fi, stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewFromStat(stat)
|
||||
}
|
||||
|
||||
func NewFromStat(stat *fstypes.Stat) (hash.Hash, error) {
|
||||
// Clear the socket bit since archive/tar.FileInfoHeader does not handle it
|
||||
stat.Mode &^= uint32(os.ModeSocket)
|
||||
|
||||
fi := &statInfo{stat}
|
||||
hdr, err := tar.FileInfoHeader(fi, stat.Linkname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr.Name = "" // note: empty name is different from current has in docker build. Name is added on recursive directory scan instead
|
||||
hdr.Mode = int64(chmodWindowsTarEntry(os.FileMode(hdr.Mode)))
|
||||
hdr.Devmajor = stat.Devmajor
|
||||
hdr.Devminor = stat.Devminor
|
||||
|
||||
if len(stat.Xattrs) > 0 {
|
||||
hdr.Xattrs = make(map[string]string, len(stat.Xattrs))
|
||||
for k, v := range stat.Xattrs {
|
||||
hdr.Xattrs[k] = string(v)
|
||||
}
|
||||
}
|
||||
// fmt.Printf("hdr: %#v\n", hdr)
|
||||
tsh := &tarsumHash{hdr: hdr, Hash: sha256.New()}
|
||||
tsh.Reset() // initialize header
|
||||
return tsh, nil
|
||||
}
|
||||
|
||||
type tarsumHash struct {
|
||||
hash.Hash
|
||||
hdr *tar.Header
|
||||
}
|
||||
|
||||
// Reset resets the Hash to its initial state.
|
||||
func (tsh *tarsumHash) Reset() {
|
||||
// comply with hash.Hash and reset to the state hash had before any writes
|
||||
tsh.Hash.Reset()
|
||||
WriteV1TarsumHeaders(tsh.hdr, tsh.Hash)
|
||||
}
|
||||
|
||||
type statInfo struct {
|
||||
*fstypes.Stat
|
||||
}
|
||||
|
||||
func (s *statInfo) Name() string {
|
||||
return filepath.Base(s.Stat.Path)
|
||||
}
|
||||
func (s *statInfo) Size() int64 {
|
||||
return s.Stat.Size_
|
||||
}
|
||||
func (s *statInfo) Mode() os.FileMode {
|
||||
return os.FileMode(s.Stat.Mode)
|
||||
}
|
||||
func (s *statInfo) ModTime() time.Time {
|
||||
return time.Unix(s.Stat.ModTime/1e9, s.Stat.ModTime%1e9)
|
||||
}
|
||||
func (s *statInfo) IsDir() bool {
|
||||
return s.Mode().IsDir()
|
||||
}
|
||||
func (s *statInfo) Sys() interface{} {
|
||||
return s.Stat
|
||||
}
|
47
vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
generated
vendored
Normal file
47
vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// +build !windows
|
||||
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
fstypes "github.com/tonistiigi/fsutil/types"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func chmodWindowsTarEntry(perm os.FileMode) os.FileMode {
|
||||
return perm
|
||||
}
|
||||
|
||||
func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
|
||||
s := fi.Sys().(*syscall.Stat_t)
|
||||
|
||||
stat.Uid = s.Uid
|
||||
stat.Gid = s.Gid
|
||||
|
||||
if !fi.IsDir() {
|
||||
if s.Mode&syscall.S_IFBLK != 0 ||
|
||||
s.Mode&syscall.S_IFCHR != 0 {
|
||||
stat.Devmajor = int64(unix.Major(uint64(s.Rdev)))
|
||||
stat.Devminor = int64(unix.Minor(uint64(s.Rdev)))
|
||||
}
|
||||
}
|
||||
|
||||
attrs, err := sysx.LListxattr(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(attrs) > 0 {
|
||||
stat.Xattrs = map[string][]byte{}
|
||||
for _, attr := range attrs {
|
||||
v, err := sysx.LGetxattr(path, attr)
|
||||
if err == nil {
|
||||
stat.Xattrs[attr] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
23
vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
generated
vendored
Normal file
23
vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// +build windows
|
||||
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
fstypes "github.com/tonistiigi/fsutil/types"
|
||||
)
|
||||
|
||||
// chmodWindowsTarEntry is used to adjust the file permissions used in tar
|
||||
// header based on the platform the archival is done.
|
||||
func chmodWindowsTarEntry(perm os.FileMode) os.FileMode {
|
||||
perm &= 0755
|
||||
// Add the x bit: make everything +x from windows
|
||||
perm |= 0111
|
||||
|
||||
return perm
|
||||
}
|
||||
|
||||
func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
|
||||
return nil
|
||||
}
|
3
vendor/github.com/moby/buildkit/cache/contenthash/generate.go
generated
vendored
Normal file
3
vendor/github.com/moby/buildkit/cache/contenthash/generate.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
package contenthash
|
||||
|
||||
//go:generate protoc -I=. -I=../../vendor/ --gogofaster_out=. checksum.proto
|
107
vendor/github.com/moby/buildkit/cache/contenthash/path.go
generated
vendored
Normal file
107
vendor/github.com/moby/buildkit/cache/contenthash/path.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
errTooManyLinks = errors.New("too many links")
|
||||
)
|
||||
|
||||
type onSymlinkFunc func(string, string) error
|
||||
|
||||
// rootPath joins a path with a root, evaluating and bounding any
|
||||
// symlink to the root directory.
|
||||
// This is containerd/continuity/fs RootPath implementation with a callback on
|
||||
// resolving the symlink.
|
||||
func rootPath(root, path string, cb onSymlinkFunc) (string, error) {
|
||||
if path == "" {
|
||||
return root, nil
|
||||
}
|
||||
var linksWalked int // to protect against cycles
|
||||
for {
|
||||
i := linksWalked
|
||||
newpath, err := walkLinks(root, path, &linksWalked, cb)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
path = newpath
|
||||
if i == linksWalked {
|
||||
newpath = filepath.Join("/", newpath)
|
||||
if path == newpath {
|
||||
return filepath.Join(root, newpath), nil
|
||||
}
|
||||
path = newpath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func walkLink(root, path string, linksWalked *int, cb onSymlinkFunc) (newpath string, islink bool, err error) {
|
||||
if *linksWalked > 255 {
|
||||
return "", false, errTooManyLinks
|
||||
}
|
||||
|
||||
path = filepath.Join("/", path)
|
||||
if path == "/" {
|
||||
return path, false, nil
|
||||
}
|
||||
realPath := filepath.Join(root, path)
|
||||
|
||||
fi, err := os.Lstat(realPath)
|
||||
if err != nil {
|
||||
// If path does not yet exist, treat as non-symlink
|
||||
if os.IsNotExist(err) {
|
||||
return path, false, nil
|
||||
}
|
||||
return "", false, err
|
||||
}
|
||||
if fi.Mode()&os.ModeSymlink == 0 {
|
||||
return path, false, nil
|
||||
}
|
||||
newpath, err = os.Readlink(realPath)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
if cb != nil {
|
||||
if err := cb(path, newpath); err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
}
|
||||
*linksWalked++
|
||||
return newpath, true, nil
|
||||
}
|
||||
|
||||
func walkLinks(root, path string, linksWalked *int, cb onSymlinkFunc) (string, error) {
|
||||
switch dir, file := filepath.Split(path); {
|
||||
case dir == "":
|
||||
newpath, _, err := walkLink(root, file, linksWalked, cb)
|
||||
return newpath, err
|
||||
case file == "":
|
||||
if os.IsPathSeparator(dir[len(dir)-1]) {
|
||||
if dir == "/" {
|
||||
return dir, nil
|
||||
}
|
||||
return walkLinks(root, dir[:len(dir)-1], linksWalked, cb)
|
||||
}
|
||||
newpath, _, err := walkLink(root, dir, linksWalked, cb)
|
||||
return newpath, err
|
||||
default:
|
||||
newdir, err := walkLinks(root, dir, linksWalked, cb)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
newpath, islink, err := walkLink(root, filepath.Join(newdir, file), linksWalked, cb)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !islink {
|
||||
return newpath, nil
|
||||
}
|
||||
if filepath.IsAbs(newpath) {
|
||||
return newpath, nil
|
||||
}
|
||||
return filepath.Join(newdir, newpath), nil
|
||||
}
|
||||
}
|
63
vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
generated
vendored
Normal file
63
vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package contenthash
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// WriteV1TarsumHeaders writes a tar header to a writer in V1 tarsum format.
|
||||
func WriteV1TarsumHeaders(h *tar.Header, w io.Writer) {
|
||||
for _, elem := range v1TarHeaderSelect(h) {
|
||||
w.Write([]byte(elem[0] + elem[1]))
|
||||
}
|
||||
}
|
||||
|
||||
// Functions below are from docker legacy tarsum implementation.
|
||||
// There is no valid technical reason to continue using them.
|
||||
|
||||
func v0TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
|
||||
return [][2]string{
|
||||
{"name", h.Name},
|
||||
{"mode", strconv.FormatInt(h.Mode, 10)},
|
||||
{"uid", strconv.Itoa(h.Uid)},
|
||||
{"gid", strconv.Itoa(h.Gid)},
|
||||
{"size", strconv.FormatInt(h.Size, 10)},
|
||||
{"mtime", strconv.FormatInt(h.ModTime.UTC().Unix(), 10)},
|
||||
{"typeflag", string([]byte{h.Typeflag})},
|
||||
{"linkname", h.Linkname},
|
||||
{"uname", h.Uname},
|
||||
{"gname", h.Gname},
|
||||
{"devmajor", strconv.FormatInt(h.Devmajor, 10)},
|
||||
{"devminor", strconv.FormatInt(h.Devminor, 10)},
|
||||
}
|
||||
}
|
||||
|
||||
func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
|
||||
// Get extended attributes.
|
||||
xAttrKeys := make([]string, len(h.Xattrs))
|
||||
for k := range h.Xattrs {
|
||||
if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
|
||||
xAttrKeys = append(xAttrKeys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(xAttrKeys)
|
||||
|
||||
// Make the slice with enough capacity to hold the 11 basic headers
|
||||
// we want from the v0 selector plus however many xattrs we have.
|
||||
orderedHeaders = make([][2]string, 0, 11+len(xAttrKeys))
|
||||
|
||||
// Copy all headers from v0 excluding the 'mtime' header (the 5th element).
|
||||
v0headers := v0TarHeaderSelect(h)
|
||||
orderedHeaders = append(orderedHeaders, v0headers[0:5]...)
|
||||
orderedHeaders = append(orderedHeaders, v0headers[6:]...)
|
||||
|
||||
// Finally, append the sorted xattrs.
|
||||
for _, k := range xAttrKeys {
|
||||
orderedHeaders = append(orderedHeaders, [2]string{k, h.Xattrs[k]})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user