Merge pull request #850 from tonistiigi/contenthash-wildcards
contenthash: add wildcard and nofollow supportdocker-19.03
commit
e814100f45
|
@ -43,8 +43,8 @@ func getDefaultManager() *cacheManager {
|
|||
// 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) (digest.Digest, error) {
|
||||
return getDefaultManager().Checksum(ctx, ref, path)
|
||||
func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
|
||||
return getDefaultManager().Checksum(ctx, ref, path, followLinks)
|
||||
}
|
||||
|
||||
func GetCacheContext(ctx context.Context, md *metadata.StorageItem) (CacheContext, error) {
|
||||
|
@ -56,7 +56,8 @@ func SetCacheContext(ctx context.Context, md *metadata.StorageItem, cc CacheCont
|
|||
}
|
||||
|
||||
type CacheContext interface {
|
||||
Checksum(ctx context.Context, ref cache.Mountable, p string) (digest.Digest, error)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -64,18 +65,23 @@ 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) (digest.Digest, error) {
|
||||
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()))
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return cc.Checksum(ctx, ref, p)
|
||||
return cc.Checksum(ctx, ref, p, followLinks)
|
||||
}
|
||||
|
||||
func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem) (CacheContext, error) {
|
||||
|
@ -317,10 +323,49 @@ func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.Fil
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string) (digest.Digest, error) {
|
||||
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) > 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 {
|
||||
|
@ -331,7 +376,7 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if cr.Type == CacheRecordTypeSymlink {
|
||||
if cr.Type == CacheRecordTypeSymlink && follow {
|
||||
link := cr.Linkname
|
||||
if !path.IsAbs(cr.Linkname) {
|
||||
link = path.Join(path.Dir(p), link)
|
||||
|
@ -344,6 +389,82 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
|
|||
}
|
||||
}
|
||||
|
||||
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 == "/" {
|
||||
|
@ -412,7 +533,7 @@ func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*
|
|||
k := convertPathToKey([]byte(p))
|
||||
txn := cc.tree.Txn()
|
||||
root = txn.Root()
|
||||
cr, updated, err := cc.checksum(ctx, root, txn, m, k)
|
||||
cr, updated, err := cc.checksum(ctx, root, txn, m, k, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -421,8 +542,8 @@ func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*
|
|||
return cr, err
|
||||
}
|
||||
|
||||
func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte) (*CacheRecord, bool, error) {
|
||||
k, cr, err := getFollowLinks(root, k)
|
||||
func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, follow bool) (*CacheRecord, bool, error) {
|
||||
k, cr, err := getFollowLinks(root, k, follow)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
@ -447,7 +568,7 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir
|
|||
}
|
||||
h.Write(bytes.TrimPrefix(subk, k))
|
||||
|
||||
subcr, _, err := cc.checksum(ctx, root, txn, m, subk)
|
||||
subcr, _, err := cc.checksum(ctx, root, txn, m, subk, true)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
@ -599,23 +720,23 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retEr
|
|||
return nil
|
||||
}
|
||||
|
||||
func getFollowLinks(root *iradix.Node, k []byte) ([]byte, *CacheRecord, error) {
|
||||
func getFollowLinks(root *iradix.Node, k []byte, follow bool) ([]byte, *CacheRecord, error) {
|
||||
var linksWalked int
|
||||
return getFollowLinksWalk(root, k, &linksWalked)
|
||||
return getFollowLinksWalk(root, k, follow, &linksWalked)
|
||||
}
|
||||
|
||||
func getFollowLinksWalk(root *iradix.Node, k []byte, linksWalked *int) ([]byte, *CacheRecord, error) {
|
||||
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 len(k) == 0 {
|
||||
if !follow || len(k) == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
dir, file := splitKey(k)
|
||||
|
||||
_, parent, err := getFollowLinksWalk(root, dir, linksWalked)
|
||||
_, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -632,7 +753,7 @@ func getFollowLinksWalk(root *iradix.Node, k []byte, linksWalked *int) ([]byte,
|
|||
if !path.IsAbs(link) {
|
||||
link = path.Join("/", path.Join(path.Dir(dirPath), link))
|
||||
}
|
||||
return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), linksWalked)
|
||||
return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked)
|
||||
}
|
||||
|
||||
return nil, nil, nil
|
||||
|
|
|
@ -29,6 +29,120 @@ const (
|
|||
dgstDirD0Modified = digest.Digest("sha256:555ffa3028630d97ba37832b749eda85ab676fd64ffb629fbf0f4ec8c1e3bff1")
|
||||
)
|
||||
|
||||
func TestChecksumWildcard(t *testing.T) {
|
||||
t.Parallel()
|
||||
tmpdir, err := ioutil.TempDir("", "buildkit-state")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
snapshotter, err := native.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
|
||||
require.NoError(t, err)
|
||||
cm := setupCacheManager(t, tmpdir, snapshotter)
|
||||
defer cm.Close()
|
||||
|
||||
ch := []string{
|
||||
"ADD bar file data1",
|
||||
"ADD foo file data0",
|
||||
"ADD fox file data2",
|
||||
"ADD x dir",
|
||||
"ADD x/d0 dir",
|
||||
"ADD x/d0/abc file data0",
|
||||
"ADD x/d0/def symlink abc",
|
||||
"ADD x/d0/ghi symlink nosuchfile",
|
||||
"ADD y1 symlink foo",
|
||||
"ADD y2 symlink fox",
|
||||
}
|
||||
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := cc.ChecksumWildcard(context.TODO(), ref, "f*o", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
expFoos := digest.Digest("sha256:c9f914ad7ad8fe6092ce67484b43ca39c2087aabf9e4a1b223249b0f8b09b9f2")
|
||||
|
||||
dgst, err = cc.ChecksumWildcard(context.TODO(), ref, "f*", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expFoos, dgst)
|
||||
|
||||
dgst, err = cc.ChecksumWildcard(context.TODO(), ref, "x/d?", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstDirD0, dgst)
|
||||
|
||||
dgst, err = cc.ChecksumWildcard(context.TODO(), ref, "x/d?/def", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
dgst, err = cc.ChecksumWildcard(context.TODO(), ref, "y*", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expFoos, dgst)
|
||||
|
||||
err = ref.Release(context.TODO())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestSymlinksNoFollow(t *testing.T) {
|
||||
t.Parallel()
|
||||
tmpdir, err := ioutil.TempDir("", "buildkit-state")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
snapshotter, err := native.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
|
||||
require.NoError(t, err)
|
||||
cm := setupCacheManager(t, tmpdir, snapshotter)
|
||||
defer cm.Close()
|
||||
|
||||
ch := []string{
|
||||
"ADD target file data0",
|
||||
"ADD sym symlink target",
|
||||
"ADD sym2 symlink target2",
|
||||
"ADD foo dir",
|
||||
"ADD foo/ghi symlink target",
|
||||
"ADD y1 symlink foo/ghi",
|
||||
}
|
||||
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
cc, err := newCacheContext(ref.Metadata())
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSym := digest.Digest("sha256:a2ba571981f48ec34eb79c9a3ab091b6491e825c2f7e9914ea86e8e958be7fae")
|
||||
|
||||
dgst, err := cc.ChecksumWildcard(context.TODO(), ref, "sym", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedSym, dgst)
|
||||
|
||||
dgst, err = cc.ChecksumWildcard(context.TODO(), ref, "sym2", false)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, expectedSym, dgst)
|
||||
|
||||
dgst, err = cc.ChecksumWildcard(context.TODO(), ref, "foo/ghi", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedSym, dgst)
|
||||
|
||||
_, err = cc.ChecksumWildcard(context.TODO(), ref, "foo/ghi", true) // same because broken symlink
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errNotFound, errors.Cause(err))
|
||||
|
||||
_, err = cc.ChecksumWildcard(context.TODO(), ref, "y1", true)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errNotFound, errors.Cause(err))
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "sym", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedSym, dgst)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "foo/ghi", false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedSym, dgst)
|
||||
|
||||
err = ref.Release(context.TODO())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestChecksumBasicFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
tmpdir, err := ioutil.TempDir("", "buildkit-state")
|
||||
|
@ -57,48 +171,48 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
cc, err := newCacheContext(ref.Metadata())
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = cc.Checksum(context.TODO(), ref, "nosuch")
|
||||
_, err = cc.Checksum(context.TODO(), ref, "nosuch", true)
|
||||
require.Error(t, err)
|
||||
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "foo")
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "foo", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
// second file returns different hash
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "bar")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "bar", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, digest.Digest("sha256:c2b5e234f5f38fc5864da7def04782f82501a40d46192e4207d5b3f0c3c4732b"), dgst)
|
||||
|
||||
// same file inside a directory
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0/abc")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0/abc", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
// repeat because codepath is different
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0/abc")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0/abc", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
// symlink to the same file is followed, returns same hash
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0/def")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0/def", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
_, err = cc.Checksum(context.TODO(), ref, "d0/ghi")
|
||||
_, err = cc.Checksum(context.TODO(), ref, "d0/ghi", true)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errNotFound, errors.Cause(err))
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, digest.Digest("sha256:427c9cf9ae98c0f81fb57a3076b965c7c149b6b0a85625ad4e884236649a42c6"), dgst)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstDirD0, dgst)
|
||||
|
@ -118,7 +232,7 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
cc, err = newCacheContext(ref.Metadata())
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstDirD0, dgst)
|
||||
|
@ -137,7 +251,7 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
cc, err = newCacheContext(ref.Metadata())
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "/", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstDirD0Modified, dgst)
|
||||
|
@ -163,14 +277,14 @@ func TestChecksumBasicFile(t *testing.T) {
|
|||
cc, err = newCacheContext(ref.Metadata())
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "abc/aa/foo")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "abc/aa/foo", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, digest.Digest("sha256:1c67653c3cf95b12a0014e2c4cd1d776b474b3218aee54155d6ae27b9b999c54"), dgst)
|
||||
require.NotEqual(t, dgstDirD0, dgst)
|
||||
|
||||
// this will force rescan
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstDirD0, dgst)
|
||||
|
@ -210,19 +324,19 @@ func TestHandleChange(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgstFoo, err := cc.Checksum(context.TODO(), ref, "foo")
|
||||
dgstFoo, err := cc.Checksum(context.TODO(), ref, "foo", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstFileData0, dgstFoo)
|
||||
|
||||
// symlink to the same file is followed, returns same hash
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d0/def")
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d0/def", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstFoo, dgst)
|
||||
|
||||
// symlink to the same file is followed, returns same hash
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgstDirD0, dgst)
|
||||
|
@ -234,7 +348,7 @@ func TestHandleChange(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstDirD0Modified, dgst)
|
||||
|
||||
|
@ -245,11 +359,11 @@ func TestHandleChange(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = cc.Checksum(context.TODO(), ref, "d0")
|
||||
_, err = cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errNotFound, errors.Cause(err))
|
||||
|
||||
_, err = cc.Checksum(context.TODO(), ref, "d0/abc")
|
||||
_, err = cc.Checksum(context.TODO(), ref, "d0/abc", true)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errNotFound, errors.Cause(err))
|
||||
|
||||
|
@ -286,7 +400,7 @@ func TestHandleRecursiveDir(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d0/foo/bar")
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d0/foo/bar", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
ch = []string{
|
||||
|
@ -298,11 +412,11 @@ func TestHandleRecursiveDir(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst2, err := cc.Checksum(context.TODO(), ref, "d1")
|
||||
dgst2, err := cc.Checksum(context.TODO(), ref, "d1", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgst2, dgst)
|
||||
|
||||
_, err = cc.Checksum(context.TODO(), ref, "")
|
||||
_, err = cc.Checksum(context.TODO(), ref, "", true)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -333,7 +447,7 @@ func TestChecksumUnorderedFiles(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d0")
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, dgst, digest.Digest("sha256:14276c302c940a80f82ca5477bf766c98a24702d6a9948ee71bb277cdad3ae05"))
|
||||
|
@ -353,7 +467,7 @@ func TestChecksumUnorderedFiles(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst2, err := cc.Checksum(context.TODO(), ref, "d0")
|
||||
dgst2, err := cc.Checksum(context.TODO(), ref, "d0", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, dgst, dgst2)
|
||||
|
@ -378,11 +492,11 @@ func TestSymlinkInPathScan(t *testing.T) {
|
|||
}
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
dgst, err := Checksum(context.TODO(), ref, "d0/def/foo")
|
||||
dgst, err := Checksum(context.TODO(), ref, "d0/def/foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
dgst, err = Checksum(context.TODO(), ref, "d0/def/foo")
|
||||
dgst, err = Checksum(context.TODO(), ref, "d0/def/foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
|
@ -412,10 +526,10 @@ func TestSymlinkNeedsScan(t *testing.T) {
|
|||
ref := createRef(t, cm, ch)
|
||||
|
||||
// scan the d0 path containing the symlink that doesn't get followed
|
||||
_, err = Checksum(context.TODO(), ref, "d0/d1")
|
||||
_, err = Checksum(context.TODO(), ref, "d0/d1", true)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := Checksum(context.TODO(), ref, "d0/d1/def/foo")
|
||||
dgst, err := Checksum(context.TODO(), ref, "d0/d1/def/foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
|
@ -442,7 +556,7 @@ func TestSymlinkAbsDirSuffix(t *testing.T) {
|
|||
}
|
||||
ref := createRef(t, cm, ch)
|
||||
|
||||
dgst, err := Checksum(context.TODO(), ref, "link/foo")
|
||||
dgst, err := Checksum(context.TODO(), ref, "link/foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
|
@ -485,27 +599,27 @@ func TestSymlinkInPathHandleChange(t *testing.T) {
|
|||
err = emit(cc.HandleChange, changeStream(ch))
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d1/def/foo")
|
||||
dgst, err := cc.Checksum(context.TODO(), ref, "d1/def/foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d1/def/bar/abc")
|
||||
dgst, err = cc.Checksum(context.TODO(), ref, "d1/def/bar/abc", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
dgstFileData0, err := cc.Checksum(context.TODO(), ref, "sub/d0")
|
||||
dgstFileData0, err := cc.Checksum(context.TODO(), ref, "sub/d0", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgstDirD0)
|
||||
|
||||
dgstFileData0, err = cc.Checksum(context.TODO(), ref, "d1/def/baz")
|
||||
dgstFileData0, err = cc.Checksum(context.TODO(), ref, "d1/def/baz", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgstDirD0)
|
||||
|
||||
dgstFileData0, err = cc.Checksum(context.TODO(), ref, "d1/def/bay")
|
||||
dgstFileData0, err = cc.Checksum(context.TODO(), ref, "d1/def/bay", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgstDirD0)
|
||||
|
||||
dgstFileData0, err = cc.Checksum(context.TODO(), ref, "link")
|
||||
dgstFileData0, err = cc.Checksum(context.TODO(), ref, "link", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgstDirD0)
|
||||
|
||||
|
@ -536,7 +650,7 @@ func TestPersistence(t *testing.T) {
|
|||
ref := createRef(t, cm, ch)
|
||||
id := ref.ID()
|
||||
|
||||
dgst, err := Checksum(context.TODO(), ref, "foo")
|
||||
dgst, err := Checksum(context.TODO(), ref, "foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
|
@ -546,7 +660,7 @@ func TestPersistence(t *testing.T) {
|
|||
ref, err = cm.Get(context.TODO(), id)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = Checksum(context.TODO(), ref, "foo")
|
||||
dgst, err = Checksum(context.TODO(), ref, "foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
|
||||
|
@ -564,7 +678,7 @@ func TestPersistence(t *testing.T) {
|
|||
ref, err = cm.Get(context.TODO(), id)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst, err = Checksum(context.TODO(), ref, "foo")
|
||||
dgst, err = Checksum(context.TODO(), ref, "foo", true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, dgstFileData0, dgst)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func NewContentHashFunc(selectors []string) solver.ResultBasedCacheFunc {
|
|||
// FIXME(tonistiigi): enabling this parallelization seems to create wrong results for some big inputs(like gobuild)
|
||||
// func(i int) {
|
||||
// eg.Go(func() error {
|
||||
dgst, err := contenthash.Checksum(ctx, ref.ImmutableRef, path.Join("/", sel))
|
||||
dgst, err := contenthash.Checksum(ctx, ref.ImmutableRef, path.Join("/", sel), true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue