Skip to content

Commit

Permalink
Abstract SPDX version from the go parser
Browse files Browse the repository at this point in the history
This is an improvement of the usage of tools-golang where there's
no version abstraction and all methods and types are duplicates.
It's still restricted by the parser's interface and in the best
case the abstraction should be implemented in tools-golang and
the adopting approach should be updated once again

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
ivanayov committed Dec 2, 2022

Verified

This commit was signed with the committer’s verified signature.
thanoulis Thanos Zygouris
1 parent 4c8f1ec commit d50cbec
Showing 5 changed files with 145 additions and 79 deletions.
32 changes: 17 additions & 15 deletions parser/build.go
Original file line number Diff line number Diff line change
@@ -9,29 +9,31 @@ import (
"github.com/spdx/tools-golang/builder"
)

func Build(dirRoot string, conf *Config) (*Document, error) {
spdxDocRef, err := builder.Build2_2(conf.PackageName, dirRoot, conf.SPDXConfigRef)
if err != nil {
fmt.Printf("error while building spdx document reference for path %v with config %v, %v: %v\n", dirRoot, conf.PackageName, conf.SPDXConfigRef, err)
}
func Build(spdxVersion string, dirRoot string, conf *Config) (*Document, error) {
spdxDocRef := BuildVersion(spdxVersion, dirRoot, conf)

for i := range spdxDocRef.Packages {
if spdxDocRef.Packages[i].PackageName == conf.PackageName &&
len(spdxDocRef.Packages[i].PackageVersion) == 0 {
spdxDocRef.Packages[i].PackageVersion = conf.PackageVersion
UpdatePackages(SPDX_VERSION, &spdxDocRef, conf)
doc := CreateDocument(&spdxDocRef, conf)
return doc, nil
}

func BuildVersion(spdxVersion string, dirRoot string, conf *Config) SPDXDocRef {
res := SPDXDocRef{}
switch spdxVersion {
case "2.2":
var err error
res.Doc2_2, err = builder.Build2_2(conf.PackageName, dirRoot, conf.SPDXConfigRef)
if err != nil {
fmt.Printf("error while building spdx document reference for path %v with config %v, %v: %v\n", dirRoot, conf.PackageName, conf.SPDXConfigRef, err)
}
}
doc := &Document{
SPDXDocRef: spdxDocRef,
ConfigDataRef: conf,
}
return doc, nil
return res
}

func GenerateComposedDoc(dirRoot string, output string, outFormat string, confFile string) error {
conf := LoadConfig(confFile)

doc, err := Build(dirRoot, conf)
doc, err := Build(SPDX_VERSION, dirRoot, conf)
if err != nil {
return err
}
27 changes: 14 additions & 13 deletions parser/build_test.go
Original file line number Diff line number Diff line change
@@ -29,13 +29,14 @@ packageSupplier: "somesupplier"
packageComment: "<text>somecomment</text>"`)

want := Document{
SPDXDocRef: &spdx.Document2_2{
SPDXVersion: "SPDX-2.2",
DataLicense: "CC0-1.0",
SPDXIdentifier: "DOCUMENT",
DocumentName: "top-level-artifact",
DocumentNamespace: "https://spdx.org/spdxdocs/top-level-artifact-",
},
SPDXDocRef: &SPDXDocRef{
Doc2_2: &spdx.Document2_2{
SPDXVersion: "SPDX-2.2",
DataLicense: "CC0-1.0",
SPDXIdentifier: "DOCUMENT",
DocumentName: "top-level-artifact",
DocumentNamespace: "https://spdx.org/spdxdocs/top-level-artifact-",
}},
ConfigDataRef: &Config{
SPDXConfigRef: SPDXConfigReference,
PackageName: "top-level-artifact",
@@ -56,14 +57,14 @@ packageComment: "<text>somecomment</text>"`)
}

loadedConfig := createConfig(input)
doc, err := Build("../example_data/micro_sboms/tag_value", loadedConfig)
doc, err := Build(SPDX_VERSION, "../example_data/micro_sboms/tag_value", loadedConfig)
assert.Equal(t, nil, err)

assert.Equal(t, want.SPDXDocRef.SPDXVersion, doc.SPDXDocRef.SPDXVersion)
assert.Equal(t, want.SPDXDocRef.DataLicense, doc.SPDXDocRef.DataLicense)
assert.Equal(t, want.SPDXDocRef.SPDXIdentifier, doc.SPDXDocRef.SPDXIdentifier)
assert.Equal(t, want.SPDXDocRef.DocumentName, doc.SPDXDocRef.DocumentName)
assert.Contains(t, doc.SPDXDocRef.DocumentNamespace, want.SPDXDocRef.DocumentNamespace)
assert.Equal(t, want.SPDXDocRef.Doc2_2.SPDXVersion, doc.SPDXDocRef.Doc2_2.SPDXVersion)
assert.Equal(t, want.SPDXDocRef.Doc2_2.DataLicense, doc.SPDXDocRef.Doc2_2.DataLicense)
assert.Equal(t, want.SPDXDocRef.Doc2_2.SPDXIdentifier, doc.SPDXDocRef.Doc2_2.SPDXIdentifier)
assert.Equal(t, want.SPDXDocRef.Doc2_2.DocumentName, doc.SPDXDocRef.Doc2_2.DocumentName)
assert.Contains(t, doc.SPDXDocRef.Doc2_2.DocumentNamespace, want.SPDXDocRef.Doc2_2.DocumentNamespace)
assert.Equal(t, want.ConfigDataRef.DocumentName, doc.ConfigDataRef.DocumentName)
assert.Equal(t, want.ConfigDataRef.SPDXID, doc.ConfigDataRef.SPDXID)
assert.Equal(t, want.ConfigDataRef.PackageVersion, doc.ConfigDataRef.PackageVersion)
33 changes: 32 additions & 1 deletion parser/document.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,37 @@ package parser
import "github.com/spdx/tools-golang/spdx"

type Document struct {
SPDXDocRef *spdx.Document2_2
SPDXDocRef *SPDXDocRef
ConfigDataRef *Config
}
type SPDXDocRef struct {
Doc2_2 *spdx.Document2_2
}

func CreateDocument(spdxDocRef *SPDXDocRef, conf *Config) *Document {
doc := &Document{
SPDXDocRef: spdxDocRef,
ConfigDataRef: conf,
}
return doc
}

func CreateDocumentWithSPDXRef() *Document {
spdxDocRef := &SPDXDocRef{Doc2_2: &spdx.Document2_2{}}
doc := &Document{
SPDXDocRef: spdxDocRef,
}
return doc
}

func UpdatePackages(spdxVersion string, spdxDocRef *SPDXDocRef, conf *Config) {
switch spdxVersion {
case "2.2":
for i := range spdxDocRef.Doc2_2.Packages {
if spdxDocRef.Doc2_2.Packages[i].PackageName == conf.PackageName &&
len(spdxDocRef.Doc2_2.Packages[i].PackageVersion) == 0 {
spdxDocRef.Doc2_2.Packages[i].PackageVersion = conf.PackageVersion
}
}
}
}
8 changes: 4 additions & 4 deletions parser/load.go
Original file line number Diff line number Diff line change
@@ -22,12 +22,12 @@ func LoadFile(file string) *Document {

res := &Document{}

doc := &Document{}
doc := CreateDocumentWithSPDXRef()

if isJSON(file) {
doc.SPDXDocRef, err = spdx_json.Load2_2(r)
doc.SPDXDocRef.Doc2_2, err = spdx_json.Load2_2(r)
} else {
doc.SPDXDocRef, err = tvloader.Load2_2(r)
doc.SPDXDocRef.Doc2_2, err = tvloader.Load2_2(r)
}

if err != nil {
@@ -36,7 +36,7 @@ func LoadFile(file string) *Document {
}

// verify if the SPDX file describes at least one package
pkgIDs, err := spdxlib.GetDescribedPackageIDs2_2(doc.SPDXDocRef)
pkgIDs, err := spdxlib.GetDescribedPackageIDs2_2(doc.SPDXDocRef.Doc2_2)
if err != nil {
fmt.Printf("couldn't find package description in the SPDX document: %v\n", err)
return nil
124 changes: 78 additions & 46 deletions parser/save.go
Original file line number Diff line number Diff line change
@@ -13,6 +13,9 @@ import (
"github.com/spdx/tools-golang/tvsaver"
)

// TODO: Make configurable
var SPDX_VERSION = "2.2"

func Save(doc *Document, composableDocs []*Document, output string, outFormat string) error {

output = updateFileExtension(output, outFormat)
@@ -26,81 +29,110 @@ func Save(doc *Document, composableDocs []*Document, output string, outFormat st

// It's not necessary for the composed doc to
// contain all merged documents as Files
doc = cleanDocumentFileData(doc)
doc = cleanDocumentFileData(SPDX_VERSION, doc)

updateRelationships(doc, composableDocs)
updateRelationships(SPDX_VERSION, doc, composableDocs)

for _, cdoc := range composableDocs {
if cdoc != nil {
AppendComposableDocument(doc, cdoc, w, outFormat)
AppendComposableDocument(SPDX_VERSION, doc, cdoc, w, outFormat)
}
}

switch outFormat {
case "tv":
err = tvsaver.Save2_2(doc.SPDXDocRef, w)
case "json":
err = spdx_json.Save2_2(doc.SPDXDocRef, w)
default:
fmt.Printf("warn: %s is not proper output format; saving to default\n", outFormat)
err = tvsaver.Save2_2(doc.SPDXDocRef, w)
}
err = SaveVersion(SPDX_VERSION, outFormat, doc, w)
if err != nil {
fmt.Printf("error while saving %v: %v\n", output, err)
return err
}
return nil
}

func SaveVersion(version string, format string, doc *Document, w *os.File) error {
switch format {
case "tv":
if version == "2.2" {
return tvsaver.Save2_2(doc.SPDXDocRef.Doc2_2, w)
}
case "json":
if version == "2.2" {
return spdx_json.Save2_2(doc.SPDXDocRef.Doc2_2, w)
}
default:
fmt.Printf("warn: %s is not proper output format; saving to default\n", format)
if version == "2.2" {
return tvsaver.Save2_2(doc.SPDXDocRef.Doc2_2, w)
}
}

return nil
}

// RenderComposableDocument processes a composable document
// and renders it to the composed document
func AppendComposableDocument(res *Document, cdoc *Document, w io.Writer, outFormat string) {

res.SPDXDocRef.Annotations = append(res.SPDXDocRef.Annotations, cdoc.SPDXDocRef.Annotations...)
res.SPDXDocRef.ExternalDocumentReferences = append(res.SPDXDocRef.ExternalDocumentReferences, cdoc.SPDXDocRef.ExternalDocumentReferences...)
res.SPDXDocRef.Files = append(res.SPDXDocRef.Files, cdoc.SPDXDocRef.Files...)
res.SPDXDocRef.OtherLicenses = append(res.SPDXDocRef.OtherLicenses, cdoc.SPDXDocRef.OtherLicenses...)
res.SPDXDocRef.Packages = append(res.SPDXDocRef.Packages, cdoc.SPDXDocRef.Packages...)
res.SPDXDocRef.Relationships = append(res.SPDXDocRef.Relationships, cdoc.SPDXDocRef.Relationships...)
res.SPDXDocRef.Reviews = append(res.SPDXDocRef.Reviews, cdoc.SPDXDocRef.Reviews...)
res.SPDXDocRef.Snippets = append(res.SPDXDocRef.Snippets, cdoc.SPDXDocRef.Snippets...)
func AppendComposableDocument(spdxVersion string, res *Document, cdoc *Document, w io.Writer, outFormat string) {

switch spdxVersion {
case "2.2":
res.SPDXDocRef.Doc2_2.Annotations = append(res.SPDXDocRef.Doc2_2.Annotations, cdoc.SPDXDocRef.Doc2_2.Annotations...)
res.SPDXDocRef.Doc2_2.ExternalDocumentReferences = append(res.SPDXDocRef.Doc2_2.ExternalDocumentReferences, cdoc.SPDXDocRef.Doc2_2.ExternalDocumentReferences...)
res.SPDXDocRef.Doc2_2.Files = append(res.SPDXDocRef.Doc2_2.Files, cdoc.SPDXDocRef.Doc2_2.Files...)
res.SPDXDocRef.Doc2_2.OtherLicenses = append(res.SPDXDocRef.Doc2_2.OtherLicenses, cdoc.SPDXDocRef.Doc2_2.OtherLicenses...)
res.SPDXDocRef.Doc2_2.Packages = append(res.SPDXDocRef.Doc2_2.Packages, cdoc.SPDXDocRef.Doc2_2.Packages...)
res.SPDXDocRef.Doc2_2.Relationships = append(res.SPDXDocRef.Doc2_2.Relationships, cdoc.SPDXDocRef.Doc2_2.Relationships...)
res.SPDXDocRef.Doc2_2.Reviews = append(res.SPDXDocRef.Doc2_2.Reviews, cdoc.SPDXDocRef.Doc2_2.Reviews...)
res.SPDXDocRef.Doc2_2.Snippets = append(res.SPDXDocRef.Doc2_2.Snippets, cdoc.SPDXDocRef.Doc2_2.Snippets...)
}
}

func cleanDocumentFileData(doc *Document) *Document {
doc.SPDXDocRef.Files = []*spdx.File2_2{}
func cleanDocumentFileData(spdxVersion string, doc *Document) *Document {
switch spdxVersion {
case "2.2":
doc.SPDXDocRef.Doc2_2.Files = []*spdx.File2_2{}

for i := range doc.SPDXDocRef.Packages {
doc.SPDXDocRef.Packages[i].Files = []*spdx.File2_2{}
for i := range doc.SPDXDocRef.Doc2_2.Packages {
doc.SPDXDocRef.Doc2_2.Packages[i].Files = []*spdx.File2_2{}
}
}

return doc
}

func updateRelationships(doc *Document, composableDocs []*Document) (*Document, []*Document) {
func updateRelationships(spdxVersion string, doc *Document, composableDocs []*Document) (*Document, []*Document) {

rootDocElID := spdx.DocElementID{}
if len(doc.SPDXDocRef.Packages) > 0 {
rootDocElID = spdx.MakeDocElementID("",
fmt.Sprintf("%s-%s", doc.SPDXDocRef.Packages[0].PackageName, doc.SPDXDocRef.Packages[0].PackageVersion))
} else {
rootDocElID = spdx.MakeDocElementID("",
fmt.Sprintf("%s-%s", doc.ConfigDataRef.PackageName, doc.ConfigDataRef.PackageVersion))
}
rootDocElID := setDocElID(spdxVersion, doc)
for _, cdoc := range composableDocs {
if cdoc != nil && len(cdoc.SPDXDocRef.Packages) > 0 {
elId := spdx.MakeDocElementID("",
fmt.Sprintf("%s-%s", cdoc.SPDXDocRef.Packages[0].PackageName, cdoc.SPDXDocRef.Packages[0].PackageVersion))
newRelationship := &spdx.Relationship2_2{
RefA: rootDocElID,
RefB: elId,
Relationship: "DESCRIBES",
switch spdxVersion {
case "2.2":
if cdoc != nil && len(cdoc.SPDXDocRef.Doc2_2.Packages) > 0 {
elId := spdx.MakeDocElementID("",
fmt.Sprintf("%s-%s", cdoc.SPDXDocRef.Doc2_2.Packages[0].PackageName, cdoc.SPDXDocRef.Doc2_2.Packages[0].PackageVersion))
newRelationship := &spdx.Relationship2_2{
RefA: rootDocElID,
RefB: elId,
Relationship: "DESCRIBES",
}
doc.SPDXDocRef.Doc2_2.Relationships = append(doc.SPDXDocRef.Doc2_2.Relationships, newRelationship)
}
if cdoc != nil && len(cdoc.SPDXDocRef.Doc2_2.Relationships) > 0 {
cdoc.SPDXDocRef.Doc2_2.Relationships = cdoc.SPDXDocRef.Doc2_2.Relationships[1:]
}
doc.SPDXDocRef.Relationships = append(doc.SPDXDocRef.Relationships, newRelationship)
}
if cdoc != nil && len(cdoc.SPDXDocRef.Relationships) > 0 {
cdoc.SPDXDocRef.Relationships = cdoc.SPDXDocRef.Relationships[1:]
}
}

return doc, composableDocs
}

func setDocElID(spdxVersion string, doc *Document) spdx.DocElementID {
rootDocElID := spdx.DocElementID{}
switch spdxVersion {
case "2.2":
if len(doc.SPDXDocRef.Doc2_2.Packages) > 0 {
rootDocElID = spdx.MakeDocElementID("",
fmt.Sprintf("%s-%s", doc.SPDXDocRef.Doc2_2.Packages[0].PackageName, doc.SPDXDocRef.Doc2_2.Packages[0].PackageVersion))
}
default:
rootDocElID = spdx.MakeDocElementID("",
fmt.Sprintf("%s-%s", doc.ConfigDataRef.PackageName, doc.ConfigDataRef.PackageVersion))
}
return rootDocElID
}

0 comments on commit d50cbec

Please sign in to comment.