Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 78 additions & 18 deletions syft/pkg/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ loopNewIDs:
}
}

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 {
byID map[artifact.ID]Package
Expand Down Expand Up @@ -92,30 +101,32 @@ func (c *Catalog) Packages(ids []artifact.ID) (result []Package) {
return result
}

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

id := p.ID()
if id == "" {
log.Warnf("found package with empty ID while adding to the catalog: %+v", p)
p.SetID()
id = p.ID()
}
for _, p := range pkgs {
id := p.ID()
if id == "" {
log.Warnf("found package with empty ID while adding to the catalog: %+v", p)
p.SetID()
id = p.ID()
}

if existing, exists := c.byID[id]; exists {
// there is already a package with this fingerprint merge the existing record with the new one
if err := existing.merge(p); err != nil {
log.Warnf("failed to merge packages: %+v", err)
} else {
c.byID[id] = existing
c.addPathsToIndex(p)
if existing, exists := c.byID[id]; exists {
// there is already a package with this fingerprint merge the existing record with the new one
if err := existing.merge(p); err != nil {
log.Warnf("failed to merge packages: %+v", err)
} else {
c.byID[id] = existing
c.addPathsToIndex(p)
}
return
}
return
}

c.addToIndex(p)
c.addToIndex(p)
}
}

func (c *Catalog) addToIndex(p Package) {
Expand Down Expand Up @@ -157,6 +168,55 @@ func (c *Catalog) addPathToIndex(id artifact.ID, path string) {
c.idsByPath[path] = pathIndex
}

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

for _, id := range ids {
p, exists := c.byID[id]
if !exists {
return
}

delete(c.byID, id)
c.deleteNameFromIndex(p)
c.deleteTypeFromIndex(p)
c.deletePathsFromIndex(p)
}
}

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

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

func (c *Catalog) deletePathsFromIndex(p Package) {
observedPaths := internal.NewStringSet()
for _, l := range p.Locations.ToSlice() {
if l.RealPath != "" && !observedPaths.Contains(l.RealPath) {
c.deletePathFromIndex(p.id, l.RealPath)
observedPaths.Add(l.RealPath)
}
if l.VirtualPath != "" && l.RealPath != l.VirtualPath && !observedPaths.Contains(l.VirtualPath) {
c.deletePathFromIndex(p.id, l.VirtualPath)
observedPaths.Add(l.VirtualPath)
}
}
}

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

// Enumerate all packages for the given type(s), enumerating all packages if no type is specified.
func (c *Catalog) Enumerate(types ...Type) <-chan Package {
channel := make(chan Package)
Expand Down
25 changes: 25 additions & 0 deletions syft/pkg/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ type expectedIndexes struct {
byPath map[string]*strset.Set
}

func TestCatalogDeleteRemovesPackages(t *testing.T) {
c := NewCatalog()
pkg1 := Package{
id: artifact.ID("pkg1"),
Name: "pkg1",
Type: RpmPkg,
}
pkg2 := Package{
id: artifact.ID("pkg2"),
Name: "pkg2",
Type: RpmPkg,
}
pkg3 := Package{
id: artifact.ID("pkg3"),
Name: "pkg3",
Type: RpmPkg,
}
c.Add(pkg1, pkg2, pkg3)

c.Delete(pkg1.ID(), pkg2.ID())

assert.Equal(t, 1, c.PackageCount())
assert.Equal(t, []Package{pkg3}, c.Sorted())
Comment thread
spiffcs marked this conversation as resolved.
Outdated
}

func TestCatalogAddPopulatesIndex(t *testing.T) {

var pkgs = []Package{
Expand Down