зеркало из https://github.com/github/go-spdx.git
Merge pull request #52 from github/ajhenry/extract-licenses
Add method for extracting licenses from expression
This commit is contained in:
Коммит
e0a077a4c3
24
README.md
24
README.md
|
@ -131,6 +131,30 @@ assert.True(valid)
|
||||||
assert.NotContains(invalidLicenses, "MIT AND APACHE-2.0")
|
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 an `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
|
## Background
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package spdxexp
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
licenses = append(licenses, *licenseNode.reconstructedLicenseString())
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses = removeDuplicateStrings(licenses)
|
||||||
|
|
||||||
|
return licenses, nil
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
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"}},
|
||||||
|
{"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)
|
||||||
|
if test.extractedLicenses == nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
list = append(list, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче