github.com/anchore/syft@v1.38.2/syft/file/cataloger/filemetadata/cataloger.go (about)

     1  package filemetadata
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/dustin/go-humanize"
     8  
     9  	"github.com/anchore/syft/internal/bus"
    10  	"github.com/anchore/syft/internal/log"
    11  	"github.com/anchore/syft/internal/unknown"
    12  	"github.com/anchore/syft/syft/event/monitor"
    13  	"github.com/anchore/syft/syft/file"
    14  )
    15  
    16  type Cataloger struct {
    17  }
    18  
    19  func NewCataloger() *Cataloger {
    20  	return &Cataloger{}
    21  }
    22  
    23  func (i *Cataloger) Catalog(ctx context.Context, resolver file.Resolver, coordinates ...file.Coordinates) (map[file.Coordinates]file.Metadata, error) {
    24  	var errs error
    25  	results := make(map[file.Coordinates]file.Metadata)
    26  	var locations <-chan file.Location
    27  	ctx, cancel := context.WithCancel(ctx)
    28  	defer cancel()
    29  	if len(coordinates) == 0 {
    30  		locations = resolver.AllLocations(ctx)
    31  	} else {
    32  		locations = func() <-chan file.Location {
    33  			ch := make(chan file.Location)
    34  			go func() {
    35  				defer close(ch)
    36  				for _, c := range coordinates {
    37  					locs, err := resolver.FilesByPath(c.RealPath)
    38  					if err != nil {
    39  						errs = unknown.Append(errs, c, err)
    40  						continue
    41  					}
    42  					for _, loc := range locs {
    43  						select {
    44  						case <-ctx.Done():
    45  							return
    46  						case ch <- loc:
    47  							continue
    48  						}
    49  					}
    50  				}
    51  			}()
    52  			return ch
    53  		}()
    54  	}
    55  
    56  	prog := catalogingProgress(-1)
    57  	for location := range locations {
    58  		prog.AtomicStage.Set(location.Path())
    59  
    60  		metadata, err := resolver.FileMetadataByLocation(location)
    61  		if err != nil {
    62  			prog.SetError(err)
    63  			return nil, err
    64  		}
    65  
    66  		prog.Increment()
    67  
    68  		results[location.Coordinates] = metadata
    69  	}
    70  
    71  	log.Debugf("file metadata cataloger processed %d files", prog.Current())
    72  
    73  	prog.AtomicStage.Set(fmt.Sprintf("%s locations", humanize.Comma(prog.Current())))
    74  	prog.SetCompleted()
    75  
    76  	return results, errs
    77  }
    78  
    79  func catalogingProgress(locations int64) *monitor.TaskProgress {
    80  	info := monitor.GenericTask{
    81  		Title: monitor.Title{
    82  			Default: "File metadata",
    83  		},
    84  		ParentID: monitor.TopLevelCatalogingTaskID,
    85  	}
    86  
    87  	return bus.StartCatalogerTask(info, locations, "")
    88  }