diff --git a/assets/compatibility/Apache-2.0.yaml b/assets/compatibility/Apache-2.0.yaml index 752f871..4111a24 100644 --- a/assets/compatibility/Apache-2.0.yaml +++ b/assets/compatibility/Apache-2.0.yaml @@ -89,3 +89,22 @@ incompatible: - CPOL-1.02 - NPL-1.0 - NPL-1.1 + +weak-compatible: + - CDDL-1.0 + - CDDL-1.1 + - CPL-1.0 + - EPL-1.0 + - EPL-2.0 + - ErlPL-1.1 + - IPA + - IPL-1.0 + - LicenseRef-scancode-ubuntu-font-1.0 + - LicenseRef-scancode-unrar + - MPL-1.0 + - MPL-1.1 + - MPL-2.0 + - OFL-1.1 + - OSL-3.0 + - Ruby + - SPL-1.0 \ No newline at end of file diff --git a/commands/deps_check.go b/commands/deps_check.go index 8073d0b..87aab07 100644 --- a/commands/deps_check.go +++ b/commands/deps_check.go @@ -26,6 +26,15 @@ import ( "github.com/apache/skywalking-eyes/pkg/deps" ) +var weakCompatible bool + +func init() { + DepsCheckCommand.PersistentFlags().BoolVarP(&weakCompatible, "weak-compatible", "w", false, + "if set to true, treat the weak-compatible licenses as compatible in dependencies check. "+ + "Note: when set to true, make sure to manually confirm that weak-compatible licenses "+ + "are used under the required conditions.") +} + var DepsCheckCommand = &cobra.Command{ Use: "check", Aliases: []string{"c"}, @@ -34,7 +43,7 @@ var DepsCheckCommand = &cobra.Command{ var errors []error configDeps := Config.Dependencies() for _, header := range Config.Headers() { - if err := deps.Check(header.License.SpdxID, configDeps); err != nil { + if err := deps.Check(header.License.SpdxID, configDeps, weakCompatible); err != nil { errors = append(errors, err) } } diff --git a/pkg/deps/check.go b/pkg/deps/check.go index f5c663a..04e8301 100644 --- a/pkg/deps/check.go +++ b/pkg/deps/check.go @@ -30,8 +30,9 @@ import ( ) type CompatibilityMatrix struct { - Compatible []string `yaml:"compatible"` - Incompatible []string `yaml:"incompatible"` + Compatible []string `yaml:"compatible"` + Incompatible []string `yaml:"incompatible"` + WeakCompatible []string `yaml:"weak-compatible"` } var matrices = make(map[string]CompatibilityMatrix) @@ -63,7 +64,7 @@ func init() { } } -func Check(mainLicenseSpdxID string, config *ConfigDeps) error { +func Check(mainLicenseSpdxID string, config *ConfigDeps, weakCompatible bool) error { matrix := matrices[mainLicenseSpdxID] report := Report{} @@ -71,7 +72,7 @@ func Check(mainLicenseSpdxID string, config *ConfigDeps) error { return nil } - return CheckWithMatrix(mainLicenseSpdxID, &matrix, &report) + return CheckWithMatrix(mainLicenseSpdxID, &matrix, &report, weakCompatible) } func compare(list []string, spdxID string) bool { @@ -99,16 +100,22 @@ func compareAny(spdxIDs []string, compare func(spdxID string) bool) bool { return false } -func CheckWithMatrix(mainLicenseSpdxID string, matrix *CompatibilityMatrix, report *Report) error { +func compareCompatible(matrix *CompatibilityMatrix, spdxID string, weakCompatible bool) bool { + if weakCompatible { + return compare(matrix.Compatible, spdxID) || compare(matrix.WeakCompatible, spdxID) + } + return compare(matrix.Compatible, spdxID) +} + +func CheckWithMatrix(mainLicenseSpdxID string, matrix *CompatibilityMatrix, report *Report, weakCompatible bool) error { var incompatibleResults []*Result var unknownResults []*Result for _, result := range append(report.Resolved, report.Skipped...) { operator, spdxIDs := parseLicenseExpression(result.LicenseSpdxID) - switch operator { case LicenseOperatorAND: if compareAll(spdxIDs, func(spdxID string) bool { - return compare(matrix.Compatible, spdxID) + return compareCompatible(matrix, spdxID, weakCompatible) }) { continue } @@ -120,7 +127,7 @@ func CheckWithMatrix(mainLicenseSpdxID string, matrix *CompatibilityMatrix, repo case LicenseOperatorOR: if compareAny(spdxIDs, func(spdxID string) bool { - return compare(matrix.Compatible, spdxID) + return compareCompatible(matrix, spdxID, weakCompatible) }) { continue } @@ -134,6 +141,9 @@ func CheckWithMatrix(mainLicenseSpdxID string, matrix *CompatibilityMatrix, repo if compatible := compare(matrix.Compatible, spdxIDs[0]); compatible { continue } + if weakCompatible && compare(matrix.WeakCompatible, spdxIDs[0]) { + continue + } if incompatible := compare(matrix.Incompatible, spdxIDs[0]); incompatible { incompatibleResults = append(incompatibleResults, result) continue diff --git a/pkg/deps/check_test.go b/pkg/deps/check_test.go index db4a250..2799991 100644 --- a/pkg/deps/check_test.go +++ b/pkg/deps/check_test.go @@ -18,9 +18,10 @@ package deps_test import ( - "github.com/apache/skywalking-eyes/pkg/deps" "strings" "testing" + + "github.com/apache/skywalking-eyes/pkg/deps" ) var TestMatrix = deps.CompatibilityMatrix{ @@ -52,6 +53,9 @@ var TestMatrix = deps.CompatibilityMatrix{ "GPL-2.0-only", "GPL-2.0-or-later", }, + WeakCompatible: []string{ + "MPL-2.0", + }, } func TestCheckWithMatrix(t *testing.T) { @@ -62,7 +66,7 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "Apache-2.0", }, }, - }); err != nil { + }, false); err != nil { t.Errorf("Shouldn't return error") } @@ -77,7 +81,7 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "LGPL-2.0", }, }, - }); err == nil { + }, false); err == nil { t.Errorf("Should return error") } else if !strings.Contains(err.Error(), "Bar | LGPL-2.0") { t.Errorf("Should return error and contains dependency Bar, now is `%s`", err.Error()) @@ -96,7 +100,7 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "Unknown", }, }, - }); err == nil { + }, false); err == nil { t.Errorf("Should return error") } else if !strings.Contains(err.Error(), "Bar | Unknown") { t.Errorf("Should return error and has dependency Bar, now is `%s`", err.Error()) @@ -109,7 +113,7 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "Apache-2.0 OR MIT", }, }, - }); err != nil { + }, false); err != nil { t.Errorf("Shouldn't return error") } @@ -120,7 +124,7 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "GPL-3.0 and GPL-3.0-or-later", }, }, - }); err == nil { + }, false); err == nil { t.Errorf("Should return error") } @@ -131,7 +135,7 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "LGPL-2.1-only AND MIT AND BSD-2-Clause", }, }, - }); err == nil { + }, false); err == nil { t.Errorf("Should return error") } @@ -142,7 +146,29 @@ func TestCheckWithMatrix(t *testing.T) { LicenseSpdxID: "GPL-2.0-or-later WITH Bison-exception-2.2", }, }, - }); err == nil { + }, false); err == nil { t.Errorf("Should return error") } + + if err := deps.CheckWithMatrix("Apache-2.0", &TestMatrix, &deps.Report{ + Resolved: []*deps.Result{ + { + Dependency: "Foo", + LicenseSpdxID: "MPL-2.0", + }, + }, + }, false); err == nil { + t.Errorf("Should return error since weak-compatible is turned off") + } + + if err := deps.CheckWithMatrix("Apache-2.0", &TestMatrix, &deps.Report{ + Resolved: []*deps.Result{ + { + Dependency: "Bar", + LicenseSpdxID: "MPL-2.0", + }, + }, + }, true); err != nil { + t.Errorf("Shouldn't return error") + } }