mirror of
https://github.com/anchore/syft.git
synced 2026-11-05 00:46:38 +01:00
* unexport as many types and functions from cataloger packages as possible Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * capture type and signature information in convention test Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * check that we return pkg.Cataloger from constructors Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
105 lines
2.8 KiB
Go
105 lines
2.8 KiB
Go
/*
|
|
Package nix provides a concrete Cataloger implementation for packages within the Nix packaging ecosystem.
|
|
*/
|
|
package nix
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/bmatcuk/doublestar/v4"
|
|
|
|
"github.com/anchore/syft/internal/log"
|
|
"github.com/anchore/syft/syft/artifact"
|
|
"github.com/anchore/syft/syft/file"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
)
|
|
|
|
const catalogerName = "nix-store-cataloger"
|
|
|
|
// storeCataloger finds package outputs installed in the Nix store location (/nix/store/*).
|
|
type storeCataloger struct{}
|
|
|
|
func NewStoreCataloger() pkg.Cataloger {
|
|
return &storeCataloger{}
|
|
}
|
|
|
|
func (c *storeCataloger) Name() string {
|
|
return catalogerName
|
|
}
|
|
|
|
func (c *storeCataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
|
|
// we want to search for only directories, which isn't possible via the stereoscope API, so we need to apply the glob manually on all returned paths
|
|
var pkgs []pkg.Package
|
|
var filesByPath = make(map[string]*file.LocationSet)
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
for location := range resolver.AllLocations(ctx) {
|
|
matchesStorePath, err := doublestar.Match("**/nix/store/*", location.RealPath)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to match nix store path: %w", err)
|
|
}
|
|
|
|
parentStorePath := findParentNixStorePath(location.RealPath)
|
|
if parentStorePath != "" {
|
|
if _, ok := filesByPath[parentStorePath]; !ok {
|
|
s := file.NewLocationSet()
|
|
filesByPath[parentStorePath] = &s
|
|
}
|
|
filesByPath[parentStorePath].Add(location)
|
|
}
|
|
|
|
if !matchesStorePath {
|
|
continue
|
|
}
|
|
|
|
storePath := parseNixStorePath(location.RealPath)
|
|
|
|
if storePath == nil || !storePath.isValidPackage() {
|
|
continue
|
|
}
|
|
|
|
p := newNixStorePackage(*storePath, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
|
pkgs = append(pkgs, p)
|
|
}
|
|
|
|
// add file sets to packages
|
|
for i := range pkgs {
|
|
p := &pkgs[i]
|
|
locations := p.Locations.ToSlice()
|
|
if len(locations) == 0 {
|
|
log.WithFields("package", p.Name).Warn("nix package has no evidence locations associated")
|
|
continue
|
|
}
|
|
parentStorePath := locations[0].RealPath
|
|
files, ok := filesByPath[parentStorePath]
|
|
if !ok {
|
|
log.WithFields("path", parentStorePath, "nix-store-path", parentStorePath).Warn("found a nix store file for a non-existent package")
|
|
continue
|
|
}
|
|
appendFiles(p, files.ToSlice()...)
|
|
}
|
|
|
|
return pkgs, nil, nil
|
|
}
|
|
|
|
func appendFiles(p *pkg.Package, location ...file.Location) {
|
|
metadata, ok := p.Metadata.(pkg.NixStoreEntry)
|
|
if !ok {
|
|
log.WithFields("package", p.Name).Warn("nix package metadata missing")
|
|
return
|
|
}
|
|
|
|
for _, l := range location {
|
|
metadata.Files = append(metadata.Files, l.RealPath)
|
|
}
|
|
|
|
if metadata.Files == nil {
|
|
// note: we always have an allocated collection for output
|
|
metadata.Files = []string{}
|
|
}
|
|
|
|
p.Metadata = metadata
|
|
p.SetID()
|
|
}
|