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:
William Murphy
2024-01-22 11:05:59 -05:00
committed by GitHub
parent 3046d43a8a
commit c6ce1de928
22 changed files with 156 additions and 42 deletions
@@ -1,6 +1,8 @@
package fileresolver
import (
"context"
"errors"
"fmt"
"io"
"io/fs"
@@ -225,8 +227,9 @@ func (u UnindexedDirectory) RelativeFileByPath(l file.Location, p string) *file.
// - NO symlink resolution should be performed on results
// - returns locations for any file or directory
func (u UnindexedDirectory) AllLocations() <-chan file.Location {
func (u UnindexedDirectory) AllLocations(ctx context.Context) <-chan file.Location {
out := make(chan file.Location)
errWalkCanceled := fmt.Errorf("walk canceled")
go func() {
defer close(out)
err := afero.Walk(u.fs, u.absPath("."), func(p string, info fs.FileInfo, err error) error {
@@ -235,10 +238,14 @@ func (u UnindexedDirectory) AllLocations() <-chan file.Location {
return nil
}
p = strings.TrimPrefix(p, "/")
out <- file.NewLocation(p)
return nil
select {
case out <- file.NewLocation(p):
return nil
case <-ctx.Done():
return errWalkCanceled
}
})
if err != nil {
if err != nil && !errors.Is(err, errWalkCanceled) {
log.Debug(err)
}
}()