@@ -35,7 +35,8 @@ import (
3535
3636type 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
406414func 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+ }
0 commit comments