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 continue
} }
pkgs = append(pkgs, j.packagesFromPomProperties(*pomProperties, parentPkg)...) pkgFromPom := j.newPackageFromPomProperties(*pomProperties, parentPkg)
if pkgFromPom != nil {
pkgs = append(pkgs, *pkgFromPom)
}
} }
return pkgs, nil return pkgs, nil
} }
// packagesFromPomProperties processes a single Maven POM properties for a given parent package, returning all listed Java packages found and // 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. // 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 // keep the artifact name within the virtual path if this package does not match the parent package
vPathSuffix := "" vPathSuffix := ""
if !strings.HasPrefix(pomProperties.ArtifactID, parentPkg.Name) { if !strings.HasPrefix(pomProperties.ArtifactID, parentPkg.Name) {
@ -213,45 +216,12 @@ func (j *archiveParser) packagesFromPomProperties(pomProperties pkg.PomPropertie
}, },
} }
pkgKey := uniquePkgKey(&p) if packageIdentitiesMatch(p, parentPkg) {
parentKey := uniquePkgKey(parentPkg) updatePackage(p, parentPkg)
return nil
// 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 { return &p
// 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
}
return nil
} }
// discoverPkgsFromNestedArchives finds Java archives within Java archives, returning all listed Java packages found and // 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 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

