Skip to content

Commit

Permalink
Merge branch 'main' into 1577-license-revamp
Browse files Browse the repository at this point in the history
* main:
  rename pkg.Catalog to pkg.Collection (#1764)

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
  • Loading branch information
spiffcs committed Apr 26, 2023
2 parents 10e3fdd + fd02bef commit 13ecc40
Show file tree
Hide file tree
Showing 22 changed files with 96 additions and 87 deletions.
2 changes: 1 addition & 1 deletion syft/formats/common/cyclonedxhelpers/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func ToSyftModel(bom *cyclonedx.BOM) (*sbom.SBOM, error) {

s := &sbom.SBOM{
Artifacts: sbom.Artifacts{
PackageCatalog: pkg.NewCatalog(),
PackageCatalog: pkg.NewCollection(),
LinuxDistribution: linuxReleaseFromComponents(*bom.Components),
},
Source: extractComponents(bom.Metadata),
Expand Down
6 changes: 3 additions & 3 deletions syft/formats/common/spdxhelpers/to_format_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,10 @@ func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID {
return spdx.ElementID(id)
}

// packages populates all Package Information from the package Catalog (see https://spdx.github.io/spdx-spec/3-package-information/)
// packages populates all Package Information from the package Collection (see https://spdx.github.io/spdx-spec/3-package-information/)
//
//nolint:funlen
func toPackages(catalog *pkg.Catalog, sbom sbom.SBOM) (results []*spdx.Package) {
func toPackages(catalog *pkg.Collection, sbom sbom.SBOM) (results []*spdx.Package) {
for _, p := range catalog.Sorted() {
// name should be guaranteed to be unique, but semantically useful and stable
id := toSPDXID(p)
Expand Down Expand Up @@ -519,7 +519,7 @@ func toFileTypes(metadata *source.FileMetadata) (ty []string) {

// other licenses are for licenses from the pkg.Package that do not have an SPDXExpression
// field. The spdxexpression field is only filled given a validated Value field.
func toOtherLicenses(catalog *pkg.Catalog) []*spdx.OtherLicense {
func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
licenses := map[string]bool{}
for _, p := range catalog.Sorted() {
d, c := parseLicenses(p.Licenses)
Expand Down
4 changes: 2 additions & 2 deletions syft/formats/common/spdxhelpers/to_format_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ func Test_H1Digest(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
catalog := pkg.NewCatalog(test.pkg)
catalog := pkg.NewCollection(test.pkg)
pkgs := toPackages(catalog, s)
require.Len(t, pkgs, 1)
for _, p := range pkgs {
Expand Down Expand Up @@ -498,7 +498,7 @@ func Test_OtherLicenses(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
catalog := pkg.NewCatalog(test.pkg)
catalog := pkg.NewCollection(test.pkg)
otherLicenses := toOtherLicenses(catalog)
require.Len(t, otherLicenses, len(test.expected))
require.Equal(t, test.expected, otherLicenses)
Expand Down
2 changes: 1 addition & 1 deletion syft/formats/common/spdxhelpers/to_syft_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func ToSyftModel(doc *spdx.Document) (*sbom.SBOM, error) {
s := &sbom.SBOM{
Source: src,
Artifacts: sbom.Artifacts{
PackageCatalog: pkg.NewCatalog(),
PackageCatalog: pkg.NewCollection(),
FileMetadata: map[source.Coordinates]source.FileMetadata{},
FileDigests: map[source.Coordinates][]file.Digest{},
LinuxDistribution: findLinuxReleaseByPURL(doc),
Expand Down
2 changes: 1 addition & 1 deletion syft/formats/github/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func Test_toGithubModel(t *testing.T) {
VersionID: "18.04",
IDLike: []string{"debian"},
},
PackageCatalog: pkg.NewCatalog(),
PackageCatalog: pkg.NewCollection(),
},
}
for _, p := range []pkg.Package{
Expand Down
12 changes: 6 additions & 6 deletions syft/formats/internal/testutils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func AssertEncoderAgainstGoldenSnapshot(t *testing.T, format sbom.Format, sbom s

func ImageInput(t testing.TB, testImage string, options ...ImageOption) sbom.SBOM {
t.Helper()
catalog := pkg.NewCatalog()
catalog := pkg.NewCollection()
var cfg imageCfg
var img *image.Image
for _, opt := range options {
Expand Down Expand Up @@ -146,7 +146,7 @@ func carriageRedactor(s []byte) []byte {
return []byte(msg)
}

func populateImageCatalog(catalog *pkg.Catalog, img *image.Image) {
func populateImageCatalog(catalog *pkg.Collection, img *image.Image) {
_, ref1, _ := img.SquashedTree().File("/somefile-1.txt", filetree.FollowBasenameLinks)
_, ref2, _ := img.SquashedTree().File("/somefile-2.txt", filetree.FollowBasenameLinks)

Expand Down Expand Up @@ -260,8 +260,8 @@ func DirectoryInputWithAuthorField(t testing.TB) sbom.SBOM {
}
}

func newDirectoryCatalog() *pkg.Catalog {
catalog := pkg.NewCatalog()
func newDirectoryCatalog() *pkg.Collection {
catalog := pkg.NewCollection()

// populate catalog with test data
catalog.Add(pkg.Package{
Expand Down Expand Up @@ -318,8 +318,8 @@ func newDirectoryCatalog() *pkg.Catalog {
return catalog
}

func newDirectoryCatalogWithAuthorField() *pkg.Catalog {
catalog := pkg.NewCatalog()
func newDirectoryCatalogWithAuthorField() *pkg.Collection {
catalog := pkg.NewCollection()

// populate catalog with test data
catalog.Add(pkg.Package{
Expand Down
2 changes: 1 addition & 1 deletion syft/formats/spdxtagvalue/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestSPDXJSONSPDXIDs(t *testing.T) {
Format(),
sbom.SBOM{
Artifacts: sbom.Artifacts{
PackageCatalog: pkg.NewCatalog(pkgs...),
PackageCatalog: pkg.NewCollection(pkgs...),
},
Relationships: nil,
Source: source.Metadata{
Expand Down
2 changes: 1 addition & 1 deletion syft/formats/syftjson/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func schemaVersionRedactor(s []byte) []byte {
}

func TestEncodeFullJSONDocument(t *testing.T) {
catalog := pkg.NewCatalog()
catalog := pkg.NewCollection()

p1 := pkg.Package{
Name: "package-1",
Expand Down
2 changes: 1 addition & 1 deletion syft/formats/syftjson/to_format_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func toFileType(ty stereoscopeFile.Type) string {
}
}

func toPackageModels(catalog *pkg.Catalog) []model.Package {
func toPackageModels(catalog *pkg.Collection) []model.Package {
artifacts := make([]model.Package, 0)
if catalog == nil {
return artifacts
Expand Down
6 changes: 3 additions & 3 deletions syft/formats/syftjson/to_syft_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func toSyftLinuxRelease(d model.LinuxRelease) *linux.Release {
}
}

func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationships []model.Relationship, idAliases map[string]string) []artifact.Relationship {
func toSyftRelationships(doc *model.Document, catalog *pkg.Collection, relationships []model.Relationship, idAliases map[string]string) []artifact.Relationship {
idMap := make(map[string]interface{})

for _, p := range catalog.Sorted() {
Expand Down Expand Up @@ -256,8 +256,8 @@ func toSyftSourceData(s model.Source) *source.Metadata {
return nil
}

func toSyftCatalog(pkgs []model.Package, idAliases map[string]string) *pkg.Catalog {
catalog := pkg.NewCatalog()
func toSyftCatalog(pkgs []model.Package, idAliases map[string]string) *pkg.Collection {
catalog := pkg.NewCollection()
for _, p := range pkgs {
catalog.Add(toSyftPackage(p, idAliases))
}
Expand Down
4 changes: 2 additions & 2 deletions syft/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
// CatalogPackages takes an inventory of packages from the given image from a particular perspective
// (e.g. squashed source, all-layers source). Returns the discovered set of packages, the identified Linux
// distribution, and the source object used to wrap the data source.
func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Catalog, []artifact.Relationship, *linux.Release, error) {
func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Collection, []artifact.Relationship, *linux.Release, error) {
resolver, err := src.FileResolver(cfg.Search.Scope)
if err != nil {
return nil, nil, nil, fmt.Errorf("unable to determine resolver while cataloging packages: %w", err)
Expand Down Expand Up @@ -76,7 +76,7 @@ func CatalogPackages(src *source.Source, cfg cataloger.Config) (*pkg.Catalog, []
return catalog, relationships, release, err
}

func newSourceRelationshipsFromCatalog(src *source.Source, c *pkg.Catalog) []artifact.Relationship {
func newSourceRelationshipsFromCatalog(src *source.Source, c *pkg.Collection) []artifact.Relationship {
relationships := make([]artifact.Relationship, 0) // Should we pre-allocate this by giving catalog a Len() method?
for p := range c.Enumerate() {
relationships = append(relationships, artifact.Relationship{
Expand Down
96 changes: 48 additions & 48 deletions syft/pkg/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,18 @@ import (
"github.com/anchore/syft/syft/artifact"
)

type orderedIDSet struct {
slice []artifact.ID
}

func (s *orderedIDSet) add(ids ...artifact.ID) {
loopNewIDs:
for _, newID := range ids {
for _, existingID := range s.slice {
if existingID == newID {
continue loopNewIDs
}
}
s.slice = append(s.slice, newID)
}
}

func (s *orderedIDSet) delete(id artifact.ID) {
for i, existingID := range s.slice {
if existingID == id {
s.slice = append(s.slice[:i], s.slice[i+1:]...)
return
}
}
}

// Catalog represents a collection of Packages.
type Catalog struct {
// Collection represents a collection of Packages.
type Collection struct {
byID map[artifact.ID]Package
idsByName map[string]orderedIDSet
idsByType map[Type]orderedIDSet
idsByPath map[string]orderedIDSet // note: this is real path or virtual path
lock sync.RWMutex
}

// NewCatalog returns a new empty Catalog
func NewCatalog(pkgs ...Package) *Catalog {
catalog := Catalog{
// NewCollection returns a new empty Collection
func NewCollection(pkgs ...Package) *Collection {
catalog := Collection{
byID: make(map[artifact.ID]Package),
idsByName: make(map[string]orderedIDSet),
idsByType: make(map[Type]orderedIDSet),
Expand All @@ -61,12 +36,12 @@ func NewCatalog(pkgs ...Package) *Catalog {
}

// PackageCount returns the total number of packages that have been added.
func (c *Catalog) PackageCount() int {
func (c *Collection) PackageCount() int {
return len(c.byID)
}

// Package returns the package with the given ID.
func (c *Catalog) Package(id artifact.ID) *Package {
func (c *Collection) Package(id artifact.ID) *Package {
v, exists := c.byID[id]
if !exists {
return nil
Expand All @@ -81,17 +56,17 @@ func (c *Catalog) Package(id artifact.ID) *Package {
}

// PackagesByPath returns all packages that were discovered from the given path.
func (c *Catalog) PackagesByPath(path string) []Package {
func (c *Collection) PackagesByPath(path string) []Package {
return c.Packages(c.idsByPath[path].slice)
}

// PackagesByName returns all packages that were discovered with a matching name.
func (c *Catalog) PackagesByName(name string) []Package {
func (c *Collection) PackagesByName(name string) []Package {
return c.Packages(c.idsByName[name].slice)
}

// Packages returns all packages for the given ID.
func (c *Catalog) Packages(ids []artifact.ID) (result []Package) {
func (c *Collection) Packages(ids []artifact.ID) (result []Package) {
for _, i := range ids {
p, exists := c.byID[i]
if exists {
Expand All @@ -102,7 +77,7 @@ func (c *Catalog) Packages(ids []artifact.ID) (result []Package) {
}

// Add n packages to the catalog.
func (c *Catalog) Add(pkgs ...Package) {
func (c *Collection) Add(pkgs ...Package) {
c.lock.Lock()
defer c.lock.Unlock()

Expand All @@ -129,26 +104,26 @@ func (c *Catalog) Add(pkgs ...Package) {
}
}

func (c *Catalog) addToIndex(p Package) {
func (c *Collection) addToIndex(p Package) {
c.byID[p.id] = p
c.addNameToIndex(p)
c.addTypeToIndex(p)
c.addPathsToIndex(p)
}

func (c *Catalog) addNameToIndex(p Package) {
func (c *Collection) addNameToIndex(p Package) {
nameIndex := c.idsByName[p.Name]
nameIndex.add(p.id)
c.idsByName[p.Name] = nameIndex
}

func (c *Catalog) addTypeToIndex(p Package) {
func (c *Collection) addTypeToIndex(p Package) {
typeIndex := c.idsByType[p.Type]
typeIndex.add(p.id)
c.idsByType[p.Type] = typeIndex
}

func (c *Catalog) addPathsToIndex(p Package) {
func (c *Collection) addPathsToIndex(p Package) {
observedPaths := internal.NewStringSet()
for _, l := range p.Locations.ToSlice() {
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
Expand All @@ -162,13 +137,13 @@ func (c *Catalog) addPathsToIndex(p Package) {
}
}

func (c *Catalog) addPathToIndex(id artifact.ID, path string) {
func (c *Collection) addPathToIndex(id artifact.ID, path string) {
pathIndex := c.idsByPath[path]
pathIndex.add(id)
c.idsByPath[path] = pathIndex
}

func (c *Catalog) Delete(ids ...artifact.ID) {
func (c *Collection) Delete(ids ...artifact.ID) {
c.lock.Lock()
defer c.lock.Unlock()

Expand All @@ -185,19 +160,19 @@ func (c *Catalog) Delete(ids ...artifact.ID) {
}
}

func (c *Catalog) deleteNameFromIndex(p Package) {
func (c *Collection) deleteNameFromIndex(p Package) {
nameIndex := c.idsByName[p.Name]
nameIndex.delete(p.id)
c.idsByName[p.Name] = nameIndex
}

func (c *Catalog) deleteTypeFromIndex(p Package) {
func (c *Collection) deleteTypeFromIndex(p Package) {
typeIndex := c.idsByType[p.Type]
typeIndex.delete(p.id)
c.idsByType[p.Type] = typeIndex
}

func (c *Catalog) deletePathsFromIndex(p Package) {
func (c *Collection) deletePathsFromIndex(p Package) {
observedPaths := internal.NewStringSet()
for _, l := range p.Locations.ToSlice() {
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
Expand All @@ -211,7 +186,7 @@ func (c *Catalog) deletePathsFromIndex(p Package) {
}
}

func (c *Catalog) deletePathFromIndex(id artifact.ID, path string) {
func (c *Collection) deletePathFromIndex(id artifact.ID, path string) {
pathIndex := c.idsByPath[path]
pathIndex.delete(id)
if len(pathIndex.slice) == 0 {
Expand All @@ -222,7 +197,7 @@ func (c *Catalog) deletePathFromIndex(id artifact.ID, path string) {
}

// Enumerate all packages for the given type(s), enumerating all packages if no type is specified.
func (c *Catalog) Enumerate(types ...Type) <-chan Package {
func (c *Collection) Enumerate(types ...Type) <-chan Package {
channel := make(chan Package)
go func() {
defer close(channel)
Expand Down Expand Up @@ -257,7 +232,7 @@ func (c *Catalog) Enumerate(types ...Type) <-chan Package {

// Sorted enumerates all packages for the given types sorted by package name. Enumerates all packages if no type
// is specified.
func (c *Catalog) Sorted(types ...Type) (pkgs []Package) {
func (c *Collection) Sorted(types ...Type) (pkgs []Package) {
for p := range c.Enumerate(types...) {
pkgs = append(pkgs, p)
}
Expand All @@ -266,3 +241,28 @@ func (c *Catalog) Sorted(types ...Type) (pkgs []Package) {

return pkgs
}

type orderedIDSet struct {
slice []artifact.ID
}

func (s *orderedIDSet) add(ids ...artifact.ID) {
loopNewIDs:
for _, newID := range ids {
for _, existingID := range s.slice {
if existingID == newID {
continue loopNewIDs
}
}
s.slice = append(s.slice, newID)
}
}

func (s *orderedIDSet) delete(id artifact.ID) {
for i, existingID := range s.slice {
if existingID == id {
s.slice = append(s.slice[:i], s.slice[i+1:]...)
return
}
}
}
Loading

0 comments on commit 13ecc40

Please sign in to comment.