mirror of
https://github.com/anchore/syft.git
synced 2026-11-02 23:46:35 +01:00
Update java generic cataloger (#1329)
* remove centralize pURL generation Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * port java cataloger to new generic cataloger pattern Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * remove common.GenericCataloger Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * update format test fixtures to reflect ID updates Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * fix package sort instability for encode-decode-encode cycles Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
+42
-21
@@ -6,6 +6,7 @@ package pkg
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
@@ -21,11 +22,11 @@ type Package struct {
|
||||
FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package
|
||||
Locations source.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package)
|
||||
Licenses []string // licenses discovered with the package metadata
|
||||
Language Language `cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc)
|
||||
Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc)
|
||||
CPEs []CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields)
|
||||
PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec)
|
||||
MetadataType MetadataType `cyclonedx:"metadataType"` // the shape of the additional data in the "metadata" field
|
||||
Language Language `hash:"ignore" cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc)
|
||||
Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc)
|
||||
CPEs []CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields)
|
||||
PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec)
|
||||
MetadataType MetadataType `cyclonedx:"metadataType"` // the shape of the additional data in the "metadata" field
|
||||
Metadata interface{} // additional data found while parsing the package source
|
||||
}
|
||||
|
||||
@@ -82,23 +83,43 @@ func IsValid(p *Package) bool {
|
||||
return p != nil && p.Name != ""
|
||||
}
|
||||
|
||||
//nolint:gocognit
|
||||
func Less(i, j Package) bool {
|
||||
if i.Name == j.Name {
|
||||
if i.Version == j.Version {
|
||||
iLocations := i.Locations.ToSlice()
|
||||
jLocations := j.Locations.ToSlice()
|
||||
if i.Type == j.Type {
|
||||
maxLen := len(iLocations)
|
||||
if len(jLocations) > maxLen {
|
||||
maxLen = len(jLocations)
|
||||
}
|
||||
for l := 0; l < maxLen; l++ {
|
||||
if len(iLocations) < l+1 || len(jLocations) < l+1 {
|
||||
if len(iLocations) == len(jLocations) {
|
||||
break
|
||||
}
|
||||
return len(iLocations) < len(jLocations)
|
||||
}
|
||||
if iLocations[l].RealPath == jLocations[l].RealPath {
|
||||
continue
|
||||
}
|
||||
return iLocations[l].RealPath < jLocations[l].RealPath
|
||||
}
|
||||
// compare remaining metadata as a final fallback
|
||||
// note: we cannot guarantee that IDs (which digests the metadata) are stable enough to sort on
|
||||
// when there are potentially missing elements there is too much reduction in the dimensions to
|
||||
// lean on ID comparison. The best fallback is to look at the string representation of the metadata.
|
||||
return strings.Compare(fmt.Sprintf("%#v", i.Metadata), fmt.Sprintf("%#v", j.Metadata)) < 0
|
||||
}
|
||||
return i.Type < j.Type
|
||||
}
|
||||
return i.Version < j.Version
|
||||
}
|
||||
return i.Name < j.Name
|
||||
}
|
||||
func Sort(pkgs []Package) {
|
||||
sort.SliceStable(pkgs, func(i, j int) bool {
|
||||
if pkgs[i].Name == pkgs[j].Name {
|
||||
if pkgs[i].Version == pkgs[j].Version {
|
||||
iLocations := pkgs[i].Locations.ToSlice()
|
||||
jLocations := pkgs[j].Locations.ToSlice()
|
||||
if pkgs[i].Type == pkgs[j].Type && len(iLocations) > 0 && len(jLocations) > 0 {
|
||||
if iLocations[0].String() == jLocations[0].String() {
|
||||
// compare IDs as a final fallback
|
||||
return pkgs[i].ID() < pkgs[j].ID()
|
||||
}
|
||||
return iLocations[0].String() < jLocations[0].String()
|
||||
}
|
||||
return pkgs[i].Type < pkgs[j].Type
|
||||
}
|
||||
return pkgs[i].Version < pkgs[j].Version
|
||||
}
|
||||
return pkgs[i].Name < pkgs[j].Name
|
||||
return Less(pkgs[i], pkgs[j])
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user