Skip to content

Commit c62e704

Browse files
authored
Merge pull request moby#4094 from jedevc/fsutil-fs-in-opt
client: modify SolveOpt to take fsutil.FS objects
2 parents d5c1d78 + 0f343f9 commit c62e704

18 files changed

Lines changed: 515 additions & 201 deletions

File tree

cache/util/fsutil.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,17 @@ type ReadDirRequest struct {
9090
func ReadDir(ctx context.Context, mount snapshot.Mountable, req ReadDirRequest) ([]*fstypes.Stat, error) {
9191
var (
9292
rd []*fstypes.Stat
93-
wo fsutil.WalkOpt
93+
fo fsutil.FilterOpt
9494
)
9595
if req.IncludePattern != "" {
96-
wo.IncludePatterns = append(wo.IncludePatterns, req.IncludePattern)
96+
fo.IncludePatterns = append(fo.IncludePatterns, req.IncludePattern)
9797
}
9898
err := withMount(ctx, mount, func(root string) error {
9999
fp, err := fs.RootPath(root, req.Path)
100100
if err != nil {
101101
return errors.WithStack(err)
102102
}
103-
return fsutil.Walk(ctx, fp, &wo, func(path string, info os.FileInfo, err error) error {
103+
return fsutil.Walk(ctx, fp, &fo, func(path string, info os.FileInfo, err error) error {
104104
if err != nil {
105105
return errors.Wrapf(err, "walking %q", root)
106106
}

client/solve.go

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ import (
3535

3636
type SolveOpt struct {
3737
Exports []ExportEntry
38-
LocalDirs map[string]string
38+
LocalDirs map[string]string // Deprecated: use LocalMounts
39+
LocalMounts map[string]fsutil.FS
3940
OCIStores map[string]content.Store
4041
SharedKey string
4142
Frontend string
@@ -90,7 +91,11 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
9091
return nil, errors.New("invalid with def and cb")
9192
}
9293

93-
syncedDirs, err := prepareSyncedDirs(def, opt.LocalDirs)
94+
mounts, err := prepareMounts(&opt)
95+
if err != nil {
96+
return nil, err
97+
}
98+
syncedDirs, err := prepareSyncedFiles(def, mounts)
9499
if err != nil {
95100
return nil, err
96101
}
@@ -361,26 +366,23 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
361366
return res, nil
362367
}
363368

364-
func prepareSyncedDirs(def *llb.Definition, localDirs map[string]string) (filesync.StaticDirSource, error) {
365-
for _, d := range localDirs {
366-
fi, err := os.Stat(d)
367-
if err != nil {
368-
return nil, errors.Wrapf(err, "could not find %s", d)
369-
}
370-
if !fi.IsDir() {
371-
return nil, errors.Errorf("%s not a directory", d)
372-
}
373-
}
369+
func prepareSyncedFiles(def *llb.Definition, localMounts map[string]fsutil.FS) (filesync.StaticDirSource, error) {
374370
resetUIDAndGID := func(p string, st *fstypes.Stat) fsutil.MapResult {
375371
st.Uid = 0
376372
st.Gid = 0
377373
return fsutil.MapResultKeep
378374
}
379375

380-
dirs := make(filesync.StaticDirSource, len(localDirs))
376+
result := make(filesync.StaticDirSource, len(localMounts))
381377
if def == nil {
382-
for name, d := range localDirs {
383-
dirs[name] = filesync.SyncedDir{Dir: d, Map: resetUIDAndGID}
378+
for name, mount := range localMounts {
379+
mount, err := fsutil.NewFilterFS(mount, &fsutil.FilterOpt{
380+
Map: resetUIDAndGID,
381+
})
382+
if err != nil {
383+
return nil, err
384+
}
385+
result[name] = mount
384386
}
385387
} else {
386388
for _, dt := range def.Def {
@@ -391,16 +393,22 @@ func prepareSyncedDirs(def *llb.Definition, localDirs map[string]string) (filesy
391393
if src := op.GetSource(); src != nil {
392394
if strings.HasPrefix(src.Identifier, "local://") {
393395
name := strings.TrimPrefix(src.Identifier, "local://")
394-
d, ok := localDirs[name]
396+
mount, ok := localMounts[name]
395397
if !ok {
396398
return nil, errors.Errorf("local directory %s not enabled", name)
397399
}
398-
dirs[name] = filesync.SyncedDir{Dir: d, Map: resetUIDAndGID}
400+
mount, err := fsutil.NewFilterFS(mount, &fsutil.FilterOpt{
401+
Map: resetUIDAndGID,
402+
})
403+
if err != nil {
404+
return nil, err
405+
}
406+
result[name] = mount
399407
}
400408
}
401409
}
402410
}
403-
return dirs, nil
411+
return result, nil
404412
}
405413

406414
func defaultSessionName() string {
@@ -523,3 +531,22 @@ func parseCacheOptions(ctx context.Context, isGateway bool, opt SolveOpt) (*cach
523531
}
524532
return &res, nil
525533
}
534+
535+
func prepareMounts(opt *SolveOpt) (map[string]fsutil.FS, error) {
536+
// merge local mounts and fallback local directories together
537+
mounts := make(map[string]fsutil.FS)
538+
for k, mount := range opt.LocalMounts {
539+
mounts[k] = mount
540+
}
541+
for k, dir := range opt.LocalDirs {
542+
mount, err := fsutil.NewFS(dir)
543+
if err != nil {
544+
return nil, err
545+
}
546+
if _, ok := mounts[k]; ok {
547+
return nil, errors.Errorf("local mount %s already exists", k)
548+
}
549+
mounts[k] = mount
550+
}
551+
return mounts, nil
552+
}

exporter/local/export.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ func (e *localExporterInstance) Export(ctx context.Context, inp *exporter.Source
108108

109109
if !e.opts.PlatformSplit {
110110
// check for duplicate paths
111-
err = outputFS.Walk(ctx, func(p string, fi os.FileInfo, err error) error {
112-
if fi.IsDir() {
111+
err = outputFS.Walk(ctx, "", func(p string, entry os.DirEntry, err error) error {
112+
if entry.IsDir() {
113113
return nil
114114
}
115115
if err != nil && !errors.Is(err, os.ErrNotExist) {

exporter/local/fs.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,14 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
9898
cleanup = lm.Unmount
9999
}
100100

101-
walkOpt := &fsutil.WalkOpt{}
102-
var idMapFunc func(p string, st *fstypes.Stat) fsutil.MapResult
101+
outputFS, err := fsutil.NewFS(src)
102+
if err != nil {
103+
return nil, nil, err
104+
}
103105

106+
// wrap the output filesystem, applying appropriate filters
107+
filterOpt := &fsutil.FilterOpt{}
108+
var idMapFunc func(p string, st *fstypes.Stat) fsutil.MapResult
104109
if idmap != nil {
105110
idMapFunc = func(p string, st *fstypes.Stat) fsutil.MapResult {
106111
uid, gid, err := idmap.ToContainer(idtools.Identity{
@@ -115,19 +120,23 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
115120
return fsutil.MapResultKeep
116121
}
117122
}
118-
119-
walkOpt.Map = func(p string, st *fstypes.Stat) fsutil.MapResult {
123+
filterOpt.Map = func(p string, st *fstypes.Stat) fsutil.MapResult {
120124
res := fsutil.MapResultKeep
121125
if idMapFunc != nil {
126+
// apply host uid/gid
122127
res = idMapFunc(p, st)
123128
}
124129
if opt.Epoch != nil {
130+
// apply used-specified epoch time
125131
st.ModTime = opt.Epoch.UnixNano()
126132
}
127133
return res
128134
}
135+
outputFS, err = fsutil.NewFilterFS(outputFS, filterOpt)
136+
if err != nil {
137+
return nil, nil, err
138+
}
129139

130-
outputFS := fsutil.NewFS(src, walkOpt)
131140
attestations = attestation.Filter(attestations, nil, map[string][]byte{
132141
result.AttestationInlineOnlyKey: []byte(strconv.FormatBool(true)),
133142
})
@@ -137,11 +146,11 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
137146
}
138147
if len(attestations) > 0 {
139148
subjects := []intoto.Subject{}
140-
err = outputFS.Walk(ctx, func(path string, info fs.FileInfo, err error) error {
149+
err = outputFS.Walk(ctx, "", func(path string, entry fs.DirEntry, err error) error {
141150
if err != nil {
142151
return err
143152
}
144-
if !info.Mode().IsRegular() {
153+
if !entry.Type().IsRegular() {
145154
return nil
146155
}
147156
f, err := outputFS.Open(path)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ require (
6464
github.com/sirupsen/logrus v1.9.3
6565
github.com/spdx/tools-golang v0.5.1
6666
github.com/stretchr/testify v1.8.4
67-
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb
67+
github.com/tonistiigi/fsutil v0.0.0-20230825212630-f09800878302
6868
github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7
6969
github.com/tonistiigi/go-archvariant v1.0.0
7070
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,8 +1206,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
12061206
github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
12071207
github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
12081208
github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85/go.mod h1:a7cilN64dG941IOXfhJhlH0qB92hxJ9A1ewrdUmJ6xo=
1209-
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb h1:uUe8rNyVXM8moActoBol6Xf6xX2GMr7SosR2EywMvGg=
1210-
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb/go.mod h1:SxX/oNQ/ag6Vaoli547ipFK9J7BZn5JqJG0JE8lf8bA=
1209+
github.com/tonistiigi/fsutil v0.0.0-20230825212630-f09800878302 h1:ZT8ibgassurSISJ1Pj26NsM3vY2jxFZn63Nd/TpHmRw=
1210+
github.com/tonistiigi/fsutil v0.0.0-20230825212630-f09800878302/go.mod h1:9kMVqMyQ/Sx2df5LtnGG+nbrmiZzCS7V6gjW3oGHsvI=
12111211
github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7 h1:8eY6m1mjgyB8XySUR7WvebTM8D/Vs86jLJzD/Tw7zkc=
12121212
github.com/tonistiigi/go-actions-cache v0.0.0-20220404170428-0bdeb6e1eac7/go.mod h1:qqvyZqkfwkoJuPU/bw61bItaoO0SJ8YSW0vSVRRvsRg=
12131213
github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0=

session/filesync/filesync.go

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,15 @@ type fsSyncProvider struct {
3535
doneCh chan error
3636
}
3737

38-
type SyncedDir struct {
39-
Dir string
40-
Map func(string, *fstypes.Stat) fsutil.MapResult
41-
}
42-
4338
type DirSource interface {
44-
LookupDir(string) (SyncedDir, bool)
39+
LookupDir(string) (fsutil.FS, bool)
4540
}
4641

47-
type StaticDirSource map[string]SyncedDir
42+
type StaticDirSource map[string]fsutil.FS
4843

4944
var _ DirSource = StaticDirSource{}
5045

51-
func (dirs StaticDirSource) LookupDir(name string) (SyncedDir, bool) {
46+
func (dirs StaticDirSource) LookupDir(name string) (fsutil.FS, bool) {
5247
dir, found := dirs[name]
5348
return dir, found
5449
}
@@ -92,15 +87,22 @@ func (sp *fsSyncProvider) handle(method string, stream grpc.ServerStream) (retEr
9287
dirName = name[0]
9388
}
9489

90+
excludes := opts[keyExcludePatterns]
91+
includes := opts[keyIncludePatterns]
92+
followPaths := opts[keyFollowPaths]
93+
9594
dir, ok := sp.dirs.LookupDir(dirName)
9695
if !ok {
9796
return InvalidSessionError{status.Errorf(codes.NotFound, "no access allowed to dir %q", dirName)}
9897
}
99-
100-
excludes := opts[keyExcludePatterns]
101-
includes := opts[keyIncludePatterns]
102-
103-
followPaths := opts[keyFollowPaths]
98+
dir, err := fsutil.NewFilterFS(dir, &fsutil.FilterOpt{
99+
ExcludePatterns: excludes,
100+
IncludePatterns: includes,
101+
FollowPaths: followPaths,
102+
})
103+
if err != nil {
104+
return err
105+
}
104106

105107
var progress progressCb
106108
if sp.p != nil {
@@ -113,12 +115,7 @@ func (sp *fsSyncProvider) handle(method string, stream grpc.ServerStream) (retEr
113115
doneCh = sp.doneCh
114116
sp.doneCh = nil
115117
}
116-
err := pr.sendFn(stream, fsutil.NewFS(dir.Dir, &fsutil.WalkOpt{
117-
ExcludePatterns: excludes,
118-
IncludePatterns: includes,
119-
FollowPaths: followPaths,
120-
Map: dir.Map,
121-
}), progress)
118+
err = pr.sendFn(stream, dir, progress)
122119
if doneCh != nil {
123120
if err != nil {
124121
doneCh <- err

session/filesync/filesync_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/moby/buildkit/session/testutil"
1111
"github.com/stretchr/testify/assert"
1212
"github.com/stretchr/testify/require"
13+
"github.com/tonistiigi/fsutil"
1314
"golang.org/x/sync/errgroup"
1415
)
1516

@@ -18,9 +19,11 @@ func TestFileSyncIncludePatterns(t *testing.T) {
1819
t.Parallel()
1920

2021
tmpDir := t.TempDir()
22+
tmpFS, err := fsutil.NewFS(tmpDir)
23+
require.NoError(t, err)
2124
destDir := t.TempDir()
2225

23-
err := os.WriteFile(filepath.Join(tmpDir, "foo"), []byte("content1"), 0600)
26+
err = os.WriteFile(filepath.Join(tmpDir, "foo"), []byte("content1"), 0600)
2427
require.NoError(t, err)
2528

2629
err = os.WriteFile(filepath.Join(tmpDir, "bar"), []byte("content2"), 0600)
@@ -32,7 +35,7 @@ func TestFileSyncIncludePatterns(t *testing.T) {
3235
m, err := session.NewManager()
3336
require.NoError(t, err)
3437

35-
fs := NewFSSyncProvider(StaticDirSource{"test0": {Dir: tmpDir}})
38+
fs := NewFSSyncProvider(StaticDirSource{"test0": tmpFS})
3639
s.Allow(fs)
3740

3841
dialer := session.Dialer(testutil.TestStream(testutil.Handler(m.HandleConn)))

util/staticfs/merge.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"io"
66
"io/fs"
77
"os"
8-
"path/filepath"
98

109
"github.com/tonistiigi/fsutil"
1110
"golang.org/x/sync/errgroup"
@@ -26,9 +25,9 @@ func NewMergeFS(lower, upper fsutil.FS) *MergeFS {
2625
}
2726

2827
type record struct {
29-
path string
30-
fi fs.FileInfo
31-
err error
28+
path string
29+
entry fs.DirEntry
30+
err error
3231
}
3332

3433
func (r *record) key() string {
@@ -38,26 +37,26 @@ func (r *record) key() string {
3837
return convertPathToKey(r.path)
3938
}
4039

41-
func (mfs *MergeFS) Walk(ctx context.Context, fn filepath.WalkFunc) error {
40+
func (mfs *MergeFS) Walk(ctx context.Context, target string, fn fs.WalkDirFunc) error {
4241
ch1 := make(chan *record, 10)
4342
ch2 := make(chan *record, 10)
4443

4544
eg, ctx := errgroup.WithContext(ctx)
4645
eg.Go(func() error {
4746
defer close(ch1)
48-
return mfs.Lower.Walk(ctx, func(path string, info fs.FileInfo, err error) error {
47+
return mfs.Lower.Walk(ctx, target, func(path string, entry fs.DirEntry, err error) error {
4948
select {
50-
case ch1 <- &record{path: path, fi: info, err: err}:
49+
case ch1 <- &record{path: path, entry: entry, err: err}:
5150
case <-ctx.Done():
5251
}
5352
return ctx.Err()
5453
})
5554
})
5655
eg.Go(func() error {
5756
defer close(ch2)
58-
return mfs.Upper.Walk(ctx, func(path string, info fs.FileInfo, err error) error {
57+
return mfs.Upper.Walk(ctx, target, func(path string, entry fs.DirEntry, err error) error {
5958
select {
60-
case ch2 <- &record{path: path, fi: info, err: err}:
59+
case ch2 <- &record{path: path, entry: entry, err: err}:
6160
case <-ctx.Done():
6261
}
6362
return ctx.Err()
@@ -75,13 +74,13 @@ func (mfs *MergeFS) Walk(ctx context.Context, fn filepath.WalkFunc) error {
7574
break
7675
}
7776
if !ok2 || ok1 && key1 < key2 {
78-
if err := fn(next1.path, next1.fi, next1.err); err != nil {
77+
if err := fn(next1.path, next1.entry, next1.err); err != nil {
7978
return err
8079
}
8180
next1, ok1 = <-ch1
8281
key1 = next1.key()
8382
} else if !ok1 || ok2 && key1 >= key2 {
84-
if err := fn(next2.path, next2.fi, next2.err); err != nil {
83+
if err := fn(next2.path, next2.entry, next2.err); err != nil {
8584
return err
8685
}
8786
if ok1 && key1 == key2 {

0 commit comments

Comments
 (0)