aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Winslow <steve@swinslow.net>2020-06-14 15:35:55 -0400
committerSteve Winslow <steve@swinslow.net>2020-06-14 15:35:55 -0400
commitdfaf5f3e3ed8a977d4ba1783ec6b95afa3faa150 (patch)
tree6ad3c33eb2df2918d319452fb182cdecfb6c4c23
parentaa88812312f0f42b5e3646d5bab8e3144614557f (diff)
downloadspdx-tools-dfaf5f3e3ed8a977d4ba1783ec6b95afa3faa150.tar.gz
Add idsearcher and tests for 2.2
Signed-off-by: Steve Winslow <steve@swinslow.net>
-rw-r--r--idsearcher/idsearcher.go136
-rw-r--r--idsearcher/idsearcher_test.go14
2 files changed, 138 insertions, 12 deletions
diff --git a/idsearcher/idsearcher.go b/idsearcher/idsearcher.go
index 0d40674..3982109 100644
--- a/idsearcher/idsearcher.go
+++ b/idsearcher/idsearcher.go
@@ -18,10 +18,12 @@ import (
"github.com/spdx/tools-golang/utils"
)
-// Config is a collection of configuration settings for docbuilder
+// ===== 2.1 Searcher functions =====
+
+// Config2_1 is a collection of configuration settings for docbuilder
// (for version 2.1 SPDX Documents). A few mandatory fields are set here
// so that they can be repeatedly reused in multiple calls to Build2_1.
-type Config struct {
+type Config2_1 struct {
// NamespacePrefix should be a URI representing a prefix for the
// namespace with which the SPDX Document will be associated.
// It will be used in the DocumentNamespace field in the CreationInfo
@@ -41,14 +43,14 @@ type Config struct {
SearcherPathsIgnored []string
}
-// BuildIDsDocument creates an SPDX Document (version 2.1) and searches for
+// BuildIDsDocument2_1 creates an SPDX Document (version 2.1) and searches for
// short-form IDs in each file, filling in license fields as appropriate. It
// returns that document or error if any is encountered. Arguments:
// - packageName: name of package / directory
// - dirRoot: path to directory to be analyzed
// - namespacePrefix: URI representing a prefix for the
// namespace with which the SPDX Document will be associated
-func BuildIDsDocument(packageName string, dirRoot string, idconfig *Config) (*spdx.Document2_1, error) {
+func BuildIDsDocument2_1(packageName string, dirRoot string, idconfig *Config2_1) (*spdx.Document2_1, error) {
// first, build the Document using builder
bconfig := &builder.Config2_1{
NamespacePrefix: idconfig.NamespacePrefix,
@@ -140,7 +142,131 @@ func BuildIDsDocument(packageName string, dirRoot string, idconfig *Config) (*sp
return doc, nil
}
-// ===== Utility functions =====
+// ===== 2.2 Searcher functions =====
+
+// Config2_2 is a collection of configuration settings for docbuilder
+// (for version 2.2 SPDX Documents). A few mandatory fields are set here
+// so that they can be repeatedly reused in multiple calls to Build2_2.
+type Config2_2 struct {
+ // NamespacePrefix should be a URI representing a prefix for the
+ // namespace with which the SPDX Document will be associated.
+ // It will be used in the DocumentNamespace field in the CreationInfo
+ // section, followed by the per-Document package name and a random UUID.
+ NamespacePrefix string
+
+ // BuilderPathsIgnored lists certain paths to be omitted from the built
+ // document. Each string should be a path, relative to the package's
+ // dirRoot, to a specific file or (for all files in a directory) ending
+ // in a slash. Prefix the string with "**" to omit all instances of that
+ // file / directory, regardless of where it is in the file tree.
+ BuilderPathsIgnored []string
+
+ // SearcherPathsIgnored lists certain paths that should not be searched
+ // by idsearcher, even if those paths have Files present. It uses the
+ // same format as BuilderPathsIgnored.
+ SearcherPathsIgnored []string
+}
+
+// BuildIDsDocument2_2 creates an SPDX Document (version 2.2) and searches for
+// short-form IDs in each file, filling in license fields as appropriate. It
+// returns that document or error if any is encountered. Arguments:
+// - packageName: name of package / directory
+// - dirRoot: path to directory to be analyzed
+// - namespacePrefix: URI representing a prefix for the
+// namespace with which the SPDX Document will be associated
+func BuildIDsDocument2_2(packageName string, dirRoot string, idconfig *Config2_2) (*spdx.Document2_2, error) {
+ // first, build the Document using builder
+ bconfig := &builder.Config2_2{
+ NamespacePrefix: idconfig.NamespacePrefix,
+ CreatorType: "Tool",
+ Creator: "github.com/spdx/tools-golang/idsearcher",
+ PathsIgnored: idconfig.BuilderPathsIgnored,
+ }
+ doc, err := builder.Build2_2(packageName, dirRoot, bconfig)
+ if err != nil {
+ return nil, err
+ }
+ if doc == nil {
+ return nil, fmt.Errorf("builder returned nil Document")
+ }
+ if doc.Packages == nil {
+ return nil, fmt.Errorf("builder returned nil Packages map")
+ }
+ if len(doc.Packages) != 1 {
+ return nil, fmt.Errorf("builder returned %d Packages", len(doc.Packages))
+ }
+
+ // now, walk through each file and find its licenses (if any)
+ pkg := doc.Packages[spdx.ElementID("Package-"+packageName)]
+ if pkg == nil {
+ return nil, fmt.Errorf("builder returned nil Package")
+ }
+ if pkg.Files == nil {
+ return nil, fmt.Errorf("builder returned nil Files in Package")
+ }
+ licsForPackage := map[string]int{}
+ for _, f := range pkg.Files {
+ // start by initializing / clearing values
+ f.LicenseInfoInFile = []string{"NOASSERTION"}
+ f.LicenseConcluded = "NOASSERTION"
+
+ // check whether the searcher should ignore this file
+ if utils.ShouldIgnore(f.FileName, idconfig.SearcherPathsIgnored) {
+ continue
+ }
+
+ fPath := filepath.Join(dirRoot, f.FileName)
+ // FIXME this is not preferable -- ignoring error
+ ids, _ := searchFileIDs(fPath)
+ // FIXME for now, proceed onwards with whatever IDs we obtained.
+ // FIXME instead of ignoring the error, should probably either log it,
+ // FIXME and/or enable the caller to configure what should happen.
+
+ // separate out for this file's licenses
+ licsForFile := map[string]int{}
+ licsParens := []string{}
+ for _, lid := range ids {
+ // get individual elements and add for file and package
+ licElements := getIndividualLicenses(lid)
+ for _, elt := range licElements {
+ licsForFile[elt] = 1
+ licsForPackage[elt] = 1
+ }
+ // parenthesize if needed and add to slice for joining
+ licsParens = append(licsParens, makeElement(lid))
+ }
+
+ // OK -- now we can fill in the file's details, or NOASSERTION if none
+ if len(licsForFile) > 0 {
+ f.LicenseInfoInFile = []string{}
+ for lic := range licsForFile {
+ f.LicenseInfoInFile = append(f.LicenseInfoInFile, lic)
+ }
+ sort.Strings(f.LicenseInfoInFile)
+ // avoid adding parens and joining for single-ID items
+ if len(licsParens) == 1 {
+ f.LicenseConcluded = ids[0]
+ } else {
+ f.LicenseConcluded = strings.Join(licsParens, " AND ")
+ }
+ }
+ }
+
+ // and finally, we can fill in the package's details
+ if len(licsForPackage) == 0 {
+ pkg.PackageLicenseInfoFromFiles = []string{"NOASSERTION"}
+ } else {
+ pkg.PackageLicenseInfoFromFiles = []string{}
+ for lic := range licsForPackage {
+ pkg.PackageLicenseInfoFromFiles = append(pkg.PackageLicenseInfoFromFiles, lic)
+ }
+ sort.Strings(pkg.PackageLicenseInfoFromFiles)
+ }
+
+ return doc, nil
+}
+
+// ===== Utility functions (not version-specific) =====
func searchFileIDs(filePath string) ([]string, error) {
idsMap := map[string]int{}
ids := []string{}
diff --git a/idsearcher/idsearcher_test.go b/idsearcher/idsearcher_test.go
index c9c6285..d6e2bfa 100644
--- a/idsearcher/idsearcher_test.go
+++ b/idsearcher/idsearcher_test.go
@@ -8,15 +8,15 @@ import (
"github.com/spdx/tools-golang/spdx"
)
-// ===== Searcher top-level function tests =====
+// ===== 2.1 Searcher top-level function tests =====
func TestSearcherCanFillInIDs(t *testing.T) {
packageName := "project2"
dirRoot := "../testdata/project2/"
- config := &Config{
+ config := &Config2_1{
NamespacePrefix: "https://github.com/swinslow/spdx-docs/spdx-go/testdata-",
}
- doc, err := BuildIDsDocument(packageName, dirRoot, config)
+ doc, err := BuildIDsDocument2_1(packageName, dirRoot, config)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
@@ -180,7 +180,7 @@ func TestSearcherCanFillInIDs(t *testing.T) {
func TestSearcherCanFillInIDsAndIgnorePaths(t *testing.T) {
packageName := "project3"
dirRoot := "../testdata/project3/"
- config := &Config{
+ config := &Config2_1{
NamespacePrefix: "https://github.com/swinslow/spdx-docs/spdx-go/testdata-",
BuilderPathsIgnored: []string{
"**/ignoredir/",
@@ -193,7 +193,7 @@ func TestSearcherCanFillInIDsAndIgnorePaths(t *testing.T) {
},
}
- doc, err := BuildIDsDocument(packageName, dirRoot, config)
+ doc, err := BuildIDsDocument2_1(packageName, dirRoot, config)
if err != nil {
t.Fatalf("expected nil error, got %v", err)
}
@@ -287,11 +287,11 @@ func TestSearcherCanFillInIDsAndIgnorePaths(t *testing.T) {
func TestSearcherFailsWithInvalidPath(t *testing.T) {
packageName := "project2"
dirRoot := "./oops/invalid"
- config := &Config{
+ config := &Config2_1{
NamespacePrefix: "whatever",
}
- _, err := BuildIDsDocument(packageName, dirRoot, config)
+ _, err := BuildIDsDocument2_1(packageName, dirRoot, config)
if err == nil {
t.Fatalf("expected non-nil error, got nil")
}