Skip to content

Commit

Permalink
add differ support for local source
Browse files Browse the repository at this point in the history
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
  • Loading branch information
tonistiigi committed Jun 12, 2021
1 parent 59d2f76 commit baa4fcd
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 3 deletions.
82 changes: 82 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"path/filepath"
"runtime"
"strings"
"syscall"
"testing"
"time"

Expand Down Expand Up @@ -126,6 +127,7 @@ func TestIntegration(t *testing.T) {
testStargzLazyPull,
testFileOpInputSwap,
testRelativeMountpoint,
testLocalSourceDiffer,
}, mirrors)

integration.Run(t, []integration.Test{
Expand Down Expand Up @@ -1269,6 +1271,86 @@ func testFileOpInputSwap(t *testing.T, sb integration.Sandbox) {
require.Contains(t, err.Error(), "bar: no such file")
}

func testLocalSourceDiffer(t *testing.T, sb integration.Sandbox) {
for _, d := range []llb.DiffType{llb.DiffNone, llb.DiffMetadata} {
t.Run(fmt.Sprintf("differ=%s", d), func(t *testing.T) {
testLocalSourceWithDiffer(t, sb, d)
})
}
}

func testLocalSourceWithDiffer(t *testing.T, sb integration.Sandbox, d llb.DiffType) {
requiresLinux(t)
c, err := New(context.TODO(), sb.Address())
require.NoError(t, err)
defer c.Close()

dir, err := tmpdir(
fstest.CreateFile("foo", []byte("foo"), 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)

tv := syscall.NsecToTimespec(time.Now().UnixNano())

err = syscall.UtimesNano(filepath.Join(dir, "foo"), []syscall.Timespec{tv, tv})
require.NoError(t, err)

st := llb.Local("mylocal"+string(d), llb.Differ(d, false))

def, err := st.Marshal(context.TODO())
require.NoError(t, err)

destDir, err := ioutil.TempDir("", "buildkit")
require.NoError(t, err)
defer os.RemoveAll(destDir)

_, err = c.Solve(context.TODO(), def, SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterLocal,
OutputDir: destDir,
},
},
LocalDirs: map[string]string{
"mylocal" + string(d): dir,
},
}, nil)
require.NoError(t, err)

dt, err := ioutil.ReadFile(filepath.Join(destDir, "foo"))
require.NoError(t, err)
require.Equal(t, []byte("foo"), dt)

err = ioutil.WriteFile(filepath.Join(dir, "foo"), []byte("bar"), 0600)
require.NoError(t, err)

err = syscall.UtimesNano(filepath.Join(dir, "foo"), []syscall.Timespec{tv, tv})
require.NoError(t, err)

_, err = c.Solve(context.TODO(), def, SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterLocal,
OutputDir: destDir,
},
},
LocalDirs: map[string]string{
"mylocal" + string(d): dir,
},
}, nil)
require.NoError(t, err)

dt, err = ioutil.ReadFile(filepath.Join(destDir, "foo"))
require.NoError(t, err)
if d == llb.DiffMetadata {
require.Equal(t, []byte("foo"), dt)
}
if d == llb.DiffNone {
require.Equal(t, []byte("bar"), dt)
}
}

func testFileOpRmWildcard(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
c, err := New(context.TODO(), sb.Address())
Expand Down
27 changes: 27 additions & 0 deletions client/llb/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,12 @@ func Local(name string, opts ...LocalOption) State {
attrs[pb.AttrSharedKeyHint] = gi.SharedKeyHint
addCap(&gi.Constraints, pb.CapSourceLocalSharedKeyHint)
}
if gi.Differ.Type != "" {
attrs[pb.AttrLocalDiffer] = string(gi.Differ.Type)
if gi.Differ.Required {
addCap(&gi.Constraints, pb.CapSourceLocalDiffer)
}
}

addCap(&gi.Constraints, pb.CapSourceLocal)

Expand Down Expand Up @@ -423,13 +429,34 @@ func SharedKeyHint(h string) LocalOption {
})
}

func Differ(t DiffType, required bool) LocalOption {
return localOptionFunc(func(li *LocalInfo) {
li.Differ = DifferInfo{
Type: t,
Required: required,
}
})
}

type DiffType string

const DiffNone DiffType = pb.AttrLocalDifferNone
const DiffMetadata DiffType = pb.AttrLocalDifferMetadata
const DiffContent DiffType = pb.AttrLocalDifferContent

type DifferInfo struct {
Type DiffType
Required bool
}

type LocalInfo struct {
constraintsWrapper
SessionID string
IncludePatterns string
ExcludePatterns string
FollowPaths string
SharedKeyHint string
Differ DifferInfo
}

func HTTP(url string, opts ...HTTPOption) State {
Expand Down
3 changes: 2 additions & 1 deletion session/filesync/diffcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (wc *streamWriterCloser) Close() error {
return nil
}

func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress progressCb, filter func(string, *fstypes.Stat) bool) (err error) {
func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress progressCb, differ fsutil.DiffType, filter func(string, *fstypes.Stat) bool) (err error) {
st := time.Now()
defer func() {
logrus.Debugf("diffcopy took: %v", time.Since(st))
Expand All @@ -93,6 +93,7 @@ func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress p
ContentHasher: ch,
ProgressCb: progress,
Filter: fsutil.FilterFunc(filter),
Differ: differ,
}))
}

