aboutsummaryrefslogtreecommitdiff
path: root/tvsaver
diff options
context:
space:
mode:
authorIan Ling <ian@iancaling.com>2022-04-08 08:52:57 -0700
committerIan Ling <ian@iancaling.com>2022-04-25 15:00:47 -0700
commit460cf54ece7eba418c50407ee35544c5d63588a7 (patch)
tree07ec7aaf51a92a1ae209e540f45241f990561919 /tvsaver
parentfa24fac85dd550a3f815896241081a1246810d2c (diff)
downloadspdx-tools-460cf54ece7eba418c50407ee35544c5d63588a7.tar.gz
Overhaul structs, refactor JSON parser and saver
Signed-off-by: Ian Ling <ian@iancaling.com>
Diffstat (limited to 'tvsaver')
-rw-r--r--tvsaver/saver2v1/save_annotation.go4
-rw-r--r--tvsaver/saver2v1/save_annotation_test.go9
-rw-r--r--tvsaver/saver2v1/save_creation_info.go43
-rw-r--r--tvsaver/saver2v1/save_creation_info_test.go86
-rw-r--r--tvsaver/saver2v1/save_document.go54
-rw-r--r--tvsaver/saver2v1/save_document_test.go70
-rw-r--r--tvsaver/saver2v1/save_file.go17
-rw-r--r--tvsaver/saver2v1/save_file_test.go56
-rw-r--r--tvsaver/saver2v1/save_package.go61
-rw-r--r--tvsaver/saver2v1/save_package_test.go151
-rw-r--r--tvsaver/saver2v1/save_snippet.go15
-rw-r--r--tvsaver/saver2v1/save_snippet_test.go46
-rw-r--r--tvsaver/saver2v2/save_annotation.go4
-rw-r--r--tvsaver/saver2v2/save_annotation_test.go9
-rw-r--r--tvsaver/saver2v2/save_creation_info.go43
-rw-r--r--tvsaver/saver2v2/save_creation_info_test.go86
-rw-r--r--tvsaver/saver2v2/save_document.go54
-rw-r--r--tvsaver/saver2v2/save_document_test.go104
-rw-r--r--tvsaver/saver2v2/save_file.go18
-rw-r--r--tvsaver/saver2v2/save_file_test.go69
-rw-r--r--tvsaver/saver2v2/save_package.go61
-rw-r--r--tvsaver/saver2v2/save_package_test.go114
-rw-r--r--tvsaver/saver2v2/save_snippet.go15
-rw-r--r--tvsaver/saver2v2/save_snippet_test.go46
24 files changed, 551 insertions, 684 deletions
diff --git a/tvsaver/saver2v1/save_annotation.go b/tvsaver/saver2v1/save_annotation.go
index 8c0ae89..f7d7953 100644
--- a/tvsaver/saver2v1/save_annotation.go
+++ b/tvsaver/saver2v1/save_annotation.go
@@ -10,8 +10,8 @@ import (
)
func renderAnnotation2_1(ann *spdx.Annotation2_1, w io.Writer) error {
- if ann.Annotator != "" && ann.AnnotatorType != "" {
- fmt.Fprintf(w, "Annotator: %s: %s\n", ann.AnnotatorType, ann.Annotator)
+ if ann.Annotator.Annotator != "" && ann.Annotator.AnnotatorType != "" {
+ fmt.Fprintf(w, "Annotator: %s: %s\n", ann.Annotator.AnnotatorType, ann.Annotator.Annotator)
}
if ann.AnnotationDate != "" {
fmt.Fprintf(w, "AnnotationDate: %s\n", ann.AnnotationDate)
diff --git a/tvsaver/saver2v1/save_annotation_test.go b/tvsaver/saver2v1/save_annotation_test.go
index 9cb0277..3eef5a7 100644
--- a/tvsaver/saver2v1/save_annotation_test.go
+++ b/tvsaver/saver2v1/save_annotation_test.go
@@ -12,8 +12,7 @@ import (
// ===== Annotation section Saver tests =====
func TestSaver2_1AnnotationSavesTextForPerson(t *testing.T) {
ann := &spdx.Annotation2_1{
- Annotator: "John Doe",
- AnnotatorType: "Person",
+ Annotator: spdx.Annotator{AnnotatorType: "Person", Annotator: "John Doe"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
@@ -45,8 +44,7 @@ AnnotationComment: This is an annotation about the SPDX document
func TestSaver2_1AnnotationSavesTextForOrganization(t *testing.T) {
ann := &spdx.Annotation2_1{
- Annotator: "John Doe, Inc.",
- AnnotatorType: "Organization",
+ Annotator: spdx.Annotator{AnnotatorType: "Organization", Annotator: "John Doe, Inc."},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
@@ -78,8 +76,7 @@ AnnotationComment: This is an annotation about the SPDX document
func TestSaver2_1AnnotationSavesTextForTool(t *testing.T) {
ann := &spdx.Annotation2_1{
- Annotator: "magictool-1.1",
- AnnotatorType: "Tool",
+ Annotator: spdx.Annotator{AnnotatorType: "Tool", Annotator: "magictool-1.1"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
diff --git a/tvsaver/saver2v1/save_creation_info.go b/tvsaver/saver2v1/save_creation_info.go
index 6ea6086..de8b107 100644
--- a/tvsaver/saver2v1/save_creation_info.go
+++ b/tvsaver/saver2v1/save_creation_info.go
@@ -4,50 +4,16 @@ package saver2v1
import (
"fmt"
- "io"
- "sort"
-
"github.com/spdx/tools-golang/spdx"
+ "io"
)
func renderCreationInfo2_1(ci *spdx.CreationInfo2_1, w io.Writer) error {
- if ci.SPDXVersion != "" {
- fmt.Fprintf(w, "SPDXVersion: %s\n", ci.SPDXVersion)
- }
- if ci.DataLicense != "" {
- fmt.Fprintf(w, "DataLicense: %s\n", ci.DataLicense)
- }
- if ci.SPDXIdentifier != "" {
- fmt.Fprintf(w, "SPDXID: %s\n", spdx.RenderElementID(ci.SPDXIdentifier))
- }
- if ci.DocumentName != "" {
- fmt.Fprintf(w, "DocumentName: %s\n", ci.DocumentName)
- }
- if ci.DocumentNamespace != "" {
- fmt.Fprintf(w, "DocumentNamespace: %s\n", ci.DocumentNamespace)
- }
- // print EDRs in order sorted by identifier
- edrIDs := []string{}
- for docRefID := range ci.ExternalDocumentReferences {
- edrIDs = append(edrIDs, docRefID)
- }
- sort.Strings(edrIDs)
- for _, edrID := range edrIDs {
- edr := ci.ExternalDocumentReferences[edrID]
- fmt.Fprintf(w, "ExternalDocumentRef: DocumentRef-%s %s %s:%s\n",
- edr.DocumentRefID, edr.URI, edr.Alg, edr.Checksum)
- }
if ci.LicenseListVersion != "" {
fmt.Fprintf(w, "LicenseListVersion: %s\n", ci.LicenseListVersion)
}
- for _, s := range ci.CreatorPersons {
- fmt.Fprintf(w, "Creator: Person: %s\n", s)
- }
- for _, s := range ci.CreatorOrganizations {
- fmt.Fprintf(w, "Creator: Organization: %s\n", s)
- }
- for _, s := range ci.CreatorTools {
- fmt.Fprintf(w, "Creator: Tool: %s\n", s)
+ for _, creator := range ci.Creators {
+ fmt.Fprintf(w, "Creator: %s: %s\n", creator.CreatorType, creator.Creator)
}
if ci.Created != "" {
fmt.Fprintf(w, "Created: %s\n", ci.Created)
@@ -55,9 +21,6 @@ func renderCreationInfo2_1(ci *spdx.CreationInfo2_1, w io.Writer) error {
if ci.CreatorComment != "" {
fmt.Fprintf(w, "CreatorComment: %s\n", textify(ci.CreatorComment))
}
- if ci.DocumentComment != "" {
- fmt.Fprintf(w, "DocumentComment: %s\n", textify(ci.DocumentComment))
- }
// add blank newline b/c end of a main section
fmt.Fprintf(w, "\n")
diff --git a/tvsaver/saver2v1/save_creation_info_test.go b/tvsaver/saver2v1/save_creation_info_test.go
index cec03c7..1784cf5 100644
--- a/tvsaver/saver2v1/save_creation_info_test.go
+++ b/tvsaver/saver2v1/save_creation_info_test.go
@@ -12,53 +12,22 @@ import (
// ===== Creation Info section Saver tests =====
func TestSaver2_1CISavesText(t *testing.T) {
ci := &spdx.CreationInfo2_1{
- SPDXVersion: "SPDX-2.1",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- ExternalDocumentReferences: map[string]spdx.ExternalDocumentRef2_1{
- "spdx-go-0.0.1a": spdx.ExternalDocumentRef2_1{
- DocumentRefID: "spdx-go-0.0.1a",
- URI: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1a.cdefab.whatever",
- Alg: "SHA1",
- Checksum: "0123456701234567012345670123456701234567",
- },
- "time-1.2.3": spdx.ExternalDocumentRef2_1{
- DocumentRefID: "time-1.2.3",
- URI: "https://github.com/swinslow/spdx-docs/time/time-1.2.3.cdefab.whatever",
- Alg: "SHA1",
- Checksum: "0123456701234567012345670123456701234568",
- },
- },
LicenseListVersion: "2.0",
- CreatorPersons: []string{
- "John Doe",
- "Jane Doe (janedoe@example.com)",
- },
- CreatorOrganizations: []string{
- "John Doe, Inc.",
- "Jane Doe LLC",
- },
- CreatorTools: []string{
- "magictool1-1.0",
- "magictool2-1.0",
- "magictool3-1.0",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe", CreatorType: "Person"},
+ {Creator: "Jane Doe (janedoe@example.com)", CreatorType: "Person"},
+ {Creator: "John Doe, Inc.", CreatorType: "Organization"},
+ {Creator: "Jane Doe LLC", CreatorType: "Organization"},
+ {Creator: "magictool1-1.0", CreatorType: "Tool"},
+ {Creator: "magictool2-1.0", CreatorType: "Tool"},
+ {Creator: "magictool3-1.0", CreatorType: "Tool"},
},
- Created: "2018-10-10T06:20:00Z",
- CreatorComment: "this is a creator comment",
- DocumentComment: "this is a document comment",
+ Created: "2018-10-10T06:20:00Z",
+ CreatorComment: "this is a creator comment",
}
// what we want to get, as a buffer of bytes
- want := bytes.NewBufferString(`SPDXVersion: SPDX-2.1
-DataLicense: CC0-1.0
-SPDXID: SPDXRef-DOCUMENT
-DocumentName: spdx-go-0.0.1.abcdef
-DocumentNamespace: https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever
-ExternalDocumentRef: DocumentRef-spdx-go-0.0.1a https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1a.cdefab.whatever SHA1:0123456701234567012345670123456701234567
-ExternalDocumentRef: DocumentRef-time-1.2.3 https://github.com/swinslow/spdx-docs/time/time-1.2.3.cdefab.whatever SHA1:0123456701234567012345670123456701234568
-LicenseListVersion: 2.0
+ want := bytes.NewBufferString(`LicenseListVersion: 2.0
Creator: Person: John Doe
Creator: Person: Jane Doe (janedoe@example.com)
Creator: Organization: John Doe, Inc.
@@ -68,7 +37,6 @@ Creator: Tool: magictool2-1.0
Creator: Tool: magictool3-1.0
Created: 2018-10-10T06:20:00Z
CreatorComment: this is a creator comment
-DocumentComment: this is a document comment
`)
@@ -89,24 +57,14 @@ DocumentComment: this is a document comment
func TestSaver2_1CIOmitsOptionalFieldsIfEmpty(t *testing.T) {
// --- need at least one creator; do first for Persons ---
ci1 := &spdx.CreationInfo2_1{
- SPDXVersion: "SPDX-2.1",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- CreatorPersons: []string{
- "John Doe",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe", CreatorType: "Person"},
},
Created: "2018-10-10T06:20:00Z",
}
// what we want to get, as a buffer of bytes
- want1 := bytes.NewBufferString(`SPDXVersion: SPDX-2.1
-DataLicense: CC0-1.0
-SPDXID: SPDXRef-DOCUMENT
-DocumentName: spdx-go-0.0.1.abcdef
-DocumentNamespace: https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever
-Creator: Person: John Doe
+ want1 := bytes.NewBufferString(`Creator: Person: John Doe
Created: 2018-10-10T06:20:00Z
`)
@@ -126,24 +84,14 @@ Created: 2018-10-10T06:20:00Z
// --- need at least one creator; now switch to organization ---
ci2 := &spdx.CreationInfo2_1{
- SPDXVersion: "SPDX-2.1",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- CreatorOrganizations: []string{
- "John Doe, Inc.",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe, Inc.", CreatorType: "Organization"},
},
Created: "2018-10-10T06:20:00Z",
}
// what we want to get, as a buffer of bytes
- want2 := bytes.NewBufferString(`SPDXVersion: SPDX-2.1
-DataLicense: CC0-1.0
-SPDXID: SPDXRef-DOCUMENT
-DocumentName: spdx-go-0.0.1.abcdef
-DocumentNamespace: https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever
-Creator: Organization: John Doe, Inc.
+ want2 := bytes.NewBufferString(`Creator: Organization: John Doe, Inc.
Created: 2018-10-10T06:20:00Z
`)
diff --git a/tvsaver/saver2v1/save_document.go b/tvsaver/saver2v1/save_document.go
index 67dfddc..ea17db2 100644
--- a/tvsaver/saver2v1/save_document.go
+++ b/tvsaver/saver2v1/save_document.go
@@ -21,30 +21,50 @@ func RenderDocument2_1(doc *spdx.Document2_1, w io.Writer) error {
return fmt.Errorf("Document had nil CreationInfo section")
}
+ if doc.SPDXVersion != "" {
+ fmt.Fprintf(w, "SPDXVersion: %s\n", doc.SPDXVersion)
+ }
+ if doc.DataLicense != "" {
+ fmt.Fprintf(w, "DataLicense: %s\n", doc.DataLicense)
+ }
+ if doc.SPDXIdentifier != "" {
+ fmt.Fprintf(w, "SPDXID: %s\n", spdx.RenderElementID(doc.SPDXIdentifier))
+ }
+ if doc.DocumentName != "" {
+ fmt.Fprintf(w, "DocumentName: %s\n", doc.DocumentName)
+ }
+ if doc.DocumentNamespace != "" {
+ fmt.Fprintf(w, "DocumentNamespace: %s\n", doc.DocumentNamespace)
+ }
+ // print EDRs in order sorted by identifier
+ sort.Slice(doc.ExternalDocumentReferences, func(i, j int) bool {
+ return doc.ExternalDocumentReferences[i].DocumentRefID < doc.ExternalDocumentReferences[j].DocumentRefID
+ })
+ for _, edr := range doc.ExternalDocumentReferences {
+ fmt.Fprintf(w, "ExternalDocumentRef: DocumentRef-%s %s %s:%s\n",
+ edr.DocumentRefID, edr.URI, edr.Checksum.Algorithm, edr.Checksum.Value)
+ }
+ if doc.DocumentComment != "" {
+ fmt.Fprintf(w, "DocumentComment: %s\n", textify(doc.DocumentComment))
+ }
+
renderCreationInfo2_1(doc.CreationInfo, w)
- if len(doc.UnpackagedFiles) > 0 {
+ if len(doc.Files) > 0 {
fmt.Fprintf(w, "##### Unpackaged files\n\n")
- // get slice of identifiers so we can sort them
- unpackagedFileKeys := []string{}
- for k := range doc.UnpackagedFiles {
- unpackagedFileKeys = append(unpackagedFileKeys, string(k))
- }
- sort.Strings(unpackagedFileKeys)
- for _, fiID := range unpackagedFileKeys {
- fi := doc.UnpackagedFiles[spdx.ElementID(fiID)]
+ sort.Slice(doc.Files, func(i, j int) bool {
+ return doc.Files[i].FileSPDXIdentifier < doc.Files[j].FileSPDXIdentifier
+ })
+ for _, fi := range doc.Files {
renderFile2_1(fi, w)
}
}
- // get slice of Package identifiers so we can sort them
- packageKeys := []string{}
- for k := range doc.Packages {
- packageKeys = append(packageKeys, string(k))
- }
- sort.Strings(packageKeys)
- for _, pkgID := range packageKeys {
- pkg := doc.Packages[spdx.ElementID(pkgID)]
+ // sort Packages by identifier
+ sort.Slice(doc.Packages, func(i, j int) bool {
+ return doc.Packages[i].PackageSPDXIdentifier < doc.Packages[j].PackageSPDXIdentifier
+ })
+ for _, pkg := range doc.Packages {
fmt.Fprintf(w, "##### Package: %s\n\n", pkg.PackageName)
renderPackage2_1(pkg, w)
}
diff --git a/tvsaver/saver2v1/save_document_test.go b/tvsaver/saver2v1/save_document_test.go
index 708eabf..b186564 100644
--- a/tvsaver/saver2v1/save_document_test.go
+++ b/tvsaver/saver2v1/save_document_test.go
@@ -14,13 +14,8 @@ func TestSaver2_1DocumentSavesText(t *testing.T) {
// Creation Info section
ci := &spdx.CreationInfo2_1{
- SPDXVersion: "SPDX-2.1",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- CreatorPersons: []string{
- "John Doe",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe", CreatorType: "Person"},
},
Created: "2018-10-10T06:20:00Z",
}
@@ -29,41 +24,39 @@ func TestSaver2_1DocumentSavesText(t *testing.T) {
f1 := &spdx.File2_1{
FileName: "/tmp/whatever1.txt",
FileSPDXIdentifier: spdx.ElementID("File1231"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983c", Algorithm: spdx.SHA1}},
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{"Apache-2.0"},
+ LicenseInfoInFiles: []string{"Apache-2.0"},
FileCopyrightText: "Copyright (c) Jane Doe",
}
f2 := &spdx.File2_1{
FileName: "/tmp/whatever2.txt",
FileSPDXIdentifier: spdx.ElementID("File1232"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983d",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983d", Algorithm: spdx.SHA1}},
LicenseConcluded: "MIT",
- LicenseInfoInFile: []string{"MIT"},
+ LicenseInfoInFiles: []string{"MIT"},
FileCopyrightText: "Copyright (c) John Doe",
}
- unFiles := map[spdx.ElementID]*spdx.File2_1{
- spdx.ElementID("File1231"): f1,
- spdx.ElementID("File1232"): f2,
+ unFiles := []*spdx.File2_1{
+ f1,
+ f2,
}
// Package 1: packaged files with snippets
sn1 := &spdx.Snippet2_1{
SnippetSPDXIdentifier: "Snippet19",
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 17}, EndPointer: spdx.SnippetRangePointer{Offset: 209}}},
SnippetLicenseConcluded: "GPL-2.0-or-later",
SnippetCopyrightText: "Copyright (c) John Doe 20x6",
}
sn2 := &spdx.Snippet2_1{
SnippetSPDXIdentifier: "Snippet20",
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets"),
- SnippetByteRangeStart: 268,
- SnippetByteRangeEnd: 309,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 268}, EndPointer: spdx.SnippetRangePointer{Offset: 309}}},
SnippetLicenseConcluded: "WTFPL",
SnippetCopyrightText: "NOASSERTION",
}
@@ -71,9 +64,9 @@ func TestSaver2_1DocumentSavesText(t *testing.T) {
f3 := &spdx.File2_1{
FileName: "/tmp/file-with-snippets.txt",
FileSPDXIdentifier: spdx.ElementID("FileHasSnippets"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983e",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983e", Algorithm: spdx.SHA1}},
LicenseConcluded: "GPL-2.0-or-later AND WTFPL",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
"GPL-2.0-or-later",
"WTFPL",
@@ -88,9 +81,9 @@ func TestSaver2_1DocumentSavesText(t *testing.T) {
f4 := &spdx.File2_1{
FileName: "/tmp/another-file.txt",
FileSPDXIdentifier: spdx.ElementID("FileAnother"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983f",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983f", Algorithm: spdx.SHA1}},
LicenseConcluded: "BSD-3-Clause",
- LicenseInfoInFile: []string{"BSD-3-Clause"},
+ LicenseInfoInFiles: []string{"BSD-3-Clause"},
FileCopyrightText: "Copyright (c) Jane Doe LLC",
}
@@ -100,7 +93,7 @@ func TestSaver2_1DocumentSavesText(t *testing.T) {
PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
FilesAnalyzed: true,
IsFilesAnalyzedTagPresent: true,
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
+ PackageVerificationCode: spdx.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
PackageLicenseConcluded: "GPL-2.0-or-later AND BSD-3-Clause AND WTFPL",
PackageLicenseInfoFromFiles: []string{
"Apache-2.0",
@@ -110,9 +103,9 @@ func TestSaver2_1DocumentSavesText(t *testing.T) {
},
PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
PackageCopyrightText: "Copyright (c) John Doe, Inc.",
- Files: map[spdx.ElementID]*spdx.File2_1{
- spdx.ElementID("FileHasSnippets"): f3,
- spdx.ElementID("FileAnother"): f4,
+ Files: []*spdx.File2_1{
+ f3,
+ f4,
},
}
@@ -152,8 +145,8 @@ blah blah blah blah`,
// Annotations
ann1 := &spdx.Annotation2_1{
- Annotator: "John Doe",
- AnnotatorType: "Person",
+ Annotator: spdx.Annotator{Annotator: "John Doe",
+ AnnotatorType: "Person"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
@@ -161,8 +154,8 @@ blah blah blah blah`,
}
ann2 := &spdx.Annotation2_1{
- Annotator: "John Doe, Inc.",
- AnnotatorType: "Organization",
+ Annotator: spdx.Annotator{Annotator: "John Doe, Inc.",
+ AnnotatorType: "Organization"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "p1"),
@@ -184,11 +177,16 @@ blah blah blah blah`,
// now, build the document
doc := &spdx.Document2_1{
- CreationInfo: ci,
- Packages: map[spdx.ElementID]*spdx.Package2_1{
- spdx.ElementID("p1"): pkgWith,
+ SPDXVersion: "SPDX-2.1",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: spdx.ElementID("DOCUMENT"),
+ DocumentName: "spdx-go-0.0.1.abcdef",
+ DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
+ CreationInfo: ci,
+ Packages: []*spdx.Package2_1{
+ pkgWith,
},
- UnpackagedFiles: unFiles,
+ Files: unFiles,
OtherLicenses: []*spdx.OtherLicense2_1{
ol1,
ol2,
diff --git a/tvsaver/saver2v1/save_file.go b/tvsaver/saver2v1/save_file.go
index d22a012..c131122 100644
--- a/tvsaver/saver2v1/save_file.go
+++ b/tvsaver/saver2v1/save_file.go
@@ -17,22 +17,17 @@ func renderFile2_1(f *spdx.File2_1, w io.Writer) error {
if f.FileSPDXIdentifier != "" {
fmt.Fprintf(w, "SPDXID: %s\n", spdx.RenderElementID(f.FileSPDXIdentifier))
}
- for _, s := range f.FileType {
+ for _, s := range f.FileTypes {
fmt.Fprintf(w, "FileType: %s\n", s)
}
- if f.FileChecksumSHA1 != "" {
- fmt.Fprintf(w, "FileChecksum: SHA1: %s\n", f.FileChecksumSHA1)
- }
- if f.FileChecksumSHA256 != "" {
- fmt.Fprintf(w, "FileChecksum: SHA256: %s\n", f.FileChecksumSHA256)
- }
- if f.FileChecksumMD5 != "" {
- fmt.Fprintf(w, "FileChecksum: MD5: %s\n", f.FileChecksumMD5)
+
+ for _, checksum := range f.Checksums {
+ fmt.Fprintf(w, "FileChecksum: %s: %s\n", checksum.Algorithm, checksum.Value)
}
if f.LicenseConcluded != "" {
fmt.Fprintf(w, "LicenseConcluded: %s\n", f.LicenseConcluded)
}
- for _, s := range f.LicenseInfoInFile {
+ for _, s := range f.LicenseInfoInFiles {
fmt.Fprintf(w, "LicenseInfoInFile: %s\n", s)
}
if f.LicenseComments != "" {
@@ -56,7 +51,7 @@ func renderFile2_1(f *spdx.File2_1, w io.Writer) error {
if f.FileNotice != "" {
fmt.Fprintf(w, "FileNotice: %s\n", textify(f.FileNotice))
}
- for _, s := range f.FileContributor {
+ for _, s := range f.FileContributors {
fmt.Fprintf(w, "FileContributor: %s\n", s)
}
for _, s := range f.FileDependencies {
diff --git a/tvsaver/saver2v1/save_file_test.go b/tvsaver/saver2v1/save_file_test.go
index cdd6d25..9708430 100644
--- a/tvsaver/saver2v1/save_file_test.go
+++ b/tvsaver/saver2v1/save_file_test.go
@@ -14,15 +14,17 @@ func TestSaver2_1FileSavesText(t *testing.T) {
f := &spdx.File2_1{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileType: []string{
+ FileTypes: []string{
"TEXT",
"DOCUMENTATION",
},
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- FileChecksumSHA256: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
- FileChecksumMD5: "624c1abb3664f4b35547e7c73864ad24",
- LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
+ {Algorithm: spdx.SHA256, Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"},
+ {Algorithm: spdx.MD5, Value: "624c1abb3664f4b35547e7c73864ad24"},
+ },
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFiles: []string{
"Apache-2.0",
"Apache-1.1",
},
@@ -48,7 +50,7 @@ func TestSaver2_1FileSavesText(t *testing.T) {
},
FileComment: "this is a file comment",
FileNotice: "This file may be used under either Apache-2.0 or Apache-1.1.",
- FileContributor: []string{
+ FileContributors: []string{
"John Doe jdoe@example.com",
"EvilCorp",
},
@@ -105,18 +107,16 @@ FileDependency: g.txt
func TestSaver2_1FileSavesSnippetsAlso(t *testing.T) {
sn1 := &spdx.Snippet2_1{
SnippetSPDXIdentifier: spdx.ElementID("Snippet19"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 17}, EndPointer: spdx.SnippetRangePointer{Offset: 209}}},
SnippetLicenseConcluded: "GPL-2.0-or-later",
SnippetCopyrightText: "Copyright (c) John Doe 20x6",
}
sn2 := &spdx.Snippet2_1{
SnippetSPDXIdentifier: spdx.ElementID("Snippet20"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123"),
- SnippetByteRangeStart: 268,
- SnippetByteRangeEnd: 309,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 268}, EndPointer: spdx.SnippetRangePointer{Offset: 309}}},
SnippetLicenseConcluded: "WTFPL",
SnippetCopyrightText: "NOASSERTION",
}
@@ -129,9 +129,11 @@ func TestSaver2_1FileSavesSnippetsAlso(t *testing.T) {
f := &spdx.File2_1{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
+ },
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: "Copyright (c) Jane Doe",
@@ -178,9 +180,11 @@ func TestSaver2_1FileOmitsOptionalFieldsIfEmpty(t *testing.T) {
f := &spdx.File2_1{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
+ },
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: "Copyright (c) Jane Doe",
@@ -214,9 +218,11 @@ func TestSaver2_1FileWrapsCopyrightMultiLine(t *testing.T) {
f := &spdx.File2_1{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
+ },
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: `Copyright (c) Jane Doe
@@ -252,11 +258,13 @@ func TestSaver2_1FileWrapsCommentsAndNoticesMultiLine(t *testing.T) {
f := &spdx.File2_1{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
+ },
LicenseComments: `this is a
multi-line license comment`,
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: "Copyright (c) Jane Doe",
diff --git a/tvsaver/saver2v1/save_package.go b/tvsaver/saver2v1/save_package.go
index 9b19cfa..24a468c 100644
--- a/tvsaver/saver2v1/save_package.go
+++ b/tvsaver/saver2v1/save_package.go
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"sort"
+ "strings"
"github.com/spdx/tools-golang/spdx"
)
@@ -23,23 +24,19 @@ func renderPackage2_1(pkg *spdx.Package2_1, w io.Writer) error {
if pkg.PackageFileName != "" {
fmt.Fprintf(w, "PackageFileName: %s\n", pkg.PackageFileName)
}
- if pkg.PackageSupplierPerson != "" {
- fmt.Fprintf(w, "PackageSupplier: Person: %s\n", pkg.PackageSupplierPerson)
- }
- if pkg.PackageSupplierOrganization != "" {
- fmt.Fprintf(w, "PackageSupplier: Organization: %s\n", pkg.PackageSupplierOrganization)
- }
- if pkg.PackageSupplierNOASSERTION == true {
- fmt.Fprintf(w, "PackageSupplier: NOASSERTION\n")
- }
- if pkg.PackageOriginatorPerson != "" {
- fmt.Fprintf(w, "PackageOriginator: Person: %s\n", pkg.PackageOriginatorPerson)
- }
- if pkg.PackageOriginatorOrganization != "" {
- fmt.Fprintf(w, "PackageOriginator: Organization: %s\n", pkg.PackageOriginatorOrganization)
+ if pkg.PackageSupplier != nil && pkg.PackageSupplier.Supplier != "" {
+ if pkg.PackageSupplier.SupplierType == "" {
+ fmt.Fprintf(w, "PackageSupplier: %s\n", pkg.PackageSupplier.Supplier)
+ } else {
+ fmt.Fprintf(w, "PackageSupplier: %s: %s\n", pkg.PackageSupplier.SupplierType, pkg.PackageSupplier.Supplier)
+ }
}
- if pkg.PackageOriginatorNOASSERTION == true {
- fmt.Fprintf(w, "PackageOriginator: NOASSERTION\n")
+ if pkg.PackageOriginator != nil && pkg.PackageOriginator.Originator != "" {
+ if pkg.PackageOriginator.OriginatorType == "" {
+ fmt.Fprintf(w, "PackageOriginator: %s\n", pkg.PackageOriginator.Originator)
+ } else {
+ fmt.Fprintf(w, "PackageOriginator: %s: %s\n", pkg.PackageOriginator.OriginatorType, pkg.PackageOriginator.Originator)
+ }
}
if pkg.PackageDownloadLocation != "" {
fmt.Fprintf(w, "PackageDownloadLocation: %s\n", pkg.PackageDownloadLocation)
@@ -51,22 +48,18 @@ func renderPackage2_1(pkg *spdx.Package2_1, w io.Writer) error {
} else {
fmt.Fprintf(w, "FilesAnalyzed: false\n")
}
- if pkg.PackageVerificationCode != "" && pkg.FilesAnalyzed == true {
- if pkg.PackageVerificationCodeExcludedFile == "" {
- fmt.Fprintf(w, "PackageVerificationCode: %s\n", pkg.PackageVerificationCode)
+ if pkg.PackageVerificationCode.Value != "" && pkg.FilesAnalyzed == true {
+ if len(pkg.PackageVerificationCode.ExcludedFiles) == 0 {
+ fmt.Fprintf(w, "PackageVerificationCode: %s\n", pkg.PackageVerificationCode.Value)
} else {
- fmt.Fprintf(w, "PackageVerificationCode: %s (excludes: %s)\n", pkg.PackageVerificationCode, pkg.PackageVerificationCodeExcludedFile)
+ fmt.Fprintf(w, "PackageVerificationCode: %s (excludes: %s)\n", pkg.PackageVerificationCode.Value, strings.Join(pkg.PackageVerificationCode.ExcludedFiles, ", "))
}
}
- if pkg.PackageChecksumSHA1 != "" {
- fmt.Fprintf(w, "PackageChecksum: SHA1: %s\n", pkg.PackageChecksumSHA1)
- }
- if pkg.PackageChecksumSHA256 != "" {
- fmt.Fprintf(w, "PackageChecksum: SHA256: %s\n", pkg.PackageChecksumSHA256)
- }
- if pkg.PackageChecksumMD5 != "" {
- fmt.Fprintf(w, "PackageChecksum: MD5: %s\n", pkg.PackageChecksumMD5)
+
+ for _, checksum := range pkg.PackageChecksums {
+ fmt.Fprintf(w, "PackageChecksum: %s: %s\n", checksum.Algorithm, checksum.Value)
}
+
if pkg.PackageHomePage != "" {
fmt.Fprintf(w, "PackageHomePage: %s\n", pkg.PackageHomePage)
}
@@ -109,14 +102,10 @@ func renderPackage2_1(pkg *spdx.Package2_1, w io.Writer) error {
fmt.Fprintf(w, "\n")
// also render any files for this package
- // get slice of File identifiers so we can sort them
- fileKeys := []string{}
- for k := range pkg.Files {
- fileKeys = append(fileKeys, string(k))
- }
- sort.Strings(fileKeys)
- for _, fiID := range fileKeys {
- fi := pkg.Files[spdx.ElementID(fiID)]
+ sort.Slice(pkg.Files, func(i, j int) bool {
+ return pkg.Files[i].FileSPDXIdentifier < pkg.Files[j].FileSPDXIdentifier
+ })
+ for _, fi := range pkg.Files {
renderFile2_1(fi, w)
}
diff --git a/tvsaver/saver2v1/save_package_test.go b/tvsaver/saver2v1/save_package_test.go
index fc6b2a6..0f1541c 100644
--- a/tvsaver/saver2v1/save_package_test.go
+++ b/tvsaver/saver2v1/save_package_test.go
@@ -41,23 +41,36 @@ multi-line external ref comment`,
}
pkg := &spdx.Package2_1{
- PackageName: "p1",
- PackageSPDXIdentifier: spdx.ElementID("p1"),
- PackageVersion: "0.1.0",
- PackageFileName: "p1-0.1.0-master.tar.gz",
- PackageSupplierOrganization: "John Doe, Inc.",
- PackageOriginatorPerson: "John Doe",
- PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
- FilesAnalyzed: true,
- IsFilesAnalyzedTagPresent: true,
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
- PackageVerificationCodeExcludedFile: "p1-0.1.0.spdx",
- PackageChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- PackageChecksumSHA256: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
- PackageChecksumMD5: "624c1abb3664f4b35547e7c73864ad24",
- PackageHomePage: "http://example.com/p1",
- PackageSourceInfo: "this is a source comment",
- PackageLicenseConcluded: "GPL-2.0-or-later",
+ PackageName: "p1",
+ PackageSPDXIdentifier: spdx.ElementID("p1"),
+ PackageVersion: "0.1.0",
+ PackageFileName: "p1-0.1.0-master.tar.gz",
+ PackageSupplier: &spdx.Supplier{SupplierType: "Organization", Supplier: "John Doe, Inc."},
+ PackageOriginator: &spdx.Originator{Originator: "John Doe", OriginatorType: "Person"},
+ PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: true,
+ PackageVerificationCode: spdx.PackageVerificationCode{
+ Value: "0123456789abcdef0123456789abcdef01234567",
+ ExcludedFiles: []string{"p1-0.1.0.spdx"},
+ },
+ PackageChecksums: []spdx.Checksum{
+ {
+ Algorithm: spdx.SHA1,
+ Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ },
+ {
+ Algorithm: spdx.SHA256,
+ Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
+ },
+ {
+ Algorithm: spdx.MD5,
+ Value: "624c1abb3664f4b35547e7c73864ad24",
+ },
+ },
+ PackageHomePage: "http://example.com/p1",
+ PackageSourceInfo: "this is a source comment",
+ PackageLicenseConcluded: "GPL-2.0-or-later",
PackageLicenseInfoFromFiles: []string{
"Apache-1.1",
"Apache-2.0",
@@ -131,22 +144,33 @@ func TestSaver2_1PackageSavesTextCombo2(t *testing.T) {
// PackageVerificationCodeExcludedFile is empty
pkg := &spdx.Package2_1{
- PackageName: "p1",
- PackageSPDXIdentifier: spdx.ElementID("p1"),
- PackageVersion: "0.1.0",
- PackageFileName: "p1-0.1.0-master.tar.gz",
- PackageSupplierNOASSERTION: true,
- PackageOriginatorOrganization: "John Doe, Inc.",
- PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
- FilesAnalyzed: true,
- IsFilesAnalyzedTagPresent: false,
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
- PackageChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- PackageChecksumSHA256: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
- PackageChecksumMD5: "624c1abb3664f4b35547e7c73864ad24",
- PackageHomePage: "http://example.com/p1",
- PackageSourceInfo: "this is a source comment",
- PackageLicenseConcluded: "GPL-2.0-or-later",
+ PackageName: "p1",
+ PackageSPDXIdentifier: spdx.ElementID("p1"),
+ PackageVersion: "0.1.0",
+ PackageFileName: "p1-0.1.0-master.tar.gz",
+ PackageSupplier: &spdx.Supplier{Supplier: "NOASSERTION"},
+ PackageOriginator: &spdx.Originator{OriginatorType: "Organization", Originator: "John Doe, Inc."},
+ PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: false,
+ PackageVerificationCode: spdx.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
+ PackageChecksums: []spdx.Checksum{
+ {
+ Algorithm: spdx.SHA1,
+ Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ },
+ {
+ Algorithm: spdx.SHA256,
+ Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
+ },
+ {
+ Algorithm: spdx.MD5,
+ Value: "624c1abb3664f4b35547e7c73864ad24",
+ },
+ },
+ PackageHomePage: "http://example.com/p1",
+ PackageSourceInfo: "this is a source comment",
+ PackageLicenseConcluded: "GPL-2.0-or-later",
PackageLicenseInfoFromFiles: []string{
"Apache-1.1",
"Apache-2.0",
@@ -208,21 +232,32 @@ func TestSaver2_1PackageSavesTextCombo3(t *testing.T) {
// PackageVerificationCodeExcludedFile is empty
pkg := &spdx.Package2_1{
- PackageName: "p1",
- PackageSPDXIdentifier: spdx.ElementID("p1"),
- PackageVersion: "0.1.0",
- PackageFileName: "p1-0.1.0-master.tar.gz",
- PackageSupplierPerson: "John Doe",
- PackageOriginatorNOASSERTION: true,
- PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
- FilesAnalyzed: false,
- IsFilesAnalyzedTagPresent: true,
+ PackageName: "p1",
+ PackageSPDXIdentifier: spdx.ElementID("p1"),
+ PackageVersion: "0.1.0",
+ PackageFileName: "p1-0.1.0-master.tar.gz",
+ PackageSupplier: &spdx.Supplier{Supplier: "John Doe", SupplierType: "Person"},
+ PackageOriginator: &spdx.Originator{Originator: "NOASSERTION"},
+ PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
+ FilesAnalyzed: false,
+ IsFilesAnalyzedTagPresent: true,
// NOTE that verification code MUST be omitted from output
// since FilesAnalyzed is false
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
- PackageChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
- PackageChecksumSHA256: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
- PackageChecksumMD5: "624c1abb3664f4b35547e7c73864ad24",
+ PackageVerificationCode: spdx.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
+ PackageChecksums: []spdx.Checksum{
+ {
+ Algorithm: spdx.SHA1,
+ Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ },
+ {
+ Algorithm: spdx.SHA256,
+ Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
+ },
+ {
+ Algorithm: spdx.MD5,
+ Value: "624c1abb3664f4b35547e7c73864ad24",
+ },
+ },
PackageHomePage: "http://example.com/p1",
PackageSourceInfo: "this is a source comment",
PackageLicenseConcluded: "GPL-2.0-or-later",
@@ -329,18 +364,28 @@ func TestSaver2_1PackageSavesFilesIfPresent(t *testing.T) {
f1 := &spdx.File2_1{
FileName: "/tmp/whatever1.txt",
FileSPDXIdentifier: spdx.ElementID("File1231"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ Checksums: []spdx.Checksum{
+ {
+ Algorithm: spdx.SHA1,
+ Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
+ },
+ },
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{"Apache-2.0"},
+ LicenseInfoInFiles: []string{"Apache-2.0"},
FileCopyrightText: "Copyright (c) Jane Doe",
}
f2 := &spdx.File2_1{
FileName: "/tmp/whatever2.txt",
FileSPDXIdentifier: spdx.ElementID("File1232"),
- FileChecksumSHA1: "85ed0817af83a24ad8da68c2b5094de69833983d",
+ Checksums: []spdx.Checksum{
+ {
+ Algorithm: spdx.SHA1,
+ Value: "85ed0817af83a24ad8da68c2b5094de69833983d",
+ },
+ },
LicenseConcluded: "MIT",
- LicenseInfoInFile: []string{"MIT"},
+ LicenseInfoInFiles: []string{"MIT"},
FileCopyrightText: "Copyright (c) John Doe",
}
@@ -362,9 +407,9 @@ func TestSaver2_1PackageSavesFilesIfPresent(t *testing.T) {
},
PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
PackageCopyrightText: "Copyright (c) John Doe, Inc.",
- Files: map[spdx.ElementID]*spdx.File2_1{
- spdx.ElementID("File1231"): f1,
- spdx.ElementID("File1232"): f2,
+ Files: []*spdx.File2_1{
+ f1,
+ f2,
},
}
diff --git a/tvsaver/saver2v1/save_snippet.go b/tvsaver/saver2v1/save_snippet.go
index e9e1a07..1399548 100644
--- a/tvsaver/saver2v1/save_snippet.go
+++ b/tvsaver/saver2v1/save_snippet.go
@@ -13,15 +13,18 @@ func renderSnippet2_1(sn *spdx.Snippet2_1, w io.Writer) error {
if sn.SnippetSPDXIdentifier != "" {
fmt.Fprintf(w, "SnippetSPDXID: %s\n", spdx.RenderElementID(sn.SnippetSPDXIdentifier))
}
- snFromFileIDStr := spdx.RenderDocElementID(sn.SnippetFromFileSPDXIdentifier)
+ snFromFileIDStr := spdx.RenderElementID(sn.SnippetFromFileSPDXIdentifier)
if snFromFileIDStr != "" {
fmt.Fprintf(w, "SnippetFromFileSPDXID: %s\n", snFromFileIDStr)
}
- if sn.SnippetByteRangeStart != 0 && sn.SnippetByteRangeEnd != 0 {
- fmt.Fprintf(w, "SnippetByteRange: %d:%d\n", sn.SnippetByteRangeStart, sn.SnippetByteRangeEnd)
- }
- if sn.SnippetLineRangeStart != 0 && sn.SnippetLineRangeEnd != 0 {
- fmt.Fprintf(w, "SnippetLineRange: %d:%d\n", sn.SnippetLineRangeStart, sn.SnippetLineRangeEnd)
+
+ for _, snippetRange := range sn.Ranges {
+ if snippetRange.StartPointer.Offset != 0 && snippetRange.EndPointer.Offset != 0 {
+ fmt.Fprintf(w, "SnippetByteRange: %d:%d\n", snippetRange.StartPointer.Offset, snippetRange.EndPointer.Offset)
+ }
+ if snippetRange.StartPointer.LineNumber != 0 && snippetRange.EndPointer.LineNumber != 0 {
+ fmt.Fprintf(w, "SnippetLineRange: %d:%d\n", snippetRange.StartPointer.LineNumber, snippetRange.EndPointer.LineNumber)
+ }
}
if sn.SnippetLicenseConcluded != "" {
fmt.Fprintf(w, "SnippetLicenseConcluded: %s\n", sn.SnippetLicenseConcluded)
diff --git a/tvsaver/saver2v1/save_snippet_test.go b/tvsaver/saver2v1/save_snippet_test.go
index 07c9e2a..fd6357e 100644
--- a/tvsaver/saver2v1/save_snippet_test.go
+++ b/tvsaver/saver2v1/save_snippet_test.go
@@ -13,12 +13,18 @@ import (
func TestSaver2_1SnippetSavesText(t *testing.T) {
sn := &spdx.Snippet2_1{
SnippetSPDXIdentifier: spdx.ElementID("Snippet17"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
- SnippetLineRangeStart: 3,
- SnippetLineRangeEnd: 8,
- SnippetLicenseConcluded: "GPL-2.0-or-later",
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292").ElementRefID,
+ Ranges: []spdx.SnippetRange{
+ {
+ StartPointer: spdx.SnippetRangePointer{LineNumber: 3},
+ EndPointer: spdx.SnippetRangePointer{LineNumber: 8},
+ },
+ {
+ StartPointer: spdx.SnippetRangePointer{Offset: 17},
+ EndPointer: spdx.SnippetRangePointer{Offset: 209},
+ },
+ },
+ SnippetLicenseConcluded: "GPL-2.0-or-later",
LicenseInfoInSnippet: []string{
"GPL-2.0-or-later",
"MIT",
@@ -32,8 +38,8 @@ func TestSaver2_1SnippetSavesText(t *testing.T) {
// what we want to get, as a buffer of bytes
want := bytes.NewBufferString(`SnippetSPDXID: SPDXRef-Snippet17
SnippetFromFileSPDXID: SPDXRef-File292
-SnippetByteRange: 17:209
SnippetLineRange: 3:8
+SnippetByteRange: 17:209
SnippetLicenseConcluded: GPL-2.0-or-later
LicenseInfoInSnippet: GPL-2.0-or-later
LicenseInfoInSnippet: MIT
@@ -61,11 +67,15 @@ SnippetName: from John's program
func TestSaver2_1SnippetOmitsOptionalFieldsIfEmpty(t *testing.T) {
sn := &spdx.Snippet2_1{
SnippetSPDXIdentifier: spdx.ElementID("Snippet17"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
- SnippetLicenseConcluded: "GPL-2.0-or-later",
- SnippetCopyrightText: "Copyright (c) John Doe 20x6",
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292").ElementRefID,
+ Ranges: []spdx.SnippetRange{
+ {
+ StartPointer: spdx.SnippetRangePointer{Offset: 17},
+ EndPointer: spdx.SnippetRangePointer{Offset: 209},
+ },
+ },
+ SnippetLicenseConcluded: "GPL-2.0-or-later",
+ SnippetCopyrightText: "Copyright (c) John Doe 20x6",
}
// what we want to get, as a buffer of bytes
@@ -94,10 +104,14 @@ SnippetCopyrightText: Copyright (c) John Doe 20x6
func TestSaver2_1SnippetWrapsCopyrightMultiline(t *testing.T) {
sn := &spdx.Snippet2_1{
SnippetSPDXIdentifier: spdx.ElementID("Snippet17"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
- SnippetLicenseConcluded: "GPL-2.0-or-later",
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292").ElementRefID,
+ Ranges: []spdx.SnippetRange{
+ {
+ StartPointer: spdx.SnippetRangePointer{Offset: 17},
+ EndPointer: spdx.SnippetRangePointer{Offset: 209},
+ },
+ },
+ SnippetLicenseConcluded: "GPL-2.0-or-later",
SnippetCopyrightText: `Copyright (c) John Doe 20x6
Copyright (c) John Doe 20x6`,
}
diff --git a/tvsaver/saver2v2/save_annotation.go b/tvsaver/saver2v2/save_annotation.go
index c0f1449..ddfe483 100644
--- a/tvsaver/saver2v2/save_annotation.go
+++ b/tvsaver/saver2v2/save_annotation.go
@@ -10,8 +10,8 @@ import (
)
func renderAnnotation2_2(ann *spdx.Annotation2_2, w io.Writer) error {
- if ann.Annotator != "" && ann.AnnotatorType != "" {
- fmt.Fprintf(w, "Annotator: %s: %s\n", ann.AnnotatorType, ann.Annotator)
+ if ann.Annotator.Annotator != "" && ann.Annotator.AnnotatorType != "" {
+ fmt.Fprintf(w, "Annotator: %s: %s\n", ann.Annotator.AnnotatorType, ann.Annotator.Annotator)
}
if ann.AnnotationDate != "" {
fmt.Fprintf(w, "AnnotationDate: %s\n", ann.AnnotationDate)
diff --git a/tvsaver/saver2v2/save_annotation_test.go b/tvsaver/saver2v2/save_annotation_test.go
index d938646..46d8546 100644
--- a/tvsaver/saver2v2/save_annotation_test.go
+++ b/tvsaver/saver2v2/save_annotation_test.go
@@ -12,8 +12,7 @@ import (
// ===== Annotation section Saver tests =====
func TestSaver2_2AnnotationSavesTextForPerson(t *testing.T) {
ann := &spdx.Annotation2_2{
- Annotator: "John Doe",
- AnnotatorType: "Person",
+ Annotator: spdx.Annotator{AnnotatorType: "Person", Annotator: "John Doe"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
@@ -45,8 +44,7 @@ AnnotationComment: This is an annotation about the SPDX document
func TestSaver2_2AnnotationSavesTextForOrganization(t *testing.T) {
ann := &spdx.Annotation2_2{
- Annotator: "John Doe, Inc.",
- AnnotatorType: "Organization",
+ Annotator: spdx.Annotator{AnnotatorType: "Organization", Annotator: "John Doe, Inc."},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
@@ -78,8 +76,7 @@ AnnotationComment: This is an annotation about the SPDX document
func TestSaver2_2AnnotationSavesTextForTool(t *testing.T) {
ann := &spdx.Annotation2_2{
- Annotator: "magictool-1.1",
- AnnotatorType: "Tool",
+ Annotator: spdx.Annotator{AnnotatorType: "Tool", Annotator: "magictool-1.1"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
diff --git a/tvsaver/saver2v2/save_creation_info.go b/tvsaver/saver2v2/save_creation_info.go
index 1492fb4..df2b0b0 100644
--- a/tvsaver/saver2v2/save_creation_info.go
+++ b/tvsaver/saver2v2/save_creation_info.go
@@ -4,50 +4,16 @@ package saver2v2
import (
"fmt"
- "io"
- "sort"
-
"github.com/spdx/tools-golang/spdx"
+ "io"
)
func renderCreationInfo2_2(ci *spdx.CreationInfo2_2, w io.Writer) error {
- if ci.SPDXVersion != "" {
- fmt.Fprintf(w, "SPDXVersion: %s\n", ci.SPDXVersion)
- }
- if ci.DataLicense != "" {
- fmt.Fprintf(w, "DataLicense: %s\n", ci.DataLicense)
- }
- if ci.SPDXIdentifier != "" {
- fmt.Fprintf(w, "SPDXID: %s\n", spdx.RenderElementID(ci.SPDXIdentifier))
- }
- if ci.DocumentName != "" {
- fmt.Fprintf(w, "DocumentName: %s\n", ci.DocumentName)
- }
- if ci.DocumentNamespace != "" {
- fmt.Fprintf(w, "DocumentNamespace: %s\n", ci.DocumentNamespace)
- }
- // print EDRs in order sorted by identifier
- edrIDs := []string{}
- for docRefID := range ci.ExternalDocumentReferences {
- edrIDs = append(edrIDs, docRefID)
- }
- sort.Strings(edrIDs)
- for _, edrID := range edrIDs {
- edr := ci.ExternalDocumentReferences[edrID]
- fmt.Fprintf(w, "ExternalDocumentRef: DocumentRef-%s %s %s:%s\n",
- edr.DocumentRefID, edr.URI, edr.Alg, edr.Checksum)
- }
if ci.LicenseListVersion != "" {
fmt.Fprintf(w, "LicenseListVersion: %s\n", ci.LicenseListVersion)
}
- for _, s := range ci.CreatorPersons {
- fmt.Fprintf(w, "Creator: Person: %s\n", s)
- }
- for _, s := range ci.CreatorOrganizations {
- fmt.Fprintf(w, "Creator: Organization: %s\n", s)
- }
- for _, s := range ci.CreatorTools {
- fmt.Fprintf(w, "Creator: Tool: %s\n", s)
+ for _, creator := range ci.Creators {
+ fmt.Fprintf(w, "Creator: %s: %s\n", creator.CreatorType, creator.Creator)
}
if ci.Created != "" {
fmt.Fprintf(w, "Created: %s\n", ci.Created)
@@ -55,9 +21,6 @@ func renderCreationInfo2_2(ci *spdx.CreationInfo2_2, w io.Writer) error {
if ci.CreatorComment != "" {
fmt.Fprintf(w, "CreatorComment: %s\n", textify(ci.CreatorComment))
}
- if ci.DocumentComment != "" {
- fmt.Fprintf(w, "DocumentComment: %s\n", textify(ci.DocumentComment))
- }
// add blank newline b/c end of a main section
fmt.Fprintf(w, "\n")
diff --git a/tvsaver/saver2v2/save_creation_info_test.go b/tvsaver/saver2v2/save_creation_info_test.go
index 404abfe..ba3c18d 100644
--- a/tvsaver/saver2v2/save_creation_info_test.go
+++ b/tvsaver/saver2v2/save_creation_info_test.go
@@ -12,53 +12,22 @@ import (
// ===== Creation Info section Saver tests =====
func TestSaver2_2CISavesText(t *testing.T) {
ci := &spdx.CreationInfo2_2{
- SPDXVersion: "SPDX-2.2",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- ExternalDocumentReferences: map[string]spdx.ExternalDocumentRef2_2{
- "spdx-go-0.0.1a": spdx.ExternalDocumentRef2_2{
- DocumentRefID: "spdx-go-0.0.1a",
- URI: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1a.cdefab.whatever",
- Alg: "SHA1",
- Checksum: "0123456701234567012345670123456701234567",
- },
- "time-1.2.3": spdx.ExternalDocumentRef2_2{
- DocumentRefID: "time-1.2.3",
- URI: "https://github.com/swinslow/spdx-docs/time/time-1.2.3.cdefab.whatever",
- Alg: "SHA1",
- Checksum: "0123456701234567012345670123456701234568",
- },
- },
LicenseListVersion: "3.9",
- CreatorPersons: []string{
- "John Doe",
- "Jane Doe (janedoe@example.com)",
- },
- CreatorOrganizations: []string{
- "John Doe, Inc.",
- "Jane Doe LLC",
- },
- CreatorTools: []string{
- "magictool1-1.0",
- "magictool2-1.0",
- "magictool3-1.0",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe", CreatorType: "Person"},
+ {Creator: "Jane Doe (janedoe@example.com)", CreatorType: "Person"},
+ {Creator: "John Doe, Inc.", CreatorType: "Organization"},
+ {Creator: "Jane Doe LLC", CreatorType: "Organization"},
+ {Creator: "magictool1-1.0", CreatorType: "Tool"},
+ {Creator: "magictool2-1.0", CreatorType: "Tool"},
+ {Creator: "magictool3-1.0", CreatorType: "Tool"},
},
- Created: "2018-10-10T06:20:00Z",
- CreatorComment: "this is a creator comment",
- DocumentComment: "this is a document comment",
+ Created: "2018-10-10T06:20:00Z",
+ CreatorComment: "this is a creator comment",
}
// what we want to get, as a buffer of bytes
- want := bytes.NewBufferString(`SPDXVersion: SPDX-2.2
-DataLicense: CC0-1.0
-SPDXID: SPDXRef-DOCUMENT
-DocumentName: spdx-go-0.0.1.abcdef
-DocumentNamespace: https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever
-ExternalDocumentRef: DocumentRef-spdx-go-0.0.1a https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1a.cdefab.whatever SHA1:0123456701234567012345670123456701234567
-ExternalDocumentRef: DocumentRef-time-1.2.3 https://github.com/swinslow/spdx-docs/time/time-1.2.3.cdefab.whatever SHA1:0123456701234567012345670123456701234568
-LicenseListVersion: 3.9
+ want := bytes.NewBufferString(`LicenseListVersion: 3.9
Creator: Person: John Doe
Creator: Person: Jane Doe (janedoe@example.com)
Creator: Organization: John Doe, Inc.
@@ -68,7 +37,6 @@ Creator: Tool: magictool2-1.0
Creator: Tool: magictool3-1.0
Created: 2018-10-10T06:20:00Z
CreatorComment: this is a creator comment
-DocumentComment: this is a document comment
`)
@@ -89,24 +57,14 @@ DocumentComment: this is a document comment
func TestSaver2_2CIOmitsOptionalFieldsIfEmpty(t *testing.T) {
// --- need at least one creator; do first for Persons ---
ci1 := &spdx.CreationInfo2_2{
- SPDXVersion: "SPDX-2.2",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- CreatorPersons: []string{
- "John Doe",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe", CreatorType: "Person"},
},
Created: "2018-10-10T06:20:00Z",
}
// what we want to get, as a buffer of bytes
- want1 := bytes.NewBufferString(`SPDXVersion: SPDX-2.2
-DataLicense: CC0-1.0
-SPDXID: SPDXRef-DOCUMENT
-DocumentName: spdx-go-0.0.1.abcdef
-DocumentNamespace: https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever
-Creator: Person: John Doe
+ want1 := bytes.NewBufferString(`Creator: Person: John Doe
Created: 2018-10-10T06:20:00Z
`)
@@ -126,24 +84,14 @@ Created: 2018-10-10T06:20:00Z
// --- need at least one creator; now switch to organization ---
ci2 := &spdx.CreationInfo2_2{
- SPDXVersion: "SPDX-2.2",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "spdx-go-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever",
- CreatorOrganizations: []string{
- "John Doe, Inc.",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe, Inc.", CreatorType: "Organization"},
},
Created: "2018-10-10T06:20:00Z",
}
// what we want to get, as a buffer of bytes
- want2 := bytes.NewBufferString(`SPDXVersion: SPDX-2.2
-DataLicense: CC0-1.0
-SPDXID: SPDXRef-DOCUMENT
-DocumentName: spdx-go-0.0.1.abcdef
-DocumentNamespace: https://github.com/swinslow/spdx-docs/spdx-go/spdx-go-0.0.1.abcdef.whatever
-Creator: Organization: John Doe, Inc.
+ want2 := bytes.NewBufferString(`Creator: Organization: John Doe, Inc.
Created: 2018-10-10T06:20:00Z
`)
diff --git a/tvsaver/saver2v2/save_document.go b/tvsaver/saver2v2/save_document.go
index 8db2363..04b482d 100644
--- a/tvsaver/saver2v2/save_document.go
+++ b/tvsaver/saver2v2/save_document.go
@@ -21,30 +21,50 @@ func RenderDocument2_2(doc *spdx.Document2_2, w io.Writer) error {
return fmt.Errorf("Document had nil CreationInfo section")
}
+ if doc.SPDXVersion != "" {
+ fmt.Fprintf(w, "SPDXVersion: %s\n", doc.SPDXVersion)
+ }
+ if doc.DataLicense != "" {
+ fmt.Fprintf(w, "DataLicense: %s\n", doc.DataLicense)
+ }
+ if doc.SPDXIdentifier != "" {
+ fmt.Fprintf(w, "SPDXID: %s\n", spdx.RenderElementID(doc.SPDXIdentifier))
+ }
+ if doc.DocumentName != "" {
+ fmt.Fprintf(w, "DocumentName: %s\n", doc.DocumentName)
+ }
+ if doc.DocumentNamespace != "" {
+ fmt.Fprintf(w, "DocumentNamespace: %s\n", doc.DocumentNamespace)
+ }
+ // print EDRs in order sorted by identifier
+ sort.Slice(doc.ExternalDocumentReferences, func(i, j int) bool {
+ return doc.ExternalDocumentReferences[i].DocumentRefID < doc.ExternalDocumentReferences[j].DocumentRefID
+ })
+ for _, edr := range doc.ExternalDocumentReferences {
+ fmt.Fprintf(w, "ExternalDocumentRef: DocumentRef-%s %s %s:%s\n",
+ edr.DocumentRefID, edr.URI, edr.Checksum.Algorithm, edr.Checksum.Value)
+ }
+ if doc.DocumentComment != "" {
+ fmt.Fprintf(w, "DocumentComment: %s\n", textify(doc.DocumentComment))
+ }
+
renderCreationInfo2_2(doc.CreationInfo, w)
- if len(doc.UnpackagedFiles) > 0 {
+ if len(doc.Files) > 0 {
fmt.Fprintf(w, "##### Unpackaged files\n\n")
- // get slice of identifiers so we can sort them
- unpackagedFileKeys := []string{}
- for k := range doc.UnpackagedFiles {
- unpackagedFileKeys = append(unpackagedFileKeys, string(k))
- }
- sort.Strings(unpackagedFileKeys)
- for _, fiID := range unpackagedFileKeys {
- fi := doc.UnpackagedFiles[spdx.ElementID(fiID)]
+ sort.Slice(doc.Files, func(i, j int) bool {
+ return doc.Files[i].FileSPDXIdentifier < doc.Files[j].FileSPDXIdentifier
+ })
+ for _, fi := range doc.Files {
renderFile2_2(fi, w)
}
}
- // get slice of Package identifiers so we can sort them
- packageKeys := []string{}
- for k := range doc.Packages {
- packageKeys = append(packageKeys, string(k))
- }
- sort.Strings(packageKeys)
- for _, pkgID := range packageKeys {
- pkg := doc.Packages[spdx.ElementID(pkgID)]
+ // sort Packages by identifier
+ sort.Slice(doc.Packages, func(i, j int) bool {
+ return doc.Packages[i].PackageSPDXIdentifier < doc.Packages[j].PackageSPDXIdentifier
+ })
+ for _, pkg := range doc.Packages {
fmt.Fprintf(w, "##### Package: %s\n\n", pkg.PackageName)
renderPackage2_2(pkg, w)
}
diff --git a/tvsaver/saver2v2/save_document_test.go b/tvsaver/saver2v2/save_document_test.go
index 1970580..552cdab 100644
--- a/tvsaver/saver2v2/save_document_test.go
+++ b/tvsaver/saver2v2/save_document_test.go
@@ -14,13 +14,8 @@ func TestSaver2_2DocumentSavesText(t *testing.T) {
// Creation Info section
ci := &spdx.CreationInfo2_2{
- SPDXVersion: "SPDX-2.2",
- DataLicense: "CC0-1.0",
- SPDXIdentifier: spdx.ElementID("DOCUMENT"),
- DocumentName: "tools-golang-0.0.1.abcdef",
- DocumentNamespace: "https://github.com/spdx/spdx-docs/tools-golang/tools-golang-0.0.1.abcdef.whatever",
- CreatorPersons: []string{
- "John Doe",
+ Creators: []spdx.Creator{
+ {Creator: "John Doe", CreatorType: "Person"},
},
Created: "2018-10-10T06:20:00Z",
}
@@ -29,51 +24,39 @@ func TestSaver2_2DocumentSavesText(t *testing.T) {
f1 := &spdx.File2_2{
FileName: "/tmp/whatever1.txt",
FileSPDXIdentifier: spdx.ElementID("File1231"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
- },
- },
- LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{"Apache-2.0"},
- FileCopyrightText: "Copyright (c) Jane Doe",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983c", Algorithm: spdx.SHA1}},
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFiles: []string{"Apache-2.0"},
+ FileCopyrightText: "Copyright (c) Jane Doe",
}
f2 := &spdx.File2_2{
FileName: "/tmp/whatever2.txt",
FileSPDXIdentifier: spdx.ElementID("File1232"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983d",
- },
- },
- LicenseConcluded: "MIT",
- LicenseInfoInFile: []string{"MIT"},
- FileCopyrightText: "Copyright (c) John Doe",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983d", Algorithm: spdx.SHA1}},
+ LicenseConcluded: "MIT",
+ LicenseInfoInFiles: []string{"MIT"},
+ FileCopyrightText: "Copyright (c) John Doe",
}
- unFiles := map[spdx.ElementID]*spdx.File2_2{
- spdx.ElementID("File1231"): f1,
- spdx.ElementID("File1232"): f2,
+ unFiles := []*spdx.File2_2{
+ f1,
+ f2,
}
// Package 1: packaged files with snippets
sn1 := &spdx.Snippet2_2{
SnippetSPDXIdentifier: "Snippet19",
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 17}, EndPointer: spdx.SnippetRangePointer{Offset: 209}}},
SnippetLicenseConcluded: "GPL-2.0-or-later",
SnippetCopyrightText: "Copyright (c) John Doe 20x6",
}
sn2 := &spdx.Snippet2_2{
SnippetSPDXIdentifier: "Snippet20",
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets"),
- SnippetByteRangeStart: 268,
- SnippetByteRangeEnd: 309,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "FileHasSnippets").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 268}, EndPointer: spdx.SnippetRangePointer{Offset: 309}}},
SnippetLicenseConcluded: "WTFPL",
SnippetCopyrightText: "NOASSERTION",
}
@@ -81,14 +64,9 @@ func TestSaver2_2DocumentSavesText(t *testing.T) {
f3 := &spdx.File2_2{
FileName: "/tmp/file-with-snippets.txt",
FileSPDXIdentifier: spdx.ElementID("FileHasSnippets"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983e",
- },
- },
- LicenseConcluded: "GPL-2.0-or-later AND WTFPL",
- LicenseInfoInFile: []string{
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983e", Algorithm: spdx.SHA1}},
+ LicenseConcluded: "GPL-2.0-or-later AND WTFPL",
+ LicenseInfoInFiles: []string{
"Apache-2.0",
"GPL-2.0-or-later",
"WTFPL",
@@ -103,15 +81,10 @@ func TestSaver2_2DocumentSavesText(t *testing.T) {
f4 := &spdx.File2_2{
FileName: "/tmp/another-file.txt",
FileSPDXIdentifier: spdx.ElementID("FileAnother"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983f",
- },
- },
- LicenseConcluded: "BSD-3-Clause",
- LicenseInfoInFile: []string{"BSD-3-Clause"},
- FileCopyrightText: "Copyright (c) Jane Doe LLC",
+ Checksums: []spdx.Checksum{{Value: "85ed0817af83a24ad8da68c2b5094de69833983f", Algorithm: spdx.SHA1}},
+ LicenseConcluded: "BSD-3-Clause",
+ LicenseInfoInFiles: []string{"BSD-3-Clause"},
+ FileCopyrightText: "Copyright (c) Jane Doe LLC",
}
pkgWith := &spdx.Package2_2{
@@ -120,7 +93,7 @@ func TestSaver2_2DocumentSavesText(t *testing.T) {
PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
FilesAnalyzed: true,
IsFilesAnalyzedTagPresent: true,
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
+ PackageVerificationCode: spdx.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
PackageLicenseConcluded: "GPL-2.0-or-later AND BSD-3-Clause AND WTFPL",
PackageLicenseInfoFromFiles: []string{
"Apache-2.0",
@@ -130,9 +103,9 @@ func TestSaver2_2DocumentSavesText(t *testing.T) {
},
PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
PackageCopyrightText: "Copyright (c) John Doe, Inc.",
- Files: map[spdx.ElementID]*spdx.File2_2{
- spdx.ElementID("FileHasSnippets"): f3,
- spdx.ElementID("FileAnother"): f4,
+ Files: []*spdx.File2_2{
+ f3,
+ f4,
},
}
@@ -172,8 +145,8 @@ blah blah blah blah`,
// Annotations
ann1 := &spdx.Annotation2_2{
- Annotator: "John Doe",
- AnnotatorType: "Person",
+ Annotator: spdx.Annotator{Annotator: "John Doe",
+ AnnotatorType: "Person"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "DOCUMENT"),
@@ -181,8 +154,8 @@ blah blah blah blah`,
}
ann2 := &spdx.Annotation2_2{
- Annotator: "John Doe, Inc.",
- AnnotatorType: "Organization",
+ Annotator: spdx.Annotator{Annotator: "John Doe, Inc.",
+ AnnotatorType: "Organization"},
AnnotationDate: "2018-10-10T17:52:00Z",
AnnotationType: "REVIEW",
AnnotationSPDXIdentifier: spdx.MakeDocElementID("", "p1"),
@@ -204,11 +177,16 @@ blah blah blah blah`,
// now, build the document
doc := &spdx.Document2_2{
- CreationInfo: ci,
- Packages: map[spdx.ElementID]*spdx.Package2_2{
- spdx.ElementID("p1"): pkgWith,
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: spdx.ElementID("DOCUMENT"),
+ DocumentName: "tools-golang-0.0.1.abcdef",
+ DocumentNamespace: "https://github.com/spdx/spdx-docs/tools-golang/tools-golang-0.0.1.abcdef.whatever",
+ CreationInfo: ci,
+ Packages: []*spdx.Package2_2{
+ pkgWith,
},
- UnpackagedFiles: unFiles,
+ Files: unFiles,
OtherLicenses: []*spdx.OtherLicense2_2{
ol1,
ol2,
diff --git a/tvsaver/saver2v2/save_file.go b/tvsaver/saver2v2/save_file.go
index ce75f31..f1684ef 100644
--- a/tvsaver/saver2v2/save_file.go
+++ b/tvsaver/saver2v2/save_file.go
@@ -17,22 +17,18 @@ func renderFile2_2(f *spdx.File2_2, w io.Writer) error {
if f.FileSPDXIdentifier != "" {
fmt.Fprintf(w, "SPDXID: %s\n", spdx.RenderElementID(f.FileSPDXIdentifier))
}
- for _, s := range f.FileType {
+ for _, s := range f.FileTypes {
fmt.Fprintf(w, "FileType: %s\n", s)
}
- if f.FileChecksums[spdx.SHA1].Value != "" {
- fmt.Fprintf(w, "FileChecksum: SHA1: %s\n", f.FileChecksums[spdx.SHA1].Value)
- }
- if f.FileChecksums[spdx.SHA256].Value != "" {
- fmt.Fprintf(w, "FileChecksum: SHA256: %s\n", f.FileChecksums[spdx.SHA256].Value)
- }
- if f.FileChecksums[spdx.MD5].Value != "" {
- fmt.Fprintf(w, "FileChecksum: MD5: %s\n", f.FileChecksums[spdx.MD5].Value)
+
+ for _, checksum := range f.Checksums {
+ fmt.Fprintf(w, "FileChecksum: %s: %s\n", checksum.Algorithm, checksum.Value)
}
+
if f.LicenseConcluded != "" {
fmt.Fprintf(w, "LicenseConcluded: %s\n", f.LicenseConcluded)
}
- for _, s := range f.LicenseInfoInFile {
+ for _, s := range f.LicenseInfoInFiles {
fmt.Fprintf(w, "LicenseInfoInFile: %s\n", s)
}
if f.LicenseComments != "" {
@@ -56,7 +52,7 @@ func renderFile2_2(f *spdx.File2_2, w io.Writer) error {
if f.FileNotice != "" {
fmt.Fprintf(w, "FileNotice: %s\n", textify(f.FileNotice))
}
- for _, s := range f.FileContributor {
+ for _, s := range f.FileContributors {
fmt.Fprintf(w, "FileContributor: %s\n", s)
}
for _, s := range f.FileAttributionTexts {
diff --git a/tvsaver/saver2v2/save_file_test.go b/tvsaver/saver2v2/save_file_test.go
index f90a1bb..c49c978 100644
--- a/tvsaver/saver2v2/save_file_test.go
+++ b/tvsaver/saver2v2/save_file_test.go
@@ -14,26 +14,17 @@ func TestSaver2_2FileSavesText(t *testing.T) {
f := &spdx.File2_2{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileType: []string{
+ FileTypes: []string{
"TEXT",
"DOCUMENTATION",
},
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
- },
- spdx.SHA256: spdx.Checksum{
- Algorithm: spdx.SHA256,
- Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
- },
- spdx.MD5: spdx.Checksum{
- Algorithm: spdx.MD5,
- Value: "624c1abb3664f4b35547e7c73864ad24",
- },
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
+ {Algorithm: spdx.SHA256, Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"},
+ {Algorithm: spdx.MD5, Value: "624c1abb3664f4b35547e7c73864ad24"},
},
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
"Apache-1.1",
},
@@ -59,7 +50,7 @@ func TestSaver2_2FileSavesText(t *testing.T) {
},
FileComment: "this is a file comment",
FileNotice: "This file may be used under either Apache-2.0 or Apache-1.1.",
- FileContributor: []string{
+ FileContributors: []string{
"John Doe jdoe@example.com",
"EvilCorp",
},
@@ -124,18 +115,16 @@ FileDependency: g.txt
func TestSaver2_2FileSavesSnippetsAlso(t *testing.T) {
sn1 := &spdx.Snippet2_2{
SnippetSPDXIdentifier: spdx.ElementID("Snippet19"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 17}, EndPointer: spdx.SnippetRangePointer{Offset: 209}}},
SnippetLicenseConcluded: "GPL-2.0-or-later",
SnippetCopyrightText: "Copyright (c) John Doe 20x6",
}
sn2 := &spdx.Snippet2_2{
SnippetSPDXIdentifier: spdx.ElementID("Snippet20"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123"),
- SnippetByteRangeStart: 268,
- SnippetByteRangeEnd: 309,
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File123").ElementRefID,
+ Ranges: []spdx.SnippetRange{{StartPointer: spdx.SnippetRangePointer{Offset: 268}, EndPointer: spdx.SnippetRangePointer{Offset: 309}}},
SnippetLicenseConcluded: "WTFPL",
SnippetCopyrightText: "NOASSERTION",
}
@@ -148,14 +137,11 @@ func TestSaver2_2FileSavesSnippetsAlso(t *testing.T) {
f := &spdx.File2_2{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
- },
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
},
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: "Copyright (c) Jane Doe",
@@ -202,14 +188,11 @@ func TestSaver2_2FileOmitsOptionalFieldsIfEmpty(t *testing.T) {
f := &spdx.File2_2{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
- },
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
},
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: "Copyright (c) Jane Doe",
@@ -243,14 +226,11 @@ func TestSaver2_2FileWrapsCopyrightMultiLine(t *testing.T) {
f := &spdx.File2_2{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
- },
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
},
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: `Copyright (c) Jane Doe
@@ -286,16 +266,13 @@ func TestSaver2_2FileWrapsCommentsAndNoticesMultiLine(t *testing.T) {
f := &spdx.File2_2{
FileName: "/tmp/whatever.txt",
FileSPDXIdentifier: spdx.ElementID("File123"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
- Algorithm: spdx.SHA1,
- Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
- },
+ Checksums: []spdx.Checksum{
+ {Algorithm: spdx.SHA1, Value: "85ed0817af83a24ad8da68c2b5094de69833983c"},
},
LicenseComments: `this is a
multi-line license comment`,
LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{
+ LicenseInfoInFiles: []string{
"Apache-2.0",
},
FileCopyrightText: "Copyright (c) Jane Doe",
diff --git a/tvsaver/saver2v2/save_package.go b/tvsaver/saver2v2/save_package.go
index 4929775..6d21a6d 100644
--- a/tvsaver/saver2v2/save_package.go
+++ b/tvsaver/saver2v2/save_package.go
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"sort"
+ "strings"
"github.com/spdx/tools-golang/spdx"
)
@@ -23,23 +24,19 @@ func renderPackage2_2(pkg *spdx.Package2_2, w io.Writer) error {
if pkg.PackageFileName != "" {
fmt.Fprintf(w, "PackageFileName: %s\n", pkg.PackageFileName)
}
- if pkg.PackageSupplierPerson != "" {
- fmt.Fprintf(w, "PackageSupplier: Person: %s\n", pkg.PackageSupplierPerson)
- }
- if pkg.PackageSupplierOrganization != "" {
- fmt.Fprintf(w, "PackageSupplier: Organization: %s\n", pkg.PackageSupplierOrganization)
- }
- if pkg.PackageSupplierNOASSERTION == true {
- fmt.Fprintf(w, "PackageSupplier: NOASSERTION\n")
- }
- if pkg.PackageOriginatorPerson != "" {
- fmt.Fprintf(w, "PackageOriginator: Person: %s\n", pkg.PackageOriginatorPerson)
- }
- if pkg.PackageOriginatorOrganization != "" {
- fmt.Fprintf(w, "PackageOriginator: Organization: %s\n", pkg.PackageOriginatorOrganization)
+ if pkg.PackageSupplier != nil && pkg.PackageSupplier.Supplier != "" {
+ if pkg.PackageSupplier.SupplierType == "" {
+ fmt.Fprintf(w, "PackageSupplier: %s\n", pkg.PackageSupplier.Supplier)
+ } else {
+ fmt.Fprintf(w, "PackageSupplier: %s: %s\n", pkg.PackageSupplier.SupplierType, pkg.PackageSupplier.Supplier)
+ }
}
- if pkg.PackageOriginatorNOASSERTION == true {
- fmt.Fprintf(w, "PackageOriginator: NOASSERTION\n")
+ if pkg.PackageOriginator != nil && pkg.PackageOriginator.Originator != "" {
+ if pkg.PackageOriginator.OriginatorType == "" {
+ fmt.Fprintf(w, "PackageOriginator: %s\n", pkg.PackageOriginator.Originator)
+ } else {
+ fmt.Fprintf(w, "PackageOriginator: %s: %s\n", pkg.PackageOriginator.OriginatorType, pkg.PackageOriginator.Originator)
+ }
}
if pkg.PackageDownloadLocation != "" {
fmt.Fprintf(w, "PackageDownloadLocation: %s\n", pkg.PackageDownloadLocation)
@@ -51,22 +48,18 @@ func renderPackage2_2(pkg *spdx.Package2_2, w io.Writer) error {
} else {
fmt.Fprintf(w, "FilesAnalyzed: false\n")
}
- if pkg.PackageVerificationCode != "" && pkg.FilesAnalyzed == true {
- if pkg.PackageVerificationCodeExcludedFile == "" {
- fmt.Fprintf(w, "PackageVerificationCode: %s\n", pkg.PackageVerificationCode)
+ if pkg.PackageVerificationCode.Value != "" && pkg.FilesAnalyzed == true {
+ if len(pkg.PackageVerificationCode.ExcludedFiles) == 0 {
+ fmt.Fprintf(w, "PackageVerificationCode: %s\n", pkg.PackageVerificationCode.Value)
} else {
- fmt.Fprintf(w, "PackageVerificationCode: %s (excludes: %s)\n", pkg.PackageVerificationCode, pkg.PackageVerificationCodeExcludedFile)
+ fmt.Fprintf(w, "PackageVerificationCode: %s (excludes: %s)\n", pkg.PackageVerificationCode.Value, strings.Join(pkg.PackageVerificationCode.ExcludedFiles, ", "))
}
}
- if pkg.PackageChecksums[spdx.SHA1].Value != "" {
- fmt.Fprintf(w, "PackageChecksum: SHA1: %s\n", pkg.PackageChecksums[spdx.SHA1].Value)
- }
- if pkg.PackageChecksums[spdx.SHA256].Value != "" {
- fmt.Fprintf(w, "PackageChecksum: SHA256: %s\n", pkg.PackageChecksums[spdx.SHA256].Value)
- }
- if pkg.PackageChecksums[spdx.MD5].Value != "" {
- fmt.Fprintf(w, "PackageChecksum: MD5: %s\n", pkg.PackageChecksums[spdx.MD5].Value)
+
+ for _, checksum := range pkg.PackageChecksums {
+ fmt.Fprintf(w, "PackageChecksum: %s: %s\n", checksum.Algorithm, checksum.Value)
}
+
if pkg.PackageHomePage != "" {
fmt.Fprintf(w, "PackageHomePage: %s\n", pkg.PackageHomePage)
}
@@ -112,14 +105,10 @@ func renderPackage2_2(pkg *spdx.Package2_2, w io.Writer) error {
fmt.Fprintf(w, "\n")
// also render any files for this package
- // get slice of File identifiers so we can sort them
- fileKeys := []string{}
- for k := range pkg.Files {
- fileKeys = append(fileKeys, string(k))
- }
- sort.Strings(fileKeys)
- for _, fiID := range fileKeys {
- fi := pkg.Files[spdx.ElementID(fiID)]
+ sort.Slice(pkg.Files, func(i, j int) bool {
+ return pkg.Files[i].FileSPDXIdentifier < pkg.Files[j].FileSPDXIdentifier
+ })
+ for _, fi := range pkg.Files {
renderFile2_2(fi, w)
}
diff --git a/tvsaver/saver2v2/save_package_test.go b/tvsaver/saver2v2/save_package_test.go
index 72d1de2..f9960f0 100644
--- a/tvsaver/saver2v2/save_package_test.go
+++ b/tvsaver/saver2v2/save_package_test.go
@@ -49,27 +49,29 @@ multi-line external ref comment`,
}
pkg := &spdx.Package2_2{
- PackageName: "p1",
- PackageSPDXIdentifier: spdx.ElementID("p1"),
- PackageVersion: "0.1.0",
- PackageFileName: "p1-0.1.0-master.tar.gz",
- PackageSupplierOrganization: "John Doe, Inc.",
- PackageOriginatorPerson: "John Doe",
- PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
- FilesAnalyzed: true,
- IsFilesAnalyzedTagPresent: true,
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
- PackageVerificationCodeExcludedFile: "p1-0.1.0.spdx",
- PackageChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
+ PackageName: "p1",
+ PackageSPDXIdentifier: spdx.ElementID("p1"),
+ PackageVersion: "0.1.0",
+ PackageFileName: "p1-0.1.0-master.tar.gz",
+ PackageSupplier: &spdx.Supplier{SupplierType: "Organization", Supplier: "John Doe, Inc."},
+ PackageOriginator: &spdx.Originator{Originator: "John Doe", OriginatorType: "Person"},
+ PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: true,
+ PackageVerificationCode: spdx.PackageVerificationCode{
+ Value: "0123456789abcdef0123456789abcdef01234567",
+ ExcludedFiles: []string{"p1-0.1.0.spdx"},
+ },
+ PackageChecksums: []spdx.Checksum{
+ {
Algorithm: spdx.SHA1,
Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
},
- spdx.SHA256: spdx.Checksum{
+ {
Algorithm: spdx.SHA256,
Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
},
- spdx.MD5: spdx.Checksum{
+ {
Algorithm: spdx.MD5,
Value: "624c1abb3664f4b35547e7c73864ad24",
},
@@ -154,26 +156,26 @@ func TestSaver2_2PackageSavesTextCombo2(t *testing.T) {
// PackageVerificationCodeExcludedFile is empty
pkg := &spdx.Package2_2{
- PackageName: "p1",
- PackageSPDXIdentifier: spdx.ElementID("p1"),
- PackageVersion: "0.1.0",
- PackageFileName: "p1-0.1.0-master.tar.gz",
- PackageSupplierNOASSERTION: true,
- PackageOriginatorOrganization: "John Doe, Inc.",
- PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
- FilesAnalyzed: true,
- IsFilesAnalyzedTagPresent: false,
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
- PackageChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
+ PackageName: "p1",
+ PackageSPDXIdentifier: spdx.ElementID("p1"),
+ PackageVersion: "0.1.0",
+ PackageFileName: "p1-0.1.0-master.tar.gz",
+ PackageSupplier: &spdx.Supplier{Supplier: "NOASSERTION"},
+ PackageOriginator: &spdx.Originator{OriginatorType: "Organization", Originator: "John Doe, Inc."},
+ PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
+ FilesAnalyzed: true,
+ IsFilesAnalyzedTagPresent: false,
+ PackageVerificationCode: spdx.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
+ PackageChecksums: []spdx.Checksum{
+ {
Algorithm: spdx.SHA1,
Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
},
- spdx.SHA256: spdx.Checksum{
+ {
Algorithm: spdx.SHA256,
Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
},
- spdx.MD5: spdx.Checksum{
+ {
Algorithm: spdx.MD5,
Value: "624c1abb3664f4b35547e7c73864ad24",
},
@@ -245,28 +247,28 @@ func TestSaver2_2PackageSavesTextCombo3(t *testing.T) {
// three PackageAttributionTexts, one with multi-line text
pkg := &spdx.Package2_2{
- PackageName: "p1",
- PackageSPDXIdentifier: spdx.ElementID("p1"),
- PackageVersion: "0.1.0",
- PackageFileName: "p1-0.1.0-master.tar.gz",
- PackageSupplierPerson: "John Doe",
- PackageOriginatorNOASSERTION: true,
- PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
- FilesAnalyzed: false,
- IsFilesAnalyzedTagPresent: true,
+ PackageName: "p1",
+ PackageSPDXIdentifier: spdx.ElementID("p1"),
+ PackageVersion: "0.1.0",
+ PackageFileName: "p1-0.1.0-master.tar.gz",
+ PackageSupplier: &spdx.Supplier{Supplier: "John Doe", SupplierType: "Person"},
+ PackageOriginator: &spdx.Originator{Originator: "NOASSERTION"},
+ PackageDownloadLocation: "http://example.com/p1/p1-0.1.0-master.tar.gz",
+ FilesAnalyzed: false,
+ IsFilesAnalyzedTagPresent: true,
// NOTE that verification code MUST be omitted from output
// since FilesAnalyzed is false
- PackageVerificationCode: "0123456789abcdef0123456789abcdef01234567",
- PackageChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
+ PackageVerificationCode: spdx.PackageVerificationCode{Value: "0123456789abcdef0123456789abcdef01234567"},
+ PackageChecksums: []spdx.Checksum{
+ {
Algorithm: spdx.SHA1,
Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
},
- spdx.SHA256: spdx.Checksum{
+ {
Algorithm: spdx.SHA256,
Value: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd",
},
- spdx.MD5: spdx.Checksum{
+ {
Algorithm: spdx.MD5,
Value: "624c1abb3664f4b35547e7c73864ad24",
},
@@ -387,29 +389,29 @@ func TestSaver2_2PackageSavesFilesIfPresent(t *testing.T) {
f1 := &spdx.File2_2{
FileName: "/tmp/whatever1.txt",
FileSPDXIdentifier: spdx.ElementID("File1231"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
+ Checksums: []spdx.Checksum{
+ {
Algorithm: spdx.SHA1,
Value: "85ed0817af83a24ad8da68c2b5094de69833983c",
},
},
- LicenseConcluded: "Apache-2.0",
- LicenseInfoInFile: []string{"Apache-2.0"},
- FileCopyrightText: "Copyright (c) Jane Doe",
+ LicenseConcluded: "Apache-2.0",
+ LicenseInfoInFiles: []string{"Apache-2.0"},
+ FileCopyrightText: "Copyright (c) Jane Doe",
}
f2 := &spdx.File2_2{
FileName: "/tmp/whatever2.txt",
FileSPDXIdentifier: spdx.ElementID("File1232"),
- FileChecksums: map[spdx.ChecksumAlgorithm]spdx.Checksum{
- spdx.SHA1: spdx.Checksum{
+ Checksums: []spdx.Checksum{
+ {
Algorithm: spdx.SHA1,
Value: "85ed0817af83a24ad8da68c2b5094de69833983d",
},
},
- LicenseConcluded: "MIT",
- LicenseInfoInFile: []string{"MIT"},
- FileCopyrightText: "Copyright (c) John Doe",
+ LicenseConcluded: "MIT",
+ LicenseInfoInFiles: []string{"MIT"},
+ FileCopyrightText: "Copyright (c) John Doe",
}
pkg := &spdx.Package2_2{
@@ -430,9 +432,9 @@ func TestSaver2_2PackageSavesFilesIfPresent(t *testing.T) {
},
PackageLicenseDeclared: "Apache-2.0 OR GPL-2.0-or-later",
PackageCopyrightText: "Copyright (c) John Doe, Inc.",
- Files: map[spdx.ElementID]*spdx.File2_2{
- spdx.ElementID("File1231"): f1,
- spdx.ElementID("File1232"): f2,
+ Files: []*spdx.File2_2{
+ f1,
+ f2,
},
}
diff --git a/tvsaver/saver2v2/save_snippet.go b/tvsaver/saver2v2/save_snippet.go
index 8423e53..4f74098 100644
--- a/tvsaver/saver2v2/save_snippet.go
+++ b/tvsaver/saver2v2/save_snippet.go
@@ -13,15 +13,18 @@ func renderSnippet2_2(sn *spdx.Snippet2_2, w io.Writer) error {
if sn.SnippetSPDXIdentifier != "" {
fmt.Fprintf(w, "SnippetSPDXID: %s\n", spdx.RenderElementID(sn.SnippetSPDXIdentifier))
}
- snFromFileIDStr := spdx.RenderDocElementID(sn.SnippetFromFileSPDXIdentifier)
+ snFromFileIDStr := spdx.RenderElementID(sn.SnippetFromFileSPDXIdentifier)
if snFromFileIDStr != "" {
fmt.Fprintf(w, "SnippetFromFileSPDXID: %s\n", snFromFileIDStr)
}
- if sn.SnippetByteRangeStart != 0 && sn.SnippetByteRangeEnd != 0 {
- fmt.Fprintf(w, "SnippetByteRange: %d:%d\n", sn.SnippetByteRangeStart, sn.SnippetByteRangeEnd)
- }
- if sn.SnippetLineRangeStart != 0 && sn.SnippetLineRangeEnd != 0 {
- fmt.Fprintf(w, "SnippetLineRange: %d:%d\n", sn.SnippetLineRangeStart, sn.SnippetLineRangeEnd)
+
+ for _, snippetRange := range sn.Ranges {
+ if snippetRange.StartPointer.Offset != 0 && snippetRange.EndPointer.Offset != 0 {
+ fmt.Fprintf(w, "SnippetByteRange: %d:%d\n", snippetRange.StartPointer.Offset, snippetRange.EndPointer.Offset)
+ }
+ if snippetRange.StartPointer.LineNumber != 0 && snippetRange.EndPointer.LineNumber != 0 {
+ fmt.Fprintf(w, "SnippetLineRange: %d:%d\n", snippetRange.StartPointer.LineNumber, snippetRange.EndPointer.LineNumber)
+ }
}
if sn.SnippetLicenseConcluded != "" {
fmt.Fprintf(w, "SnippetLicenseConcluded: %s\n", sn.SnippetLicenseConcluded)
diff --git a/tvsaver/saver2v2/save_snippet_test.go b/tvsaver/saver2v2/save_snippet_test.go
index b749c7d..da91b99 100644
--- a/tvsaver/saver2v2/save_snippet_test.go
+++ b/tvsaver/saver2v2/save_snippet_test.go
@@ -13,12 +13,18 @@ import (
func TestSaver2_2SnippetSavesText(t *testing.T) {
sn := &spdx.Snippet2_2{
SnippetSPDXIdentifier: spdx.ElementID("Snippet17"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
- SnippetLineRangeStart: 3,
- SnippetLineRangeEnd: 8,
- SnippetLicenseConcluded: "GPL-2.0-or-later",
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292").ElementRefID,
+ Ranges: []spdx.SnippetRange{
+ {
+ StartPointer: spdx.SnippetRangePointer{LineNumber: 3},
+ EndPointer: spdx.SnippetRangePointer{LineNumber: 8},
+ },
+ {
+ StartPointer: spdx.SnippetRangePointer{Offset: 17},
+ EndPointer: spdx.SnippetRangePointer{Offset: 209},
+ },
+ },
+ SnippetLicenseConcluded: "GPL-2.0-or-later",
LicenseInfoInSnippet: []string{
"GPL-2.0-or-later",
"MIT",
@@ -33,8 +39,8 @@ func TestSaver2_2SnippetSavesText(t *testing.T) {
// what we want to get, as a buffer of bytes
want := bytes.NewBufferString(`SnippetSPDXID: SPDXRef-Snippet17
SnippetFromFileSPDXID: SPDXRef-File292
-SnippetByteRange: 17:209
SnippetLineRange: 3:8
+SnippetByteRange: 17:209
SnippetLicenseConcluded: GPL-2.0-or-later
LicenseInfoInSnippet: GPL-2.0-or-later
LicenseInfoInSnippet: MIT
@@ -63,11 +69,15 @@ SnippetAttributionText: some attributions
func TestSaver2_2SnippetOmitsOptionalFieldsIfEmpty(t *testing.T) {
sn := &spdx.Snippet2_2{
SnippetSPDXIdentifier: spdx.ElementID("Snippet17"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
- SnippetLicenseConcluded: "GPL-2.0-or-later",
- SnippetCopyrightText: "Copyright (c) John Doe 20x6",
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292").ElementRefID,
+ Ranges: []spdx.SnippetRange{
+ {
+ StartPointer: spdx.SnippetRangePointer{Offset: 17},
+ EndPointer: spdx.SnippetRangePointer{Offset: 209},
+ },
+ },
+ SnippetLicenseConcluded: "GPL-2.0-or-later",
+ SnippetCopyrightText: "Copyright (c) John Doe 20x6",
}
// what we want to get, as a buffer of bytes
@@ -96,10 +106,14 @@ SnippetCopyrightText: Copyright (c) John Doe 20x6
func TestSaver2_2SnippetWrapsCopyrightMultiline(t *testing.T) {
sn := &spdx.Snippet2_2{
SnippetSPDXIdentifier: spdx.ElementID("Snippet17"),
- SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292"),
- SnippetByteRangeStart: 17,
- SnippetByteRangeEnd: 209,
- SnippetLicenseConcluded: "GPL-2.0-or-later",
+ SnippetFromFileSPDXIdentifier: spdx.MakeDocElementID("", "File292").ElementRefID,
+ Ranges: []spdx.SnippetRange{
+ {
+ StartPointer: spdx.SnippetRangePointer{Offset: 17},
+ EndPointer: spdx.SnippetRangePointer{Offset: 209},
+ },
+ },
+ SnippetLicenseConcluded: "GPL-2.0-or-later",
SnippetCopyrightText: `Copyright (c) John Doe 20x6
Copyright (c) John Doe 20x6`,
}