-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from github/ajhenry/extract-licenses
Add method for extracting licenses from expression
- Loading branch information
Showing
4 changed files
with
103 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |