@@ -8,6 +8,7 @@ package loader
88import (
99 "bytes"
1010 "fmt"
11+ "io/fs"
1112 "io/ioutil"
1213 "os"
1314 "path/filepath"
@@ -79,7 +80,7 @@ type Filter = filter.LoaderFilter
7980// GlobExcludeName excludes files and directories whose names do not match the
8081// shell style pattern at minDepth or greater.
8182func GlobExcludeName (pattern string , minDepth int ) Filter {
82- return func (abspath string , info os .FileInfo , depth int ) bool {
83+ return func (abspath string , info fs .FileInfo , depth int ) bool {
8384 match , _ := filepath .Match (pattern , info .Name ())
8485 return match && depth >= minDepth
8586 }
@@ -91,6 +92,7 @@ type FileLoader interface {
9192 All (paths []string ) (* Result , error )
9293 Filtered (paths []string , filter Filter ) (* Result , error )
9394 AsBundle (path string ) (* bundle.Bundle , error )
95+ WithFS (fsys fs.FS ) FileLoader
9496 WithMetrics (m metrics.Metrics ) FileLoader
9597 WithFilter (filter Filter ) FileLoader
9698 WithBundleVerificationConfig (* bundle.VerificationConfig ) FileLoader
@@ -113,6 +115,15 @@ type fileLoader struct {
113115 skipVerify bool
114116 files map [string ]bundle.FileInfo
115117 opts ast.ParserOptions
118+ fsys fs.FS
119+ }
120+
121+ // WithFS provides an fs.FS to use for loading files. You can pass nil to
122+ // use plain IO calls (e.g. os.Open, os.Stat, etc.), this is the default
123+ // behaviour.
124+ func (fl * fileLoader ) WithFS (fsys fs.FS ) FileLoader {
125+ fl .fsys = fsys
126+ return fl
116127}
117128
118129// WithMetrics provides the metrics instance to use while loading
@@ -154,9 +165,17 @@ func (fl fileLoader) All(paths []string) (*Result, error) {
154165// paths while applying the given filters. If any filter returns true, the
155166// file/directory is excluded.
156167func (fl fileLoader ) Filtered (paths []string , filter Filter ) (* Result , error ) {
157- return all (paths , filter , func (curr * Result , path string , depth int ) error {
158-
159- bs , err := ioutil .ReadFile (path )
168+ return all (fl .fsys , paths , filter , func (curr * Result , path string , depth int ) error {
169+
170+ var (
171+ bs []byte
172+ err error
173+ )
174+ if fl .fsys != nil {
175+ bs , err = fs .ReadFile (fl .fsys , path )
176+ } else {
177+ bs , err = ioutil .ReadFile (path )
178+ }
160179 if err != nil {
161180 return err
162181 }
@@ -266,13 +285,19 @@ func GetBundleDirectoryLoaderWithFilter(path string, filter Filter) (bundle.Dire
266285 return bundleLoader , fi .IsDir (), nil
267286}
268287
269- // FilteredPaths return a list of files from the specified
288+ // FilteredPaths is the same as FilterPathsFS using the current diretory file
289+ // system
290+ func FilteredPaths (paths []string , filter Filter ) ([]string , error ) {
291+ return FilteredPathsFS (nil , paths , filter )
292+ }
293+
294+ // FilteredPathsFS return a list of files from the specified
270295// paths while applying the given filters. If any filter returns true, the
271296// file/directory is excluded.
272- func FilteredPaths ( paths []string , filter Filter ) ([]string , error ) {
297+ func FilteredPathsFS ( fsys fs. FS , paths []string , filter Filter ) ([]string , error ) {
273298 result := []string {}
274299
275- _ , err := all (paths , filter , func (_ * Result , path string , _ int ) error {
300+ _ , err := all (fsys , paths , filter , func (_ * Result , path string , _ int ) error {
276301 result = append (result , path )
277302 return nil
278303 })
@@ -549,7 +574,7 @@ func newResult() *Result {
549574 }
550575}
551576
552- func all (paths []string , filter Filter , f func (* Result , string , int ) error ) (* Result , error ) {
577+ func all (fsys fs. FS , paths []string , filter Filter , f func (* Result , string , int ) error ) (* Result , error ) {
553578 errs := Errors {}
554579 root := newResult ()
555580
@@ -566,7 +591,7 @@ func all(paths []string, filter Filter, f func(*Result, string, int) error) (*Re
566591 }
567592 }
568593
569- allRec (path , filter , & errs , loaded , 0 , f )
594+ allRec (fsys , path , filter , & errs , loaded , 0 , f )
570595 }
571596
572597 if len (errs ) > 0 {
@@ -576,15 +601,20 @@ func all(paths []string, filter Filter, f func(*Result, string, int) error) (*Re
576601 return root , nil
577602}
578603
579- func allRec (path string , filter Filter , errors * Errors , loaded * Result , depth int , f func (* Result , string , int ) error ) {
604+ func allRec (fsys fs. FS , path string , filter Filter , errors * Errors , loaded * Result , depth int , f func (* Result , string , int ) error ) {
580605
581606 path , err := fileurl .Clean (path )
582607 if err != nil {
583608 errors .add (err )
584609 return
585610 }
586611
587- info , err := os .Stat (path )
612+ var info fs.FileInfo
613+ if fsys != nil {
614+ info , err = fs .Stat (fsys , path )
615+ } else {
616+ info , err = os .Stat (path )
617+ }
588618 if err != nil {
589619 errors .add (err )
590620 return
@@ -607,14 +637,19 @@ func allRec(path string, filter Filter, errors *Errors, loaded *Result, depth in
607637 loaded = loaded .withParent (info .Name ())
608638 }
609639
610- files , err := ioutil .ReadDir (path )
640+ var files []fs.DirEntry
641+ if fsys != nil {
642+ files , err = fs .ReadDir (fsys , path )
643+ } else {
644+ files , err = os .ReadDir (path )
645+ }
611646 if err != nil {
612647 errors .add (err )
613648 return
614649 }
615650
616651 for _ , file := range files {
617- allRec (filepath .Join (path , file .Name ()), filter , errors , loaded , depth + 1 , f )
652+ allRec (fsys , filepath .Join (path , file .Name ()), filter , errors , loaded , depth + 1 , f )
618653 }
619654}
620655
0 commit comments