@ -564,11 +564,11 @@ func TestParseNestedJar(t *testing.T) {
func TestPackagesFromPomProperties(t *testing.T) { func TestPackagesFromPomProperties(t *testing.T) {
virtualPath := "given/virtual/path" virtualPath := "given/virtual/path"
tests := []struct { tests := []struct {
name string name string
props *pkg.PomProperties props *pkg.PomProperties
parent *pkg.Package parent *pkg.Package
expectedParent pkg.Package expectedParent pkg.Package
expectedPackages []pkg.Package expectedPackage *pkg.Package
}{ }{
{ {
name: "go case: get a single package from pom properties", name: "go case: get a single package from pom properties",
@ -599,30 +599,28 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil, Parent: nil,
}, },
}, },
expectedPackages: []pkg.Package{ expectedPackage: &pkg.Package{
{ Name: "some-artifact-id",
Name: "some-artifact-id", Version: "1.0",
Version: "1.0", Language: pkg.Java,
Language: pkg.Java, Type: pkg.JavaPkg,
Type: pkg.JavaPkg, MetadataType: pkg.JavaMetadataType,
MetadataType: pkg.JavaMetadataType, Metadata: pkg.JavaMetadata{
Metadata: pkg.JavaMetadata{ VirtualPath: virtualPath + ":" + "some-artifact-id",
VirtualPath: virtualPath + ":" + "some-artifact-id", PomProperties: &pkg.PomProperties{
PomProperties: &pkg.PomProperties{ Name: "some-name",
Name: "some-name", GroupID: "some-group-id",
GroupID: "some-group-id", ArtifactID: "some-artifact-id",
ArtifactID: "some-artifact-id", Version: "1.0",
Version: "1.0", },
}, Parent: &pkg.Package{
Parent: &pkg.Package{ Name: "some-parent-name",
Name: "some-parent-name", Version: "2.0",
Version: "2.0", Metadata: pkg.JavaMetadata{
Metadata: pkg.JavaMetadata{ VirtualPath: "some-parent-virtual-path",
VirtualPath: "some-parent-virtual-path", Manifest: nil,
Manifest: nil, PomProperties: nil,
PomProperties: nil, Parent: nil,
Parent: nil,
},
}, },
}, },
}, },
@ -657,30 +655,28 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil, Parent: nil,
}, },
}, },
expectedPackages: []pkg.Package{ expectedPackage: &pkg.Package{
{ Name: "some-artifact-id",
Name: "some-artifact-id", Version: "1.0",
Version: "1.0", Language: pkg.Java,
Language: pkg.Java, Type: pkg.JenkinsPluginPkg,
Type: pkg.JenkinsPluginPkg, MetadataType: pkg.JavaMetadataType,
MetadataType: pkg.JavaMetadataType, Metadata: pkg.JavaMetadata{
Metadata: pkg.JavaMetadata{ VirtualPath: virtualPath + ":" + "some-artifact-id",
VirtualPath: virtualPath + ":" + "some-artifact-id", PomProperties: &pkg.PomProperties{
PomProperties: &pkg.PomProperties{ Name: "some-name",
Name: "some-name", GroupID: "com.cloudbees.jenkins.plugins",
GroupID: "com.cloudbees.jenkins.plugins", ArtifactID: "some-artifact-id",
ArtifactID: "some-artifact-id", Version: "1.0",
Version: "1.0", },
}, Parent: &pkg.Package{
Parent: &pkg.Package{ Name: "some-parent-name",
Name: "some-parent-name", Version: "2.0",
Version: "2.0", Metadata: pkg.JavaMetadata{
Metadata: pkg.JavaMetadata{ VirtualPath: "some-parent-virtual-path",
VirtualPath: "some-parent-virtual-path", Manifest: nil,
Manifest: nil, PomProperties: nil,
PomProperties: nil, Parent: nil,
Parent: nil,
},
}, },
}, },
}, },
@ -723,7 +719,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil, Parent: nil,
}, },
}, },
expectedPackages: nil, expectedPackage: nil,
}, },
{ {
name: "child matches parent by key and is Jenkins plugin", name: "child matches parent by key and is Jenkins plugin",
@ -761,45 +757,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
Parent: nil, Parent: nil,
}, },
}, },
expectedPackages: nil, expectedPackage: 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,
}, },
{ {
name: "child matches parent by virtual path -- override name and version", 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 Version: "3.0", // note: DOES NOT match parent package
}, },
parent: &pkg.Package{ parent: &pkg.Package{
Name: "", // note: empty Name: "", // note: empty, so should not be matched on
Version: "", // note: empty Version: "", // note: empty, so should not be matched on
Type: pkg.JavaPkg, Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{ Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path VirtualPath: virtualPath, // note: matching virtual path
Manifest: nil, Manifest: nil,
PomProperties: nil, PomProperties: nil,
Parent: nil, Parent: nil,
@ -825,56 +783,19 @@ func TestPackagesFromPomProperties(t *testing.T) {
Version: "3.0", Version: "3.0",
Type: pkg.JavaPkg, Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{ Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":some-parent-name", // note: matching virtual path VirtualPath: virtualPath,
Manifest: nil, Manifest: nil,
// note: we attach the discovered pom properties data // note: we attach the discovered pom properties data
PomProperties: &pkg.PomProperties{ PomProperties: &pkg.PomProperties{
Name: "some-name", Name: "some-name",
GroupID: "some-group-id", GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: DOES NOT match parent package ArtifactID: "some-parent-name",
Version: "3.0", // note: DOES NOT match parent package Version: "3.0",
}, },
Parent: nil, Parent: nil,
}, },
}, },
expectedPackages: nil, expectedPackage: 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,
}, },
{ {
name: "child matches parent by artifact id", name: "child matches parent by artifact id",
@ -898,7 +819,7 @@ func TestPackagesFromPomProperties(t *testing.T) {
// note: the SAME as the original parent values // note: the SAME as the original parent values
expectedParent: pkg.Package{ expectedParent: pkg.Package{
Name: "some-parent-name", Name: "some-parent-name",
Version: "2.0", Version: "NOT_THE_PARENT_VERSION", // note: the version is updated from pom properties
Type: pkg.JavaPkg, Type: pkg.JavaPkg,
Metadata: pkg.JavaMetadata{ Metadata: pkg.JavaMetadata{
VirtualPath: virtualPath + ":NEW_VIRTUAL_PATH", VirtualPath: virtualPath + ":NEW_VIRTUAL_PATH",
@ -907,13 +828,13 @@ func TestPackagesFromPomProperties(t *testing.T) {
PomProperties: &pkg.PomProperties{ PomProperties: &pkg.PomProperties{
Name: "some-name", Name: "some-name",
GroupID: "some-group-id", GroupID: "some-group-id",
ArtifactID: "some-parent-name", // note: matches parent package ArtifactID: "some-parent-name",
Version: "NOT_THE_PARENT_VERSION", // note: DOES NOT match parent package Version: "NOT_THE_PARENT_VERSION",
}, },
Parent: nil, Parent: nil,
}, },
}, },
expectedPackages: nil, expectedPackage: nil,
}, },
} }
@ -929,9 +850,9 @@ func TestPackagesFromPomProperties(t *testing.T) {
t.Cleanup(cleanup) t.Cleanup(cleanup)
// get the test data // get the test data
actualPackages := parser.packagesFromPomProperties(*test.props, test.parent) actualPackage := parser.newPackageFromPomProperties(*test.props, test.parent)
assert.Equal(t, test.expectedPackages, actualPackages) assert.Equal(t, test.expectedPackage, actualPackage, "new package doesn't match")
assert.Equal(t, test.expectedParent, *test.parent) assert.Equal(t, test.expectedParent, *test.parent, "parent doesn't match")
}) })
} }
} }