add purl types to cataloger info cmd (#4984)

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman
2026-06-16 12:13:34 -04:00
committed by GitHub
parent 92ae4d44c5
commit 951fbd454a
40 changed files with 266 additions and 7 deletions
+38
View File
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"sort"
"strings"
"github.com/scylladb/go-set/strset"
@@ -10,6 +11,7 @@ import (
"github.com/anchore/syft/internal/capabilities"
"github.com/anchore/syft/internal/capabilities/internal"
"github.com/anchore/syft/internal/packagemetadata"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/binary"
)
@@ -192,6 +194,9 @@ func RegenerateCapabilities(catalogerDir string, repoRoot string) (*Statistics,
formatOrphans(orphans))
}
// 5a. Derive PURL types from the discovered package types (purely a function of pkg.Type)
derivePURLTypes(updated)
// 6. Write back to YAML files with comments, preserving existing node trees
fmt.Print(" → Writing updated capabilities files...")
if err := saveCapabilities(catalogerDir, repoRoot, updated, existingNodes); err != nil {
@@ -427,6 +432,39 @@ func (e *EnrichmentData) GetMetadataTypes(catalogerName string) ([]string, bool)
return types, ok
}
// derivePURLTypes populates the PURLTypes field on every cataloger and parser by mapping each
// observed package type to its canonical PURL type via pkg.Type.PackageURLType. this is a pure
// function of the already-discovered package_types, so it needs no additional test observations.
func derivePURLTypes(doc *capabilities.Document) {
for i := range doc.Catalogers {
cat := &doc.Catalogers[i]
cat.PURLTypes = purlTypesFromPackageTypes(cat.PackageTypes)
for j := range cat.Parsers {
cat.Parsers[j].PURLTypes = purlTypesFromPackageTypes(cat.Parsers[j].PackageTypes)
}
}
}
// purlTypesFromPackageTypes maps syft package type strings (e.g. "go-module") to their PURL types
// (e.g. "golang"), returning a deduplicated, sorted slice. package types with no PURL mapping are skipped.
func purlTypesFromPackageTypes(packageTypes []string) []string {
if len(packageTypes) == 0 {
return nil
}
set := strset.New()
for _, pt := range packageTypes {
if purlType := pkg.Type(pt).PackageURLType(); purlType != "" {
set.Add(purlType)
}
}
if set.IsEmpty() {
return nil
}
result := set.List()
sort.Strings(result)
return result
}
// GetPackageTypes returns the package types for the given cataloger name
func (e *EnrichmentData) GetPackageTypes(catalogerName string) ([]string, bool) {
types, ok := e.packageTypes[catalogerName]