mirror of
https://github.com/anchore/syft.git
synced 2026-11-03 16:06:36 +01:00
make AllLocations accept a context (#2518)
The previous implementation would leak a goroutine if the caller of AllLocations stopped iterating early. Now, accept a context so that the caller can cancel the AllLocations iterator rather than leak the goroutine. Signed-off-by: Will Murphy <will.murphy@anchore.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package filemetadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
@@ -21,8 +22,10 @@ func NewCataloger() *Cataloger {
|
||||
func (i *Cataloger) Catalog(resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates]file.Metadata, error) {
|
||||
results := make(map[file.Coordinates]file.Metadata)
|
||||
var locations <-chan file.Location
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
defer cancel()
|
||||
if len(coordinates) == 0 {
|
||||
locations = resolver.AllLocations()
|
||||
locations = resolver.AllLocations(ctx)
|
||||
} else {
|
||||
locations = func() <-chan file.Location {
|
||||
ch := make(chan file.Location)
|
||||
@@ -35,7 +38,12 @@ func (i *Cataloger) Catalog(resolver file.Resolver, coordinates ...file.Coordina
|
||||
continue
|
||||
}
|
||||
for _, loc := range locs {
|
||||
ch <- loc
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ch <- loc:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
func AllRegularFiles(resolver file.Resolver) (locations []file.Location) {
|
||||
for location := range resolver.AllLocations() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
for location := range resolver.AllLocations(ctx) {
|
||||
resolvedLocations, err := resolver.FilesByPath(location.RealPath)
|
||||
if err != nil {
|
||||
log.Warnf("unable to resolve %+v: %+v", location, err)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -144,12 +145,17 @@ func (r MockResolver) RelativeFileByPath(_ Location, path string) *Location {
|
||||
return &paths[0]
|
||||
}
|
||||
|
||||
func (r MockResolver) AllLocations() <-chan Location {
|
||||
func (r MockResolver) AllLocations(ctx context.Context) <-chan Location {
|
||||
results := make(chan Location)
|
||||
go func() {
|
||||
defer close(results)
|
||||
for _, l := range r.locations {
|
||||
results <- l
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case results <- l:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}()
|
||||
return results
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package file
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Resolver is an interface that encompasses how to get specific file references and file contents for a generic data source.
|
||||
type Resolver interface {
|
||||
@@ -53,7 +56,7 @@ type LocationResolver interface {
|
||||
// The implementation for this may vary, however, generally the following considerations should be made:
|
||||
// - NO symlink resolution should be performed on results
|
||||
// - returns locations for any file or directory
|
||||
AllLocations() <-chan Location
|
||||
AllLocations(ctx context.Context) <-chan Location
|
||||
}
|
||||
|
||||
type WritableResolver interface {
|
||||
|
||||
Reference in New Issue
Block a user