github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/internal/fileresolver/excluding_file.go (about) 1 package fileresolver 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/nextlinux/gosbom/gosbom/file" 8 ) 9 10 type excludeFn func(string) bool 11 12 // excluding decorates a resolver with an exclusion function that is used to 13 // filter out entries in the delegate resolver 14 type excluding struct { 15 delegate file.Resolver 16 excludeFn excludeFn 17 } 18 19 // NewExcluding create a new resolver which wraps the provided delegate and excludes 20 // entries based on a provided path exclusion function 21 func NewExcluding(delegate file.Resolver, excludeFn excludeFn) file.Resolver { 22 return &excluding{ 23 delegate, 24 excludeFn, 25 } 26 } 27 28 func (r *excluding) FileContentsByLocation(location file.Location) (io.ReadCloser, error) { 29 if locationMatches(&location, r.excludeFn) { 30 return nil, fmt.Errorf("no such location: %+v", location.RealPath) 31 } 32 return r.delegate.FileContentsByLocation(location) 33 } 34 35 func (r *excluding) FileMetadataByLocation(location file.Location) (file.Metadata, error) { 36 if locationMatches(&location, r.excludeFn) { 37 return file.Metadata{}, fmt.Errorf("no such location: %+v", location.RealPath) 38 } 39 return r.delegate.FileMetadataByLocation(location) 40 } 41 42 func (r *excluding) HasPath(path string) bool { 43 if r.excludeFn(path) { 44 return false 45 } 46 return r.delegate.HasPath(path) 47 } 48 49 func (r *excluding) FilesByPath(paths ...string) ([]file.Location, error) { 50 locations, err := r.delegate.FilesByPath(paths...) 51 return filterLocations(locations, err, r.excludeFn) 52 } 53 54 func (r *excluding) FilesByGlob(patterns ...string) ([]file.Location, error) { 55 locations, err := r.delegate.FilesByGlob(patterns...) 56 return filterLocations(locations, err, r.excludeFn) 57 } 58 59 func (r *excluding) FilesByMIMEType(types ...string) ([]file.Location, error) { 60 locations, err := r.delegate.FilesByMIMEType(types...) 61 return filterLocations(locations, err, r.excludeFn) 62 } 63 64 func (r *excluding) RelativeFileByPath(location file.Location, path string) *file.Location { 65 l := r.delegate.RelativeFileByPath(location, path) 66 if l != nil && locationMatches(l, r.excludeFn) { 67 return nil 68 } 69 return l 70 } 71 72 func (r *excluding) AllLocations() <-chan file.Location { 73 c := make(chan file.Location) 74 go func() { 75 defer close(c) 76 for location := range r.delegate.AllLocations() { 77 if !locationMatches(&location, r.excludeFn) { 78 c <- location 79 } 80 } 81 }() 82 return c 83 } 84 85 func locationMatches(location *file.Location, exclusionFn excludeFn) bool { 86 return exclusionFn(location.RealPath) || exclusionFn(location.VirtualPath) 87 } 88 89 func filterLocations(locations []file.Location, err error, exclusionFn excludeFn) ([]file.Location, error) { 90 if err != nil { 91 return nil, err 92 } 93 if exclusionFn != nil { 94 for i := 0; i < len(locations); i++ { 95 location := &locations[i] 96 if locationMatches(location, exclusionFn) { 97 locations = append(locations[:i], locations[i+1:]...) 98 i-- 99 } 100 } 101 } 102 return locations, nil 103 }