Expand Down
6 changes: 4 additions & 2 deletions session/filesync/filesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
keyFollowPaths = "followpaths"
keyDirName = "dir-name"
keyExporterMetaPrefix = "exporter-md-"
keyDiffer = "differ"
)

type fsSyncProvider struct {
Expand Down Expand Up @@ -130,7 +131,7 @@ type progressCb func(int, bool)
type protocol struct {
name string
sendFn func(stream Stream, fs fsutil.FS, progress progressCb) error
recvFn func(stream grpc.ClientStream, destDir string, cu CacheUpdater, progress progressCb, mapFunc func(string, *fstypes.Stat) bool) error
recvFn func(stream grpc.ClientStream, destDir string, cu CacheUpdater, progress progressCb, differ fsutil.DiffType, mapFunc func(string, *fstypes.Stat) bool) error
}

func isProtoSupported(p string) bool {
Expand Down Expand Up @@ -160,6 +161,7 @@ type FSSendRequestOpt struct {
CacheUpdater CacheUpdater
ProgressCb func(int, bool)
Filter func(string, *fstypes.Stat) bool
Differ fsutil.DiffType
}

// CacheUpdater is an object capable of sending notifications for the cache hash changes
Expand Down Expand Up @@ -227,7 +229,7 @@ func FSSync(ctx context.Context, c session.Caller, opt FSSendRequestOpt) error {
panic(fmt.Sprintf("invalid protocol: %q", pr.name))
}

return pr.recvFn(stream, opt.DestDir, opt.CacheUpdater, opt.ProgressCb, opt.Filter)
return pr.recvFn(stream, opt.DestDir, opt.CacheUpdater, opt.ProgressCb, opt.Differ, opt.Filter)
}

// NewFSSyncTargetDir allows writing into a directory
Expand Down
6 changes: 6 additions & 0 deletions solver/pb/attr.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const AttrIncludePatterns = "local.includepattern"
const AttrFollowPaths = "local.followpaths"
const AttrExcludePatterns = "local.excludepatterns"
const AttrSharedKeyHint = "local.sharedkeyhint"

const AttrLLBDefinitionFilename = "llbbuild.filename"

const AttrHTTPChecksum = "http.checksum"
Expand All @@ -26,4 +27,9 @@ const AttrImageResolveModeForcePull = "pull"
const AttrImageResolveModePreferLocal = "local"
const AttrImageRecordType = "image.recordtype"

const AttrLocalDiffer = "local.differ"
const AttrLocalDifferNone = "none"
const AttrLocalDifferMetadata = "metadata"
const AttrLocalDifferContent = "content"

type IsFileAction = isFileAction_Action
8 changes: 8 additions & 0 deletions solver/pb/caps.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
CapSourceLocalFollowPaths apicaps.CapID = "source.local.followpaths"
CapSourceLocalExcludePatterns apicaps.CapID = "source.local.excludepatterns"
CapSourceLocalSharedKeyHint apicaps.CapID = "source.local.sharedkeyhint"
CapSourceLocalDiffer apicaps.CapID = "source.local.differ"

CapSourceGit apicaps.CapID = "source.git"
CapSourceGitKeepDir apicaps.CapID = "source.git.keepgitdir"
Expand Down Expand Up @@ -118,6 +119,13 @@ func init() {
Enabled: true,
Status: apicaps.CapStatusExperimental,
})

Caps.Init(apicaps.Cap{
ID: CapSourceLocalDiffer,
Enabled: true,
Status: apicaps.CapStatusExperimental,
})

Caps.Init(apicaps.Cap{
ID: CapSourceGit,
Enabled: true,
Expand Down
11 changes: 11 additions & 0 deletions source/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/tonistiigi/fsutil"
)

var (
Expand Down Expand Up @@ -146,6 +147,15 @@ func FromLLB(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) {
id.FollowPaths = paths
case pb.AttrSharedKeyHint:
id.SharedKeyHint = v
case pb.AttrLocalDiffer:
switch v {
case pb.AttrLocalDifferMetadata, "":
id.Differ = fsutil.DiffMetadata
case pb.AttrLocalDifferNone:
id.Differ = fsutil.DiffNone
case pb.AttrLocalDifferContent:
id.Differ = fsutil.DiffContent
}
}
}
}
Expand Down Expand Up @@ -214,6 +224,7 @@ type LocalIdentifier struct {
ExcludePatterns []string
FollowPaths []string
SharedKeyHint string
Differ fsutil.DiffType
}

func NewLocalIdentifier(str string) (*LocalIdentifier, error) {
Expand Down
1 change: 1 addition & 0 deletions source/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func (ls *localSourceHandler) snapshot(ctx context.Context, s session.Group, cal
DestDir: dest,
CacheUpdater: &cacheUpdater{cc, mount.IdentityMapping()},
ProgressCb: newProgressHandler(ctx, "transferring "+ls.src.Name+":"),
Differ: ls.src.Differ,
}

if idmap := mount.IdentityMapping(); idmap != nil {
Expand Down

0 comments on commit baa4fcd

Please sign in to comment.