Merge pull request #403 from anchore/pom-persist-not-for-shaded-jars

Update parent pom persistence with regard to shaded jars
This commit is contained in:
Alex Goodman 2021-04-22 15:51:38 -04:00 committed by GitHub
commit 1b62b10b2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 121 additions and 183 deletions

View File

@ -184,14 +184,17 @@ func (j *archiveParser) discoverPkgsFromAllPomProperties(parentPkg *pkg.Package)
continue
}
pkgs = append(pkgs, j.packagesFromPomProperties(*pomProperties, parentPkg)...)
pkgFromPom := j.newPackageFromPomProperties(*pomProperties, parentPkg)
if pkgFromPom != nil {
pkgs = append(pkgs, *pkgFromPom)
}
}
return pkgs, nil
}
// packagesFromPomProperties processes a single Maven POM properties for a given parent package, returning all listed Java packages found and
// associating each discovered package to the given parent package.
func (j *archiveParser) packagesFromPomProperties(pomProperties pkg.PomProperties, parentPkg *pkg.Package) []pkg.Package {
func (j *archiveParser) newPackageFromPomProperties(pomProperties pkg.PomProperties, parentPkg *pkg.Package) *pkg.Package {
// keep the artifact name within the virtual path if this package does not match the parent package
vPathSuffix := ""
if !strings.HasPrefix(pomProperties.ArtifactID, parentPkg.Name) {
@ -213,45 +216,12 @@ func (j *archiveParser) packagesFromPomProperties(pomProperties pkg.PomPropertie
},
}
pkgKey := uniquePkgKey(&p)
parentKey := uniquePkgKey(parentPkg)
// the name/version pair matches...
matchesParentPkg := pkgKey == parentKey
// the virtual path matches...
matchesParentPkg = matchesParentPkg || parentPkg.Metadata.(pkg.JavaMetadata).VirtualPath == virtualPath
// the pom artifactId has the parent name or vice versa
if pomProperties.ArtifactID != "" {
matchesParentPkg = matchesParentPkg || strings.Contains(parentPkg.Name, pomProperties.ArtifactID) || strings.Contains(pomProperties.ArtifactID, parentPkg.Name)
}
if !matchesParentPkg {
// only keep packages we haven't seen yet (and are not related to the parent package)
return []pkg.Package{p}
}
// we've run across more information about our parent package, add this info to the parent package metadata
// the pom properties is typically a better source of information for name and version than the manifest
if parentPkg.Name == "" {
parentPkg.Name = p.Name
}
if parentPkg.Version == "" {
parentPkg.Version = p.Version
}
// We may have learned more about the type via data in the pom properties
parentPkg.Type = p.Type
// keep the pom properties, but don't overwrite existing pom properties
parentMetadata, ok := parentPkg.Metadata.(pkg.JavaMetadata)
if ok && parentMetadata.PomProperties == nil {
parentMetadata.PomProperties = &pomProperties
parentPkg.Metadata = parentMetadata
}
if packageIdentitiesMatch(p, parentPkg) {
updatePackage(p, parentPkg)
return nil
}
return &p
}
// discoverPkgsFromNestedArchives finds Java archives within Java archives, returning all listed Java packages found and
@ -297,3 +267,50 @@ func (j *archiveParser) discoverPkgsFromNestedArchives(parentPkg *pkg.Package) (
return pkgs, nil
}
func packageIdentitiesMatch(p pkg.Package, parentPkg *pkg.Package) bool {
// the name/version pair matches...
if uniquePkgKey(&p) == uniquePkgKey(parentPkg) {
return true
}
metadata := p.Metadata.(pkg.JavaMetadata)
// the virtual path matches...
if parentPkg.Metadata.(pkg.JavaMetadata).VirtualPath == metadata.VirtualPath {
return true
}
// the pom artifactId is the parent name
// note: you CANNOT use name-is-subset-of-artifact-id or vice versa --this is too generic. Shaded jars are a good
// example of this: where the package name is "cloudbees-analytics-segment-driver" and a child is "analytics", but
// they do not indicate the same package.
if metadata.PomProperties.ArtifactID != "" && parentPkg.Name == metadata.PomProperties.ArtifactID {
return true
}
return false
}
func updatePackage(p pkg.Package, parentPkg *pkg.Package) {
// we've run across more information about our parent package, add this info to the parent package metadata
// the pom properties is typically a better source of information for name and version than the manifest
parentPkg.Name = p.Name
parentPkg.Version = p.Version
// we may have learned more about the type via data in the pom properties
parentPkg.Type = p.Type
metadata, ok := p.Metadata.(pkg.JavaMetadata)
if !ok {
return
}
pomPropertiesCopy := *metadata.PomProperties
// keep the pom properties, but don't overwrite existing pom properties
parentMetadata, ok := parentPkg.Metadata.(pkg.JavaMetadata)
if ok && parentMetadata.PomProperties == nil {
parentMetadata.PomProperties = &pomPropertiesCopy
parentPkg.Metadata = parentMetadata
}
}

View File

@ -568,7 +568,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
props *pkg.PomProperties
parent *pkg.Package
expectedParent pkg.Package
expectedPackages []pkg.Package
expectedPackage *pkg.Package
}{
{
name: "go case: get a single package from pom properties",
@ -599,8 +599,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil,
},
},
expectedPackages: []pkg.Package{
{
expectedPackage: &pkg.Package{
Name: "some-artifact-id",
Version: "1.0",
Language: pkg.Java,
@ -627,7 +626,6 @@ func TestPackagesFromPomProperties(t *testing.T) {
},
},
},
},
{
name: "single package from pom properties that's a Jenkins plugin",
props: &pkg.PomProperties{
@ -657,8 +655,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil,
},
},
expectedPackages: []pkg.Package{
{
expectedPackage: &pkg.Package{
Name: "some-artifact-id",
Version: "1.0",
Language: pkg.Java,
@ -685,7 +682,6 @@ func TestPackagesFromPomProperties(t *testing.T) {
},
},
},
},
{
name: "child matches parent by key",
props: &pkg.PomProperties{
@ -723,7 +719,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil,
},
},
expectedPackages: nil,
expectedPackage: nil,
},
{
name: "child matches parent by key and is Jenkins plugin",
@ -761,45 +757,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil,
},
},
expectedPackages: nil,
},
{
name: "child matches parent by virtual path",
props: &pkg.PomProperties{
Name: "some-name",
GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: matches parent package
Version: "NOT_THE_PARENT_VERSION", // note: DOES NOT match parent package
},
parent: &pkg.Package{
Name: "some-parent-name",
Version: "2.0",
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path
Manifest: nil,
PomProperties: nil,
Parent: nil,
},
},
expectedParent: pkg.Package{
Name: "some-parent-name",
Version: "2.0",
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path
Manifest: nil,
// note: we attach the discovered pom properties data
PomProperties: &pkg.PomProperties{
Name: "some-name",
GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: matches parent package
Version: "NOT_THE_PARENT_VERSION", // note: DOES NOT match parent package
},
Parent: nil,
},
},
expectedPackages: nil,
expectedPackage: nil,
},
{
name: "child matches parent by virtual path -- override name and version",
@ -810,11 +768,11 @@ func TestPackagesFromPomProperties(t *testing.T) {
Version: "3.0", // note: DOES NOT match parent package
},
parent: &pkg.Package{
Name: "", // note: empty
Version: "", // note: empty
Name: "", // note: empty, so should not be matched on
Version: "", // note: empty, so should not be matched on
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path
VirtualPath: virtualPath, // note: matching virtual path
Manifest: nil,
PomProperties: nil,
Parent: nil,
@ -825,56 +783,19 @@ func TestPackagesFromPomProperties(t *testing.T) {
Version: "3.0",
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path
VirtualPath: virtualPath,
Manifest: nil,
// note: we attach the discovered pom properties data
PomProperties: &pkg.PomProperties{
Name: "some-name",
GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: DOES NOT match parent package
Version: "3.0", // note: DOES NOT match parent package
ArtifactID: "some-parent-name",
Version: "3.0",
},
Parent: nil,
},
},
expectedPackages: nil,
},
{
name: "child matches parent by virtual path -- do not override existing pom properties",
props: &pkg.PomProperties{
Name: "some-name",
GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: matches parent package
Version: "NOT_THE_PARENT_VERSION", // note: DOES NOT match parent package
},
parent: &pkg.Package{
Name: "some-parent-name",
Version: "2.0",
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path
Manifest: nil,
PomProperties: &pkg.PomProperties{
Name: "EXISTS", // note: this already exists and should not be overridden
},
Parent: nil,
},
},
expectedParent: pkg.Package{
Name: "some-parent-name",
Version: "2.0",
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path
Manifest: nil,
// note: we attach the discovered pom properties data
PomProperties: &pkg.PomProperties{
Name: "EXISTS", // note: this already exists and should not be overridden
},
Parent: nil,
},
},
expectedPackages: nil,
expectedPackage: nil,
},
{
name: "child matches parent by artifact id",
@ -898,7 +819,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
// note: the SAME as the original parent values
expectedParent: pkg.Package{
Name: "some-parent-name",
Version: "2.0",
Version: "NOT_THE_PARENT_VERSION", // note: the version is updated from pom properties
Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":NEW_VIRTUAL_PATH",
@ -907,13 +828,13 @@ func TestPackagesFromPomProperties(t *testing.T) {
PomProperties: &pkg.PomProperties{
Name: "some-name",
GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: matches parent package
Version: "NOT_THE_PARENT_VERSION", // note: DOES NOT match parent package
ArtifactID: "some-parent-name",
Version: "NOT_THE_PARENT_VERSION",
},
Parent: nil,
},
},
expectedPackages: nil,
expectedPackage: nil,
},
}
@ -929,9 +850,9 @@ func TestPackagesFromPomProperties(t *testing.T) {
t.Cleanup(cleanup)
// get the test data
actualPackages := parser.packagesFromPomProperties(*test.props, test.parent)
assert.Equal(t, test.expectedPackages, actualPackages)
assert.Equal(t, test.expectedParent, *test.parent)
actualPackage := parser.newPackageFromPomProperties(*test.props, test.parent)
assert.Equal(t, test.expectedPackage, actualPackage, "new package doesn't match")
assert.Equal(t, test.expectedParent, *test.parent, "parent doesn't match")
})
}
}