From 1814a0163a109974c3187ca5c41e8db5f2b78f4f Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 1 Mar 2019 17:17:43 -0800 Subject: [PATCH 1/2] contenthash: add wildcard support Signed-off-by: Tonis Tiigi --- cache/contenthash/checksum.go | 141 ++++++++++++++++++++++++++--- cache/contenthash/checksum_test.go | 55 +++++++++++ 2 files changed, 185 insertions(+), 11 deletions(-) diff --git a/cache/contenthash/checksum.go b/cache/contenthash/checksum.go index 8cb03359..c490d89c 100644 --- a/cache/contenthash/checksum.go +++ b/cache/contenthash/checksum.go @@ -64,6 +64,11 @@ type Hashed interface { Digest() digest.Digest } +type Wildcard struct { + Path string + Record *CacheRecord +} + type cacheManager struct { locker *locker.Locker lru *simplelru.LRU @@ -317,10 +322,48 @@ 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) + if err == nil { + 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) +} + +func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string) (digest.Digest, error) { const maxSymlinkLimit = 255 i := 0 for { @@ -344,6 +387,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 +531,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 +540,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 +566,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 +718,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 +751,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 diff --git a/cache/contenthash/checksum_test.go b/cache/contenthash/checksum_test.go index 034e7469..960a0f4f 100644 --- a/cache/contenthash/checksum_test.go +++ b/cache/contenthash/checksum_test.go @@ -29,6 +29,61 @@ 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 TestChecksumBasicFile(t *testing.T) { t.Parallel() tmpdir, err := ioutil.TempDir("", "buildkit-state") From 8bcd59a546d4567a559095f47e5f6e23a41440b7 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 1 Mar 2019 17:37:27 -0800 Subject: [PATCH 2/2] contenthash: add nofollow support Signed-off-by: Tonis Tiigi --- cache/contenthash/checksum.go | 24 ++--- cache/contenthash/checksum_test.go | 135 +++++++++++++++++++++-------- solver/llbsolver/result.go | 2 +- 3 files changed, 111 insertions(+), 50 deletions(-) diff --git a/cache/contenthash/checksum.go b/cache/contenthash/checksum.go index c490d89c..ef129cc7 100644 --- a/cache/contenthash/checksum.go +++ b/cache/contenthash/checksum.go @@ -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 } @@ -75,12 +76,12 @@ type cacheManager struct { 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) { @@ -334,10 +335,11 @@ func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mo if followLinks { for i, w := range wildcards { if w.Record.Type == CacheRecordTypeSymlink { - dgst, err := cc.checksumFollow(ctx, m, w.Path) - if err == nil { - wildcards[i].Record = &CacheRecord{Digest: dgst} + dgst, err := cc.checksumFollow(ctx, m, w.Path, followLinks) + if err != nil { + return "", err } + wildcards[i].Record = &CacheRecord{Digest: dgst} } } } @@ -360,10 +362,10 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, m := &mount{mountable: mountable} defer m.clean() - return cc.checksumFollow(ctx, m, p) + return cc.checksumFollow(ctx, m, p, followLinks) } -func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string) (digest.Digest, error) { +func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string, follow bool) (digest.Digest, error) { const maxSymlinkLimit = 255 i := 0 for { @@ -374,7 +376,7 @@ func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string) 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) diff --git a/cache/contenthash/checksum_test.go b/cache/contenthash/checksum_test.go index 960a0f4f..05d4f868 100644 --- a/cache/contenthash/checksum_test.go +++ b/cache/contenthash/checksum_test.go @@ -84,6 +84,65 @@ func TestChecksumWildcard(t *testing.T) { 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") @@ -112,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) @@ -173,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) @@ -192,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) @@ -218,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) @@ -265,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) @@ -289,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) @@ -300,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)) @@ -341,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{ @@ -353,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) } @@ -388,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")) @@ -408,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) @@ -433,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) @@ -467,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) @@ -497,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) @@ -540,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) @@ -591,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) @@ -601,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) @@ -619,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) } diff --git a/solver/llbsolver/result.go b/solver/llbsolver/result.go index cd1959c0..19431fe0 100644 --- a/solver/llbsolver/result.go +++ b/solver/llbsolver/result.go @@ -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 }