From f9e708490807d6733be3a30bf66e4a243ea521d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 07:05:24 +0000 Subject: [PATCH 01/16] Bump actions/setup-go from 3 to 4 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 2 +- .github/workflows/lint.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7be3962..09cbe86 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.18.5" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index b0d3294..8a08ddb 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.18.5" From b14ea221fcf767421d4f81662041f2cb5e0fca21 Mon Sep 17 00:00:00 2001 From: Kevin Dangoor Date: Mon, 20 Mar 2023 21:34:17 -0400 Subject: [PATCH 02/16] Add myself to CODEOWNERS I can help with reviews here. --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 6106937..6b59173 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,2 +1,2 @@ # This repository is maintained by: -* @elrayle @ajhenry +* @elrayle @ajhenry @dangoor From 3f40be4afce90356dcb1ed1182a6f4f31435b444 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Tue, 21 Mar 2023 11:09:54 -0400 Subject: [PATCH 03/16] Add go package badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3027123..d4510d0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Go Reference](https://pkg.go.dev/badge/github.com/github/go-spdx/v2@v2.1.2/spdxexp.svg)](https://pkg.go.dev/github.com/github/go-spdx/v2@v2.1.2/spdxexp) + # go-spdx Golang implementation of a checker for determining if a set of SPDX IDs satisfies an SPDX Expression. From 766b0abc03a9457af8e7f00c6ca5d0ed4acb5550 Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Thu, 13 Apr 2023 12:28:42 -0400 Subject: [PATCH 04/16] test: update tests and documentation to express spdx expression use case Signed-off-by: Christopher Phillips --- README.md | 9 +++++++++ spdxexp/satisfies_test.go | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/README.md b/README.md index d4510d0..9525f2b 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,15 @@ assert.Contains(invalidLicenses, "NON-EXISTENT-LICENSE") assert.NotContains(invalidLicenses, "MIT") ``` +#### Examples: ValidateLicenses works with SPDX expressions + +```go +valid, invalidLicenses := ValidateLicenses([]string{"MIT AND APACHE-2.0"}) +assert.True(valid) +assert.NotContains(invalidLicenses, "MIT AND APACHE-2.0") +``` + + ## Background This package was developed to support testing whether a repository's license requirements are met by an allowed-list of licenses. diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index cc32199..0a240d0 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -20,6 +20,12 @@ func TestValidateLicenses(t *testing.T) { {"Some invalid", []string{"MTI", "Apche-2.0", "GPL-2.0"}, false, []string{"MTI", "Apche-2.0"}}, {"GPL-2.0", []string{"GPL-2.0"}, true, []string{}}, {"GPL-2.0-only", []string{"GPL-2.0-only"}, true, []string{}}, + {"SPDX Expressions are valid", []string{ + "MIT AND APACHE-2.0", + "MIT AND APCHE-2.0", + "LGPL-2.1-only OR MIT OR BSD-3-Clause", + "GPL-2.0-or-later WITH Bison-exception-2.2", + }, false, []string{"MIT AND APCHE-2.0"}}, } for _, test := range tests { From 91b93971067fa21db18d098483ce2d3d81ff8727 Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Thu, 13 Apr 2023 12:31:41 -0400 Subject: [PATCH 05/16] style: small changes for golangci-lint Signed-off-by: Christopher Phillips --- spdxexp/parse_test.go | 6 +++--- spdxexp/scan.go | 6 ++---- spdxexp/scan_test.go | 8 ++++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/spdxexp/parse_test.go b/spdxexp/parse_test.go index 8ee3d9d..707331d 100644 --- a/spdxexp/parse_test.go +++ b/spdxexp/parse_test.go @@ -919,7 +919,7 @@ func TestParse(t *testing.T) { require.Equal(t, test.err, err) if test.err != nil { // when error, check that returned node is nil - var nilNode *node = nil + var nilNode *node assert.Equal(t, nilNode, startNode, "Expected nil node when error occurs.") return } @@ -1115,7 +1115,7 @@ func TestParseTokens(t *testing.T) { require.Equal(t, test.err, test.tokens.err) if test.err != nil { // when error, check that returned node is nil - var nilNode *node = nil + var nilNode *node assert.Equal(t, nilNode, startNode, "Expected nil node when error occurs.") return } @@ -1257,7 +1257,7 @@ func TestParseWith(t *testing.T) { require.Equal(t, test.err, test.tokens.err) if test.expectNil { // exception license is nil when error occurs or WITH operator is not found - var nilString *string = nil + var nilString *string assert.Equal(t, nilString, exceptionLicense) return } diff --git a/spdxexp/scan.go b/spdxexp/scan.go index 0af567c..294dbe5 100644 --- a/spdxexp/scan.go +++ b/spdxexp/scan.go @@ -269,10 +269,8 @@ func (exp *expressionStream) normalizeLicense(license string) *token { return token } } - if token := deprecatedLicenseLookup(license); token != nil { - return token - } - return nil + + return deprecatedLicenseLookup(license) } // Lookup license identifier in active and exception lists to determine if it is a supported SPDX id diff --git a/spdxexp/scan_test.go b/spdxexp/scan_test.go index 266ec62..27471b5 100644 --- a/spdxexp/scan_test.go +++ b/spdxexp/scan_test.go @@ -127,7 +127,7 @@ func TestParseToken(t *testing.T) { require.Equal(t, test.err, test.exp.err) if test.err != nil { // token is nil when error occurs or token is not recognized - var nilToken *token = nil + var nilToken *token assert.Equal(t, nilToken, tokn) return } @@ -298,7 +298,7 @@ func TestReadDocumentRef(t *testing.T) { require.Equal(t, test.err, test.exp.err) if test.err != nil { // ref should be nil when error occurs or a ref is not found - var nilToken *token = nil + var nilToken *token assert.Equal(t, nilToken, ref, "Expected nil token when error occurs.") return } @@ -331,7 +331,7 @@ func TestReadLicenseRef(t *testing.T) { require.Equal(t, test.err, test.exp.err) if test.err != nil { // ref should be nil when error occurs or a ref is not found - var nilToken *token = nil + var nilToken *token assert.Equal(t, nilToken, ref) return } @@ -371,7 +371,7 @@ func TestReadLicense(t *testing.T) { require.Equal(t, test.err, test.exp.err) if test.err != nil { // license should be nil when error occurs or a license is not found - var nilToken *token = nil + var nilToken *token assert.Equal(t, nilToken, license) return } From 26cc8c92102d9458545fa76e81f320ab2e178df5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 07:03:50 +0000 Subject: [PATCH 06/16] Bump golangci/golangci-lint-action from 3.4.0 to 3.6.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.4.0 to 3.6.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.4.0...v3.6.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 8a08ddb..e046c24 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -18,7 +18,7 @@ jobs: go-version: "1.18.5" - name: golangci-lint - uses: golangci/golangci-lint-action@v3.4.0 + uses: golangci/golangci-lint-action@v3.6.0 with: version: v1.47.3 args: --verbose --config .golangci.yaml From 55394025e97b1a876a65dfe74debd71bb7ab8837 Mon Sep 17 00:00:00 2001 From: "E. Lynette Rayle" Date: Wed, 19 Jul 2023 13:59:46 -0400 Subject: [PATCH 07/16] Add Go Playground for testing spdx.Satisfies --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9525f2b..a10b2b5 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,8 @@ to first check if all of the expressions from `allowedList` are valid. #### Examples: Satisfies returns true +[Go Playground for Satisfies](https://go.dev/play/p/Ul8H15hyEpQ) + ```go Satisfies("MIT", []string{"MIT"}) Satisfies("MIT", []string{"MIT", "Apache-2.0"}) From c1fe5d254153ac2e7299bb8ec9775d89b752ff64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 06:33:25 +0000 Subject: [PATCH 08/16] Bump golangci/golangci-lint-action from 3.6.0 to 3.7.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.6.0 to 3.7.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.6.0...v3.7.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index e046c24..215530c 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -18,7 +18,7 @@ jobs: go-version: "1.18.5" - name: golangci-lint - uses: golangci/golangci-lint-action@v3.6.0 + uses: golangci/golangci-lint-action@v3.7.0 with: version: v1.47.3 args: --verbose --config .golangci.yaml From 10de6482145bb4b214444f3dc87634efe6b35055 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 06:33:07 +0000 Subject: [PATCH 09/16] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 2 +- .github/workflows/lint.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 09cbe86..ac5e0c3 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: go-version: "1.18.5" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 215530c..e5a7c74 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: go-version: "1.18.5" From df5d42ebe2fb001c160965ea36103bc598b45a7c Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Mon, 18 Sep 2023 13:20:22 -0400 Subject: [PATCH 10/16] feat: add method for extracting licenses from expression --- spdxexp/helpers.go | 24 ++++++++++++++++++++++++ spdxexp/satisfies.go | 19 +++++++++++++++++++ spdxexp/satisfies_test.go | 22 ++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 spdxexp/helpers.go diff --git a/spdxexp/helpers.go b/spdxexp/helpers.go new file mode 100644 index 0000000..20fad38 --- /dev/null +++ b/spdxexp/helpers.go @@ -0,0 +1,24 @@ +package spdxexp + +// flatten will take an array of nested array and return +// all nested elements in an array. e.g. [[1,2,[3]],4] -> [1,2,3,4] +func flatten[T any](lists [][]T) []T { + var res []T + for _, list := range lists { + res = append(res, list...) + } + return res +} + +// removeDuplicates will remove all duplicates from a slice +func removeDuplicates[T string](sliceList []T) []T { + allKeys := make(map[T]bool) + list := []T{} + for _, item := range sliceList { + if _, value := allKeys[item]; !value { + allKeys[item] = true + list = append(list, item) + } + } + return list +} diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index abd4778..e34fce5 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -50,6 +50,25 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { return false, nil } +// ExtractLicenses extracts licenses from the given expression without duplicates. +func ExtractLicenses(expression string) ([]string, error) { + node, err := parse(expression) + if err != nil { + return nil, err + } + + expanded := node.expand(true) + licenses := make([]string, 0) + allLicenses := flatten(expanded) + for _, license := range allLicenses { + licenses = append(licenses, license.lic.license) + } + + licenses = removeDuplicates(licenses) + + return licenses, nil +} + // stringsToNodes converts an array of single license strings to to an array of license nodes. func stringsToNodes(licenseStrings []string) ([]*node, error) { nodes := make([]*node, len(licenseStrings)) diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index 0a240d0..2468e1b 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -37,6 +37,28 @@ func TestValidateLicenses(t *testing.T) { } } +func TestExtractLicenses(t *testing.T) { + tests := []struct { + name string + inputExpression string + extractedLicenses []string + }{ + {"Single license", "MIT", []string{"MIT"}}, + {"AND'ed licenses", "MIT AND Apache-2.0", []string{"MIT", "Apache-2.0"}}, + {"AND'ed & OR'ed licenses", "(MIT AND Apache-2.0) OR GPL-3.0", []string{"GPL-3.0", "MIT", "Apache-2.0"}}, + {"ONLY modifiers", "LGPL-2.1-only OR MIT OR BSD-3-Clause", []string{"MIT", "BSD-3-Clause", "LGPL-2.1-only"}}, + {"WITH modifiers", "GPL-2.0-or-later WITH Bison-exception-2.2", []string{"GPL-2.0-or-later"}}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + licenses, err := ExtractLicenses(test.inputExpression) + assert.ElementsMatch(t, test.extractedLicenses, licenses) + assert.NoError(t, err) + }) + } +} + // TestSatisfiesSingle lets you quickly test a single call to Satisfies with a specific license expression and allowed list of licenses. // To test a different expression, change the expression, allowed licenses, and expected result in the function body. // TO RUN: go test ./expression -run TestSatisfiesSingle From cb36f68515b092bac5e1ceb2c10fb8ffd4edb1f3 Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Mon, 18 Sep 2023 13:28:05 -0400 Subject: [PATCH 11/16] docs: add public method docs --- spdxexp/satisfies.go | 1 + 1 file changed, 1 insertion(+) diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index e34fce5..c61701f 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -51,6 +51,7 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { } // ExtractLicenses extracts licenses from the given expression without duplicates. +// Returns an array of licenses or error if error occurs during processing. func ExtractLicenses(expression string) ([]string, error) { node, err := parse(expression) if err != nil { From 674a5c96bf2c1a6e8ecad3dd26243b90c9265830 Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Mon, 18 Sep 2023 16:45:00 -0400 Subject: [PATCH 12/16] fix: Make modifiers present and more to extracts file --- spdxexp/extracts.go | 27 +++++++++++++++++++++++++++ spdxexp/extracts_test.go | 29 +++++++++++++++++++++++++++++ spdxexp/helpers.go | 8 ++++---- spdxexp/satisfies.go | 20 -------------------- spdxexp/satisfies_test.go | 22 ---------------------- 5 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 spdxexp/extracts.go create mode 100644 spdxexp/extracts_test.go diff --git a/spdxexp/extracts.go b/spdxexp/extracts.go new file mode 100644 index 0000000..2d8e59c --- /dev/null +++ b/spdxexp/extracts.go @@ -0,0 +1,27 @@ +package spdxexp + +import "errors" + +// ExtractLicenses extracts licenses from the given expression without duplicates. +// Returns an array of licenses or error if error occurs during processing. +func ExtractLicenses(expression string) ([]string, error) { + node, err := parse(expression) + if err != nil { + return nil, err + } + + expanded := node.expand(true) + licenses := make([]string, 0) + allLicenses := flatten(expanded) + for _, licenseNode := range allLicenses { + if licenseNode == nil { + return nil, errors.New("license node is nil") + } + + licenses = append(licenses, *licenseNode.reconstructedLicenseString()) + } + + licenses = removeDuplicateStrings(licenses) + + return licenses, nil +} diff --git a/spdxexp/extracts_test.go b/spdxexp/extracts_test.go new file mode 100644 index 0000000..02f0d4c --- /dev/null +++ b/spdxexp/extracts_test.go @@ -0,0 +1,29 @@ +package spdxexp + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestExtractLicenses(t *testing.T) { + tests := []struct { + name string + inputExpression string + extractedLicenses []string + }{ + {"Single license", "MIT", []string{"MIT"}}, + {"AND'ed licenses", "MIT AND Apache-2.0", []string{"MIT", "Apache-2.0"}}, + {"AND'ed & OR'ed licenses", "(MIT AND Apache-2.0) OR GPL-3.0", []string{"GPL-3.0", "MIT", "Apache-2.0"}}, + {"ONLY modifiers", "LGPL-2.1-only OR MIT OR BSD-3-Clause", []string{"MIT", "BSD-3-Clause", "LGPL-2.1-only"}}, + {"WITH modifiers", "GPL-2.0-or-later WITH Bison-exception-2.2", []string{"GPL-2.0-or-later+ WITH Bison-exception-2.2"}}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + licenses, err := ExtractLicenses(test.inputExpression) + assert.ElementsMatch(t, test.extractedLicenses, licenses) + assert.NoError(t, err) + }) + } +} diff --git a/spdxexp/helpers.go b/spdxexp/helpers.go index 20fad38..8ad73df 100644 --- a/spdxexp/helpers.go +++ b/spdxexp/helpers.go @@ -10,10 +10,10 @@ func flatten[T any](lists [][]T) []T { return res } -// removeDuplicates will remove all duplicates from a slice -func removeDuplicates[T string](sliceList []T) []T { - allKeys := make(map[T]bool) - list := []T{} +// removeDuplicateStrings will remove all duplicates from a slice +func removeDuplicateStrings(sliceList []string) []string { + allKeys := make(map[string]bool) + list := []string{} for _, item := range sliceList { if _, value := allKeys[item]; !value { allKeys[item] = true diff --git a/spdxexp/satisfies.go b/spdxexp/satisfies.go index c61701f..abd4778 100644 --- a/spdxexp/satisfies.go +++ b/spdxexp/satisfies.go @@ -50,26 +50,6 @@ func Satisfies(testExpression string, allowedList []string) (bool, error) { return false, nil } -// ExtractLicenses extracts licenses from the given expression without duplicates. -// Returns an array of licenses or error if error occurs during processing. -func ExtractLicenses(expression string) ([]string, error) { - node, err := parse(expression) - if err != nil { - return nil, err - } - - expanded := node.expand(true) - licenses := make([]string, 0) - allLicenses := flatten(expanded) - for _, license := range allLicenses { - licenses = append(licenses, license.lic.license) - } - - licenses = removeDuplicates(licenses) - - return licenses, nil -} - // stringsToNodes converts an array of single license strings to to an array of license nodes. func stringsToNodes(licenseStrings []string) ([]*node, error) { nodes := make([]*node, len(licenseStrings)) diff --git a/spdxexp/satisfies_test.go b/spdxexp/satisfies_test.go index 2468e1b..0a240d0 100644 --- a/spdxexp/satisfies_test.go +++ b/spdxexp/satisfies_test.go @@ -37,28 +37,6 @@ func TestValidateLicenses(t *testing.T) { } } -func TestExtractLicenses(t *testing.T) { - tests := []struct { - name string - inputExpression string - extractedLicenses []string - }{ - {"Single license", "MIT", []string{"MIT"}}, - {"AND'ed licenses", "MIT AND Apache-2.0", []string{"MIT", "Apache-2.0"}}, - {"AND'ed & OR'ed licenses", "(MIT AND Apache-2.0) OR GPL-3.0", []string{"GPL-3.0", "MIT", "Apache-2.0"}}, - {"ONLY modifiers", "LGPL-2.1-only OR MIT OR BSD-3-Clause", []string{"MIT", "BSD-3-Clause", "LGPL-2.1-only"}}, - {"WITH modifiers", "GPL-2.0-or-later WITH Bison-exception-2.2", []string{"GPL-2.0-or-later"}}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - licenses, err := ExtractLicenses(test.inputExpression) - assert.ElementsMatch(t, test.extractedLicenses, licenses) - assert.NoError(t, err) - }) - } -} - // TestSatisfiesSingle lets you quickly test a single call to Satisfies with a specific license expression and allowed list of licenses. // To test a different expression, change the expression, allowed licenses, and expected result in the function body. // TO RUN: go test ./expression -run TestSatisfiesSingle From 16353ede453549eb59f7798243b003c6937ae16a Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Tue, 19 Sep 2023 09:41:26 -0400 Subject: [PATCH 13/16] test: update to include error test --- spdxexp/extracts_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spdxexp/extracts_test.go b/spdxexp/extracts_test.go index 02f0d4c..d9e1b67 100644 --- a/spdxexp/extracts_test.go +++ b/spdxexp/extracts_test.go @@ -17,13 +17,18 @@ func TestExtractLicenses(t *testing.T) { {"AND'ed & OR'ed licenses", "(MIT AND Apache-2.0) OR GPL-3.0", []string{"GPL-3.0", "MIT", "Apache-2.0"}}, {"ONLY modifiers", "LGPL-2.1-only OR MIT OR BSD-3-Clause", []string{"MIT", "BSD-3-Clause", "LGPL-2.1-only"}}, {"WITH modifiers", "GPL-2.0-or-later WITH Bison-exception-2.2", []string{"GPL-2.0-or-later+ WITH Bison-exception-2.2"}}, + {"Invalid SPDX expression", "MIT OR INVALID", nil}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { licenses, err := ExtractLicenses(test.inputExpression) assert.ElementsMatch(t, test.extractedLicenses, licenses) - assert.NoError(t, err) + if test.extractedLicenses == nil { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } }) } } From 7fe1a57f224bfb7bad17dc0783a9e94717048f24 Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Tue, 19 Sep 2023 09:42:04 -0400 Subject: [PATCH 14/16] fix: remove nil guard --- spdxexp/extracts.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spdxexp/extracts.go b/spdxexp/extracts.go index 2d8e59c..55afff3 100644 --- a/spdxexp/extracts.go +++ b/spdxexp/extracts.go @@ -1,7 +1,5 @@ package spdxexp -import "errors" - // ExtractLicenses extracts licenses from the given expression without duplicates. // Returns an array of licenses or error if error occurs during processing. func ExtractLicenses(expression string) ([]string, error) { @@ -14,10 +12,6 @@ func ExtractLicenses(expression string) ([]string, error) { licenses := make([]string, 0) allLicenses := flatten(expanded) for _, licenseNode := range allLicenses { - if licenseNode == nil { - return nil, errors.New("license node is nil") - } - licenses = append(licenses, *licenseNode.reconstructedLicenseString()) } From 4f63854de4e185fa77290cab8f026aa32bd15b81 Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Tue, 19 Sep 2023 09:45:34 -0400 Subject: [PATCH 15/16] docs: update docs to include extract licenses --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index a10b2b5..258aee7 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,30 @@ assert.True(valid) assert.NotContains(invalidLicenses, "MIT AND APACHE-2.0") ``` +### ExtractLicenses + +```go +func ExtractLicenses(expression string) ([]string, error) +``` + +Function `ExtractLicenses` is used to extract licenses from the given expression without duplicates. + +**parameter: expression** + +`expression` is an SPDX expression string. + +**returns** + +Function `ExtractLicenses` has 2 return values. First is `[]string` which contains all of the SPDX licenses without duplicates. + +The second return value is a `error` which is not `nil` if the given expression is not a valid SPDX expression. + +#### Example + +```go +licenses, err := ExtractLicenses("(MIT AND APACHE-2.0) OR (APACHE-2.0)") +assert.Equal(licenses, []string{"MIT", "Apache-2.0"}) +``` ## Background From 0f05021d0fe4c46f1938f44d7bd606ae30a8eedc Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Tue, 19 Sep 2023 10:01:16 -0400 Subject: [PATCH 16/16] docs: update readme with extractlicenses --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 258aee7..093b1a4 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ Function `ExtractLicenses` is used to extract licenses from the given expression Function `ExtractLicenses` has 2 return values. First is `[]string` which contains all of the SPDX licenses without duplicates. -The second return value is a `error` which is not `nil` if the given expression is not a valid SPDX expression. +The second return value is an `error` which is not `nil` if the given expression is not a valid SPDX expression. #### Example