Fix: unmarshal key values in Java, Go, and Conan metadata (#2603)

Previously, Syft represented several metadata fields as map[string]string,
however this representation erased ordering, so Syft now represents these values
as []KeyValue. Add custom unmarshaling so that JSON that was written by
older versions of Syft using the map[string]string representation can be parsed
into the new []KeyValue representation.

Signed-off-by: Will Murphy <will.murphy@anchore.com>
This commit is contained in:
William Murphy
2024-02-07 11:26:23 -05:00
committed by GitHub
parent bbd34f61fd
commit ce67927a98
5 changed files with 340 additions and 1 deletions
+56
View File
@@ -1,6 +1,9 @@
package pkg
import (
"encoding/json"
"fmt"
"sort"
"strings"
"github.com/anchore/syft/internal"
@@ -70,6 +73,59 @@ type JavaManifest struct {
Sections []KeyValues `json:"sections,omitempty"`
}
type unmarshalJavaManifest JavaManifest
type legacyJavaManifest struct {
Main map[string]string `json:"main"`
NamedSections map[string]map[string]string `json:"namedSections"`
}
func (m *JavaManifest) UnmarshalJSON(b []byte) error {
var either map[string]any
err := json.Unmarshal(b, &either)
if err != nil {
return fmt.Errorf("could not unmarshal java manifest: %w", err)
}
if _, ok := either["namedSections"]; ok {
var lm legacyJavaManifest
if err = json.Unmarshal(b, &lm); err != nil {
return fmt.Errorf("could not unmarshal java manifest: %w", err)
}
*m = lm.toNewManifest()
return nil
}
var jm unmarshalJavaManifest
err = json.Unmarshal(b, &jm)
if err != nil {
return fmt.Errorf("could not unmarshal java manifest: %w", err)
}
*m = JavaManifest(jm)
return nil
}
func (lm legacyJavaManifest) toNewManifest() JavaManifest {
var result JavaManifest
result.Main = keyValuesFromMap(lm.Main)
var sectionNames []string
for k := range lm.NamedSections {
sectionNames = append(sectionNames, k)
}
sort.Strings(sectionNames)
var sections []KeyValues
for _, name := range sectionNames {
section := KeyValues{
KeyValue{
Key: "Name",
Value: name,
},
}
section = append(section, keyValuesFromMap(lm.NamedSections[name])...)
sections = append(sections, section)
}
result.Sections = sections
return result
}
func (m JavaManifest) Section(name string) KeyValues {
for _, section := range m.Sections {
if sectionName, ok := section.Get("Name"); ok && sectionName == name {