mirror of
https://github.com/anchore/syft.git
synced 2026-10-31 06:26:30 +01:00
translate maps to sequences in pkg metadata (#2553)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/gookit/color"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
@@ -197,31 +198,31 @@ func TestParseJar(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-jenkins-plugin.hpi",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Specification-Title": "Example Jenkins Plugin",
|
||||
"Specification-Version": "1.0",
|
||||
"Implementation-Title": "Example Jenkins Plugin",
|
||||
"Implementation-Version": "1.0-SNAPSHOT",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
{Key: "Created-By", Value: "Maven Archiver 3.6.0"},
|
||||
{Key: "Build-Jdk-Spec", Value: "18"},
|
||||
{Key: "Specification-Title", Value: "Example Jenkins Plugin"},
|
||||
{Key: "Specification-Version", Value: "1.0"},
|
||||
{Key: "Implementation-Title", Value: "Example Jenkins Plugin"},
|
||||
{Key: "Implementation-Version", Value: "1.0-SNAPSHOT"},
|
||||
{Key: "Group-Id", Value: "io.jenkins.plugins"},
|
||||
{Key: "Short-Name", Value: "example-jenkins-plugin"},
|
||||
{Key: "Long-Name", Value: "Example Jenkins Plugin"},
|
||||
{Key: "Hudson-Version", Value: "2.204"},
|
||||
{Key: "Jenkins-Version", Value: "2.204"},
|
||||
{Key: "Plugin-Dependencies", Value: "structs:1.20"},
|
||||
{Key: "Plugin-Developers", Value: ""},
|
||||
{Key: "Plugin-License-Name", Value: "MIT License"},
|
||||
{Key: "Plugin-License-Url", Value: "https://opensource.org/licenses/MIT"},
|
||||
{Key: "Plugin-ScmUrl", Value: "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin"},
|
||||
// extra fields...
|
||||
//"Archiver-Version": "Plexus Archiver",
|
||||
"Plugin-License-Url": "https://opensource.org/licenses/MIT",
|
||||
"Plugin-License-Name": "MIT License",
|
||||
"Created-By": "Maven Archiver 3.6.0",
|
||||
//"Built-By": "?",
|
||||
//"Build-Jdk": "14.0.1",
|
||||
"Build-Jdk-Spec": "18",
|
||||
"Jenkins-Version": "2.204",
|
||||
//"Minimum-Java-Version": "1.8",
|
||||
"Plugin-Developers": "",
|
||||
"Plugin-ScmUrl": "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin",
|
||||
//"Extension-Name": "example-jenkins-plugin",
|
||||
"Short-Name": "example-jenkins-plugin",
|
||||
"Group-Id": "io.jenkins.plugins",
|
||||
"Plugin-Dependencies": "structs:1.20",
|
||||
//"Plugin-Version": "1.0-SNAPSHOT (private-07/09/2020 13:30-?)",
|
||||
"Hudson-Version": "2.204",
|
||||
"Long-Name": "Example Jenkins Plugin",
|
||||
//{Key: "Minimum-Java-Version", Value: "1.8"},
|
||||
//{Key: "Archiver-Version", Value: "Plexus Archiver"},
|
||||
//{Key: "Built-By", Value: "?"},
|
||||
//{Key: "Build-Jdk", Value: "14.0.1"},
|
||||
//{Key: "Extension-Name", Value: "example-jenkins-plugin"},
|
||||
//{Key: "Plugin-Version", Value: "1.0-SNAPSHOT (private-07/09/2020 13:30-?)"},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -255,9 +256,15 @@ func TestParseJar(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-gradle-0.1.0.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Main-Class": "hello.HelloWorld",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
{
|
||||
Key: "Main-Class",
|
||||
Value: "hello.HelloWorld",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -326,14 +333,32 @@ func TestParseJar(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
// extra fields...
|
||||
"Archiver-Version": "Plexus Archiver",
|
||||
"Created-By": "Apache Maven 3.8.6",
|
||||
//"Built-By": "?",
|
||||
//"Build-Jdk": "14.0.1",
|
||||
"Main-Class": "hello.HelloWorld",
|
||||
{
|
||||
Key: "Archiver-Version",
|
||||
Value: "Plexus Archiver",
|
||||
},
|
||||
{
|
||||
Key: "Created-By",
|
||||
Value: "Apache Maven 3.8.6",
|
||||
},
|
||||
//{
|
||||
// Key: "Built-By",
|
||||
// Value: "?",
|
||||
//},
|
||||
//{
|
||||
// Key: "Build-Jdk",
|
||||
// Value: "14.0.1",
|
||||
//},
|
||||
{
|
||||
Key: "Main-Class",
|
||||
Value: "hello.HelloWorld",
|
||||
},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -455,7 +480,14 @@ func TestParseJar(t *testing.T) {
|
||||
// ignore select fields (only works for the main section)
|
||||
for _, field := range test.ignoreExtras {
|
||||
if metadata.Manifest != nil && metadata.Manifest.Main != nil {
|
||||
delete(metadata.Manifest.Main, field)
|
||||
newMain := make(pkg.KeyValues, 0)
|
||||
for i, kv := range metadata.Manifest.Main {
|
||||
if kv.Key == field {
|
||||
continue
|
||||
}
|
||||
newMain = append(newMain, metadata.Manifest.Main[i])
|
||||
}
|
||||
metadata.Manifest.Main = newMain
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1158,32 +1190,32 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/jar-metadata/cache/jackson-core-2.15.2.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Build-Jdk-Spec": "1.8",
|
||||
"Bundle-Description": "Core Jackson processing abstractions",
|
||||
"Bundle-DocURL": "https://github.com/FasterXML/jackson-core",
|
||||
"Bundle-License": "https://www.apache.org/licenses/LICENSE-2.0.txt",
|
||||
"Bundle-ManifestVersion": "2",
|
||||
"Bundle-Name": "Jackson-core",
|
||||
"Bundle-SymbolicName": "com.fasterxml.jackson.core.jackson-core",
|
||||
"Bundle-Vendor": "FasterXML",
|
||||
"Bundle-Version": "2.15.2",
|
||||
"Created-By": "Apache Maven Bundle Plugin 5.1.8",
|
||||
"Export-Package": "com.fasterxml.jackson.core;version...snip",
|
||||
"Implementation-Title": "Jackson-core",
|
||||
"Implementation-Vendor": "FasterXML",
|
||||
"Implementation-Vendor-Id": "com.fasterxml.jackson.core",
|
||||
"Implementation-Version": "2.15.2",
|
||||
"Import-Package": "com.fasterxml.jackson.core;version=...snip",
|
||||
"Manifest-Version": "1.0",
|
||||
"Multi-Release": "true",
|
||||
"Require-Capability": `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`,
|
||||
"Specification-Title": "Jackson-core",
|
||||
"Specification-Vendor": "FasterXML",
|
||||
"Specification-Version": "2.15.2",
|
||||
"Tool": "Bnd-6.3.1.202206071316",
|
||||
"X-Compile-Source-JDK": "1.8",
|
||||
"X-Compile-Target-JDK": "1.8",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
{Key: "Bundle-License", Value: "https://www.apache.org/licenses/LICENSE-2.0.txt"},
|
||||
{Key: "Bundle-SymbolicName", Value: "com.fasterxml.jackson.core.jackson-core"},
|
||||
{Key: "Implementation-Vendor-Id", Value: "com.fasterxml.jackson.core"},
|
||||
{Key: "Specification-Title", Value: "Jackson-core"},
|
||||
{Key: "Bundle-DocURL", Value: "https://github.com/FasterXML/jackson-core"},
|
||||
{Key: "Import-Package", Value: "com.fasterxml.jackson.core;version=...snip"},
|
||||
{Key: "Require-Capability", Value: `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`},
|
||||
{Key: "Export-Package", Value: "com.fasterxml.jackson.core;version...snip"},
|
||||
{Key: "Bundle-Name", Value: "Jackson-core"},
|
||||
{Key: "Multi-Release", Value: "true"},
|
||||
{Key: "Build-Jdk-Spec", Value: "1.8"},
|
||||
{Key: "Bundle-Description", Value: "Core Jackson processing abstractions"},
|
||||
{Key: "Implementation-Title", Value: "Jackson-core"},
|
||||
{Key: "Implementation-Version", Value: "2.15.2"},
|
||||
{Key: "Bundle-ManifestVersion", Value: "2"},
|
||||
{Key: "Specification-Vendor", Value: "FasterXML"},
|
||||
{Key: "Bundle-Vendor", Value: "FasterXML"},
|
||||
{Key: "Tool", Value: "Bnd-6.3.1.202206071316"},
|
||||
{Key: "Implementation-Vendor", Value: "FasterXML"},
|
||||
{Key: "Bundle-Version", Value: "2.15.2"},
|
||||
{Key: "X-Compile-Target-JDK", Value: "1.8"},
|
||||
{Key: "X-Compile-Source-JDK", Value: "1.8"},
|
||||
{Key: "Created-By", Value: "Apache Maven Bundle Plugin 5.1.8"},
|
||||
{Key: "Specification-Version", Value: "2.15.2"},
|
||||
},
|
||||
},
|
||||
// not under test
|
||||
@@ -1212,32 +1244,32 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/jar-metadata/cache/com.fasterxml.jackson.core.jackson-core-2.15.2.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Build-Jdk-Spec": "1.8",
|
||||
"Bundle-Description": "Core Jackson processing abstractions",
|
||||
"Bundle-DocURL": "https://github.com/FasterXML/jackson-core",
|
||||
"Bundle-License": "https://www.apache.org/licenses/LICENSE-2.0.txt",
|
||||
"Bundle-ManifestVersion": "2",
|
||||
"Bundle-Name": "Jackson-core",
|
||||
"Bundle-SymbolicName": "com.fasterxml.jackson.core.jackson-core",
|
||||
"Bundle-Vendor": "FasterXML",
|
||||
"Bundle-Version": "2.15.2",
|
||||
"Created-By": "Apache Maven Bundle Plugin 5.1.8",
|
||||
"Export-Package": "com.fasterxml.jackson.core;version...snip",
|
||||
"Implementation-Title": "Jackson-core",
|
||||
"Implementation-Vendor": "FasterXML",
|
||||
"Implementation-Vendor-Id": "com.fasterxml.jackson.core",
|
||||
"Implementation-Version": "2.15.2",
|
||||
"Import-Package": "com.fasterxml.jackson.core;version=...snip",
|
||||
"Manifest-Version": "1.0",
|
||||
"Multi-Release": "true",
|
||||
"Require-Capability": `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`,
|
||||
"Specification-Title": "Jackson-core",
|
||||
"Specification-Vendor": "FasterXML",
|
||||
"Specification-Version": "2.15.2",
|
||||
"Tool": "Bnd-6.3.1.202206071316",
|
||||
"X-Compile-Source-JDK": "1.8",
|
||||
"X-Compile-Target-JDK": "1.8",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
{Key: "Bundle-License", Value: "https://www.apache.org/licenses/LICENSE-2.0.txt"},
|
||||
{Key: "Bundle-SymbolicName", Value: "com.fasterxml.jackson.core.jackson-core"},
|
||||
{Key: "Implementation-Vendor-Id", Value: "com.fasterxml.jackson.core"},
|
||||
{Key: "Specification-Title", Value: "Jackson-core"},
|
||||
{Key: "Bundle-DocURL", Value: "https://github.com/FasterXML/jackson-core"},
|
||||
{Key: "Import-Package", Value: "com.fasterxml.jackson.core;version=...snip"},
|
||||
{Key: "Require-Capability", Value: `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`},
|
||||
{Key: "Export-Package", Value: "com.fasterxml.jackson.core;version...snip"},
|
||||
{Key: "Bundle-Name", Value: "Jackson-core"},
|
||||
{Key: "Multi-Release", Value: "true"},
|
||||
{Key: "Build-Jdk-Spec", Value: "1.8"},
|
||||
{Key: "Bundle-Description", Value: "Core Jackson processing abstractions"},
|
||||
{Key: "Implementation-Title", Value: "Jackson-core"},
|
||||
{Key: "Implementation-Version", Value: "2.15.2"},
|
||||
{Key: "Bundle-ManifestVersion", Value: "2"},
|
||||
{Key: "Specification-Vendor", Value: "FasterXML"},
|
||||
{Key: "Bundle-Vendor", Value: "FasterXML"},
|
||||
{Key: "Tool", Value: "Bnd-6.3.1.202206071316"},
|
||||
{Key: "Implementation-Vendor", Value: "FasterXML"},
|
||||
{Key: "Bundle-Version", Value: "2.15.2"},
|
||||
{Key: "X-Compile-Target-JDK", Value: "1.8"},
|
||||
{Key: "X-Compile-Source-JDK", Value: "1.8"},
|
||||
{Key: "Created-By", Value: "Apache Maven Bundle Plugin 5.1.8"},
|
||||
{Key: "Specification-Version", Value: "2.15.2"},
|
||||
},
|
||||
},
|
||||
// not under test
|
||||
@@ -1261,11 +1293,23 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/jar-metadata/cache/api-all-2.0.0-sources.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Build-Jdk": "1.8.0_191",
|
||||
"Built-By": "elecharny",
|
||||
"Created-By": "Apache Maven 3.6.0",
|
||||
"Manifest-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
{
|
||||
Key: "Built-By",
|
||||
Value: "elecharny",
|
||||
},
|
||||
{
|
||||
Key: "Created-By",
|
||||
Value: "Apache Maven 3.6.0",
|
||||
},
|
||||
{
|
||||
Key: "Build-Jdk",
|
||||
Value: "1.8.0_191",
|
||||
},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -1314,10 +1358,25 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
|
||||
if tt.assignParent {
|
||||
assignParent(&tt.expectedPkgs[0], tt.expectedPkgs[1:]...)
|
||||
}
|
||||
for i := range tt.expectedPkgs {
|
||||
tt.expectedPkgs[i].SetID()
|
||||
}
|
||||
pkgtest.NewCatalogTester().
|
||||
FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName)).
|
||||
Expects(tt.expectedPkgs, tt.expectedRelationships).
|
||||
WithCompareOptions(cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests")).
|
||||
WithCompareOptions(
|
||||
cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests"),
|
||||
cmp.Comparer(func(x, y pkg.KeyValue) bool {
|
||||
if x.Key != y.Key {
|
||||
return false
|
||||
}
|
||||
if x.Value != y.Value {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}),
|
||||
).
|
||||
TestParser(t, gap.parseJavaArchive)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,8 +24,11 @@ func Test_packageURL(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -49,8 +52,11 @@ func Test_packageURL(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -74,8 +80,11 @@ func Test_packageURL(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -101,8 +110,11 @@ func Test_packageURL(t *testing.T) {
|
||||
Metadata: pkg.JavaArchive{
|
||||
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
PomProperties: &pkg.JavaPomProperties{
|
||||
@@ -163,8 +175,11 @@ func Test_groupIDFromJavaMetadata(t *testing.T) {
|
||||
name: "java manifest",
|
||||
metadata: pkg.JavaArchive{
|
||||
Manifest: &pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Implementation-Vendor": "org.anchore",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Implementation-Vendor",
|
||||
Value: "org.anchore",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
@@ -20,7 +19,7 @@ const manifestGlob = "/META-INF/MANIFEST.MF"
|
||||
//nolint:funlen
|
||||
func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error) {
|
||||
var manifest pkg.JavaManifest
|
||||
var sections []map[string]string
|
||||
sections := make([]pkg.KeyValues, 0)
|
||||
|
||||
currentSection := func() int {
|
||||
return len(sections) - 1
|
||||
@@ -51,7 +50,9 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
|
||||
continue
|
||||
}
|
||||
|
||||
sections[currentSection()][lastKey] += strings.TrimSpace(line)
|
||||
lastSection := sections[currentSection()]
|
||||
|
||||
sections[currentSection()][len(lastSection)-1].Value += strings.TrimSpace(line)
|
||||
|
||||
continue
|
||||
}
|
||||
@@ -73,10 +74,13 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
|
||||
|
||||
if lastKey == "" {
|
||||
// we're entering a new section
|
||||
sections = append(sections, make(map[string]string))
|
||||
sections = append(sections, make(pkg.KeyValues, 0))
|
||||
}
|
||||
|
||||
sections[currentSection()][key] = value
|
||||
sections[currentSection()] = append(sections[currentSection()], pkg.KeyValue{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
|
||||
// keep track of key for potential future continuations
|
||||
lastKey = key
|
||||
@@ -89,20 +93,7 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
|
||||
if len(sections) > 0 {
|
||||
manifest.Main = sections[0]
|
||||
if len(sections) > 1 {
|
||||
manifest.NamedSections = make(map[string]map[string]string)
|
||||
for i, s := range sections[1:] {
|
||||
name, ok := s["Name"]
|
||||
if !ok {
|
||||
// per the manifest spec (https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#jar-manifest)
|
||||
// this should never happen. If it does, we want to know about it, but not necessarily stop
|
||||
// cataloging entirely... for this reason we only log.
|
||||
log.Debugf("java manifest section found without a name: %s", path)
|
||||
name = strconv.Itoa(i)
|
||||
} else {
|
||||
delete(s, "Name")
|
||||
}
|
||||
manifest.NamedSections[name] = s
|
||||
}
|
||||
manifest.Sections = sections[1:]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,12 +118,12 @@ func extractNameFromApacheMavenBundlePlugin(manifest *pkg.JavaManifest) string {
|
||||
// The computed symbolic name is also stored in the $(maven-symbolicname) property in case you want to add attributes or directives to it.
|
||||
//
|
||||
if manifest != nil {
|
||||
if strings.Contains(manifest.Main["Created-By"], "Apache Maven Bundle Plugin") {
|
||||
if symbolicName := manifest.Main["Bundle-SymbolicName"]; symbolicName != "" {
|
||||
if strings.Contains(manifest.Main.MustGet("Created-By"), "Apache Maven Bundle Plugin") {
|
||||
if symbolicName := manifest.Main.MustGet("Bundle-SymbolicName"); symbolicName != "" {
|
||||
// It is possible that `Bundle-SymbolicName` is just the groupID (like in the case of
|
||||
// https://repo1.maven.org/maven2/com/google/oauth-client/google-oauth-client/1.25.0/google-oauth-client-1.25.0.jar),
|
||||
// so if `Implementation-Vendor-Id` is equal to `Bundle-SymbolicName`, bail on this logic
|
||||
if vendorID := manifest.Main["Implementation-Vendor-Id"]; vendorID != "" && vendorID == symbolicName {
|
||||
if vendorID := manifest.Main.MustGet("Implementation-Vendor-Id"); vendorID != "" && vendorID == symbolicName {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -212,21 +203,21 @@ func selectName(manifest *pkg.JavaManifest, filenameObj archiveFilename) string
|
||||
// remaining fields in the manifest is a bit of a free-for-all depending on the build tooling used and package maintainer preferences
|
||||
if manifest != nil {
|
||||
switch {
|
||||
case manifest.Main["Name"] != "":
|
||||
case manifest.Main.MustGet("Name") != "":
|
||||
// Manifest original spec...
|
||||
return manifest.Main["Name"]
|
||||
case manifest.Main["Bundle-Name"] != "":
|
||||
return manifest.Main.MustGet("Name")
|
||||
case manifest.Main.MustGet("Bundle-Name") != "":
|
||||
// BND tooling... TODO: this does not seem accurate (I don't see a reference in the BND tooling docs for this)
|
||||
return manifest.Main["Bundle-Name"]
|
||||
case manifest.Main["Short-Name"] != "":
|
||||
return manifest.Main.MustGet("Bundle-Name")
|
||||
case manifest.Main.MustGet("Short-Name") != "":
|
||||
// Jenkins...
|
||||
return manifest.Main["Short-Name"]
|
||||
case manifest.Main["Extension-Name"] != "":
|
||||
return manifest.Main.MustGet("Short-Name")
|
||||
case manifest.Main.MustGet("Extension-Name") != "":
|
||||
// Jenkins...
|
||||
return manifest.Main["Extension-Name"]
|
||||
case manifest.Main["Implementation-Title"] != "":
|
||||
return manifest.Main.MustGet("Extension-Name")
|
||||
case manifest.Main.MustGet("Implementation-Title") != "":
|
||||
// last ditch effort...
|
||||
return manifest.Main["Implementation-Title"]
|
||||
return manifest.Main.MustGet("Implementation-Title")
|
||||
}
|
||||
}
|
||||
return ""
|
||||
@@ -278,12 +269,12 @@ func selectLicenses(manifest *pkg.JavaManifest) []string {
|
||||
}
|
||||
|
||||
func fieldValueFromManifest(manifest pkg.JavaManifest, fieldName string) string {
|
||||
if value := manifest.Main[fieldName]; value != "" {
|
||||
if value := manifest.Main.MustGet(fieldName); value != "" {
|
||||
return value
|
||||
}
|
||||
|
||||
for _, section := range manifest.NamedSections {
|
||||
if value := section[fieldName]; value != "" {
|
||||
for _, section := range manifest.Sections {
|
||||
if value := section.MustGet(fieldName); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,41 +19,63 @@ func TestParseJavaManifest(t *testing.T) {
|
||||
{
|
||||
fixture: "test-fixtures/manifest/small",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/manifest/standard-info",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Name": "the-best-name",
|
||||
"Manifest-Version": "1.0",
|
||||
"Specification-Title": "the-spec-title",
|
||||
"Specification-Version": "the-spec-version",
|
||||
"Specification-Vendor": "the-spec-vendor",
|
||||
"Implementation-Title": "the-impl-title",
|
||||
"Implementation-Version": "the-impl-version",
|
||||
"Implementation-Vendor": "the-impl-vendor",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
{Key: "Name", Value: "the-best-name"},
|
||||
{Key: "Specification-Title", Value: "the-spec-title"},
|
||||
{Key: "Specification-Vendor", Value: "the-spec-vendor"},
|
||||
{Key: "Specification-Version", Value: "the-spec-version"},
|
||||
{Key: "Implementation-Title", Value: "the-impl-title"},
|
||||
{Key: "Implementation-Vendor", Value: "the-impl-vendor"},
|
||||
{Key: "Implementation-Version", Value: "the-impl-version"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/manifest/extra-info",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Archiver-Version": "Plexus Archiver",
|
||||
"Created-By": "Apache Maven 3.6.3",
|
||||
},
|
||||
NamedSections: map[string]map[string]string{
|
||||
"thing-1": {
|
||||
"Built-By": "?",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
"1": {
|
||||
"Build-Jdk": "14.0.1",
|
||||
"Main-Class": "hello.HelloWorld",
|
||||
{
|
||||
Key: "Archiver-Version",
|
||||
Value: "Plexus Archiver",
|
||||
},
|
||||
{
|
||||
Key: "Created-By",
|
||||
Value: "Apache Maven 3.6.3",
|
||||
},
|
||||
},
|
||||
Sections: []pkg.KeyValues{
|
||||
{
|
||||
{
|
||||
Key: "Name",
|
||||
Value: "thing-1",
|
||||
},
|
||||
{
|
||||
Key: "Built-By",
|
||||
Value: "?",
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
Key: "Build-Jdk",
|
||||
Value: "14.0.1",
|
||||
},
|
||||
{
|
||||
Key: "Main-Class",
|
||||
Value: "hello.HelloWorld",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -61,23 +83,34 @@ func TestParseJavaManifest(t *testing.T) {
|
||||
{
|
||||
fixture: "test-fixtures/manifest/extra-empty-lines",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Archiver-Version": "Plexus Archiver",
|
||||
"Created-By": "Apache Maven 3.6.3",
|
||||
Main: pkg.KeyValues{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
{
|
||||
Key: "Archiver-Version",
|
||||
Value: "Plexus Archiver",
|
||||
},
|
||||
{
|
||||
Key: "Created-By",
|
||||
Value: "Apache Maven 3.6.3",
|
||||
},
|
||||
},
|
||||
NamedSections: map[string]map[string]string{
|
||||
"thing-1": {
|
||||
"Built-By": "?",
|
||||
Sections: []pkg.KeyValues{
|
||||
{
|
||||
{Key: "Name", Value: "thing-1"},
|
||||
{Key: "Built-By", Value: "?"},
|
||||
},
|
||||
"thing-2": {
|
||||
"Built-By": "someone!",
|
||||
{
|
||||
{Key: "Name", Value: "thing-2"},
|
||||
{Key: "Built-By", Value: "someone!"},
|
||||
},
|
||||
"2": {
|
||||
"Other": "things",
|
||||
{
|
||||
{Key: "Other", Value: "things"},
|
||||
},
|
||||
"3": {
|
||||
"Last": "item",
|
||||
{
|
||||
{Key: "Last", Value: "item"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -85,9 +118,15 @@ func TestParseJavaManifest(t *testing.T) {
|
||||
{
|
||||
fixture: "test-fixtures/manifest/continuation",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Plugin-ScmUrl": "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin",
|
||||
Main: pkg.KeyValues{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
{
|
||||
Key: "Plugin-ScmUrl",
|
||||
Value: "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -95,9 +134,15 @@ func TestParseJavaManifest(t *testing.T) {
|
||||
// regression test, we should always keep the full version
|
||||
fixture: "test-fixtures/manifest/version-with-date",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Implementation-Version": "1.3 2244 October 5 2005",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
{
|
||||
Key: "Implementation-Version",
|
||||
Value: "1.3 2244 October 5 2005",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -106,9 +151,15 @@ func TestParseJavaManifest(t *testing.T) {
|
||||
// https://github.com/anchore/syft/issues/2179
|
||||
fixture: "test-fixtures/manifest/leading-space",
|
||||
expected: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Key-keykeykey": "initialconfig:com$ # aka not empty line",
|
||||
"should": "parse",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Key-keykeykey",
|
||||
Value: "initialconfig:com$ # aka not empty line",
|
||||
},
|
||||
{
|
||||
Key: "should",
|
||||
Value: "parse",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -154,8 +205,11 @@ func TestSelectName(t *testing.T) {
|
||||
desc: "Get name from Implementation-Title",
|
||||
archive: archiveFilename{},
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Implementation-Title": "maven-wrapper",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Implementation-Title",
|
||||
Value: "maven-wrapper",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "maven-wrapper",
|
||||
@@ -163,9 +217,15 @@ func TestSelectName(t *testing.T) {
|
||||
{
|
||||
desc: "Implementation-Title does not override name from filename",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Name": "foo",
|
||||
"Implementation-Title": "maven-wrapper",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Name",
|
||||
Value: "foo",
|
||||
},
|
||||
{
|
||||
Key: "Implementation-Title",
|
||||
Value: "maven-wrapper",
|
||||
},
|
||||
},
|
||||
},
|
||||
archive: newJavaArchiveFilename("/something/omg.jar"),
|
||||
@@ -174,11 +234,11 @@ func TestSelectName(t *testing.T) {
|
||||
{
|
||||
desc: "Use the artifact ID baked by the Apache Maven Bundle Plugin",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Created-By": "Apache Maven Bundle Plugin",
|
||||
"Bundle-SymbolicName": "com.atlassian.gadgets.atlassian-gadgets-api",
|
||||
"Name": "foo",
|
||||
"Implementation-Title": "maven-wrapper",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Created-By", Value: "Apache Maven Bundle Plugin"},
|
||||
{Key: "Bundle-SymbolicName", Value: "com.atlassian.gadgets.atlassian-gadgets-api"},
|
||||
{Key: "Name", Value: "foo"},
|
||||
{Key: "Implementation-Title", Value: "maven-wrapper"},
|
||||
},
|
||||
},
|
||||
archive: newJavaArchiveFilename("/something/omg.jar"),
|
||||
@@ -188,11 +248,11 @@ func TestSelectName(t *testing.T) {
|
||||
// example: pkg:maven/org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-beans@5.3.26_1
|
||||
desc: "Apache Maven Bundle Plugin might bake a version in the created-by field",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Created-By": "Apache Maven Bundle Plugin 5.1.6",
|
||||
"Bundle-SymbolicName": "com.atlassian.gadgets.atlassian-gadgets-api",
|
||||
"Name": "foo",
|
||||
"Implementation-Title": "maven-wrapper",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Created-By", Value: "Apache Maven Bundle Plugin 5.1.6"},
|
||||
{Key: "Bundle-SymbolicName", Value: "com.atlassian.gadgets.atlassian-gadgets-api"},
|
||||
{Key: "Name", Value: "foo"},
|
||||
{Key: "Implementation-Title", Value: "maven-wrapper"},
|
||||
},
|
||||
},
|
||||
archive: newJavaArchiveFilename("/something/omg.jar"),
|
||||
@@ -201,9 +261,15 @@ func TestSelectName(t *testing.T) {
|
||||
{
|
||||
desc: "Filename looks like a groupid + artifact id",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Name": "foo",
|
||||
"Implementation-Title": "maven-wrapper",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Name",
|
||||
Value: "foo",
|
||||
},
|
||||
{
|
||||
Key: "Implementation-Title",
|
||||
Value: "maven-wrapper",
|
||||
},
|
||||
},
|
||||
},
|
||||
archive: newJavaArchiveFilename("/something/com.atlassian.gadgets.atlassian-gadgets-api.jar"),
|
||||
@@ -228,8 +294,11 @@ func TestSelectName(t *testing.T) {
|
||||
{
|
||||
desc: "Skip stripping groupId prefix from archive filename for org.eclipse",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Automatic-Module-Name": "org.eclipse.ant.core",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Automatic-Module-Name",
|
||||
Value: "org.eclipse.ant.core",
|
||||
},
|
||||
},
|
||||
},
|
||||
archive: newJavaArchiveFilename("/something/org.eclipse.ant.core-3.7.0.jar"),
|
||||
@@ -239,21 +308,21 @@ func TestSelectName(t *testing.T) {
|
||||
// example: pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0
|
||||
desc: "skip Apache Maven Bundle Plugin logic if symbolic name is same as vendor id",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Bundle-DocURL": "http://www.google.com/",
|
||||
"Bundle-License": "http://www.apache.org/licenses/LICENSE-2.0.txt",
|
||||
"Bundle-ManifestVersion": "2",
|
||||
"Bundle-Name": "Google OAuth Client Library for Java",
|
||||
"Bundle-RequiredExecutionEnvironment": "JavaSE-1.6",
|
||||
"Bundle-SymbolicName": "com.google.oauth-client",
|
||||
"Bundle-Vendor": "Google",
|
||||
"Bundle-Version": "1.25.0",
|
||||
"Created-By": "Apache Maven Bundle Plugin",
|
||||
"Export-Package": "com.google.api.client.auth.openidconnect;uses:=\"com.google.api.client.auth.oauth2,com.google.api.client.json,com.google.api.client.json.webtoken,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth;uses:=\"com.google.api.client.http,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth2;uses:=\"com.google.api.client.http,com.google.api.client.json,com.google.api.client.util,com.google.api.client.util.store\";version=\"1.25.0\"",
|
||||
"Implementation-Title": "Google OAuth Client Library for Java",
|
||||
"Implementation-Vendor": "Google",
|
||||
"Implementation-Vendor-Id": "com.google.oauth-client",
|
||||
"Implementation-Version": "1.25.0",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Bundle-DocURL", Value: "http://www.google.com/"},
|
||||
{Key: "Bundle-License", Value: "http://www.apache.org/licenses/LICENSE-2.0.txt"},
|
||||
{Key: "Bundle-ManifestVersion", Value: "2"},
|
||||
{Key: "Bundle-Name", Value: "Google OAuth Client Library for Java"},
|
||||
{Key: "Bundle-RequiredExecutionEnvironment", Value: "JavaSE-1.6"},
|
||||
{Key: "Bundle-SymbolicName", Value: "com.google.oauth-client"},
|
||||
{Key: "Bundle-Vendor", Value: "Google"},
|
||||
{Key: "Bundle-Version", Value: "1.25.0"},
|
||||
{Key: "Created-By", Value: "Apache Maven Bundle Plugin"},
|
||||
{Key: "Export-Package", Value: "com.google.api.client.auth.openidconnect;uses:=\"com.google.api.client.auth.oauth2,com.google.api.client.json,com.google.api.client.json.webtoken,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth;uses:=\"com.google.api.client.http,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth2;uses:=\"com.google.api.client.http,com.google.api.client.json,com.google.api.client.util,com.google.api.client.util.store\";version=\"1.25.0\""},
|
||||
{Key: "Implementation-Title", Value: "Google OAuth Client Library for Java"},
|
||||
{Key: "Implementation-Vendor", Value: "Google"},
|
||||
{Key: "Implementation-Vendor-Id", Value: "com.google.oauth-client"},
|
||||
{Key: "Implementation-Version", Value: "1.25.0"},
|
||||
},
|
||||
},
|
||||
archive: newJavaArchiveFilename("/something/google-oauth-client-1.25.0.jar"),
|
||||
@@ -283,8 +352,11 @@ func TestSelectVersion(t *testing.T) {
|
||||
name: "Get name from Implementation-Version",
|
||||
archive: archiveFilename{},
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Implementation-Version": "1.8.2",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Implementation-Version",
|
||||
Value: "1.8.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "1.8.2",
|
||||
@@ -292,9 +364,15 @@ func TestSelectVersion(t *testing.T) {
|
||||
{
|
||||
name: "Implementation-Version takes precedence over Specification-Version",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Implementation-Version": "1.8.2",
|
||||
"Specification-Version": "1.0",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Implementation-Version",
|
||||
Value: "1.8.2",
|
||||
},
|
||||
{
|
||||
Key: "Specification-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "1.8.2",
|
||||
@@ -302,14 +380,15 @@ func TestSelectVersion(t *testing.T) {
|
||||
{
|
||||
name: "Implementation-Version found outside the main section",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Ant-Version": "Apache Ant 1.8.2",
|
||||
"Created-By": "1.5.0_22-b03 (Sun Microsystems Inc.)",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
{Key: "Ant-Version", Value: "Apache Ant 1.8.2"},
|
||||
{Key: "Created-By", Value: "1.5.0_22-b03 (Sun Microsystems Inc.)"},
|
||||
},
|
||||
NamedSections: map[string]map[string]string{
|
||||
"org/apache/tools/ant/taskdefs/optional/": {
|
||||
"Implementation-Version": "1.8.2",
|
||||
Sections: []pkg.KeyValues{
|
||||
{
|
||||
{Key: "Name", Value: "org/apache/tools/ant/taskdefs/optional/"},
|
||||
{Key: "Implementation-Version", Value: "1.8.2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -318,34 +397,53 @@ func TestSelectVersion(t *testing.T) {
|
||||
{
|
||||
name: "Implementation-Version takes precedence over Specification-Version in subsequent section",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Ant-Version": "Apache Ant 1.8.2",
|
||||
"Created-By": "1.5.0_22-b03 (Sun Microsystems Inc.)",
|
||||
"Specification-Version": "2.0",
|
||||
Main: pkg.KeyValues{
|
||||
{Key: "Manifest-Version", Value: "1.0"},
|
||||
{Key: "Ant-Version", Value: "Apache Ant 1.8.2"},
|
||||
{Key: "Created-By", Value: "1.5.0_22-b03 (Sun Microsystems Inc.)"},
|
||||
{Key: "Specification-Version", Value: "2.0"},
|
||||
},
|
||||
NamedSections: map[string]map[string]string{
|
||||
"org/apache/tools/ant/taskdefs/optional/": {
|
||||
"Specification-Version": "1.8",
|
||||
Sections: []pkg.KeyValues{
|
||||
{
|
||||
{Key: "Name", Value: "org/apache/tools/ant/taskdefs/optional/"},
|
||||
{Key: "Specification-Version", Value: "1.8"},
|
||||
},
|
||||
"some-other-section": {
|
||||
"Implementation-Version": "1.8.2",
|
||||
{
|
||||
{Key: "Name", Value: "some-other-section"},
|
||||
{Key: "Implementation-Version", Value: "1.8.2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
expected: "1.8.2",
|
||||
},
|
||||
{
|
||||
name: "Implementation-Version takes precedence over Specification-Version in subsequent section",
|
||||
manifest: pkg.JavaManifest{
|
||||
Main: map[string]string{
|
||||
"Manifest-Version": "1.0",
|
||||
"Ant-Version": "Apache Ant 1.8.2",
|
||||
"Created-By": "1.5.0_22-b03 (Sun Microsystems Inc.)",
|
||||
Main: []pkg.KeyValue{
|
||||
{
|
||||
Key: "Manifest-Version",
|
||||
Value: "1.0",
|
||||
},
|
||||
{
|
||||
Key: "Ant-Version",
|
||||
Value: "Apache Ant 1.8.2",
|
||||
},
|
||||
{
|
||||
Key: "Created-By",
|
||||
Value: "1.5.0_22-b03 (Sun Microsystems Inc.)",
|
||||
},
|
||||
},
|
||||
NamedSections: map[string]map[string]string{
|
||||
"some-other-section": {
|
||||
"Bundle-Version": "1.11.28",
|
||||
Sections: []pkg.KeyValues{
|
||||
{
|
||||
{
|
||||
Key: "Name",
|
||||
Value: "some-other-section",
|
||||
},
|
||||
{
|
||||
Key: "Bundle-Version",
|
||||
Value: "1.11.28",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user