blob: 11395ec6be4976969db31c221f82fd89fde5127f [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package checklicenses
import (
"context"
"errors"
"os"
"path/filepath"
"runtime/trace"
"sort"
"strings"
)
// Licenses is an object that facilitates operations on each License object in bulk
type Licenses struct {
licenses []*License
}
// NewLicenses returns a Licenses object with each license pattern loaded from
// the .lic folder location specified in Config
func NewLicenses(ctx context.Context, config *Config) (*Licenses, error) {
defer trace.StartRegion(ctx, "NewLicenses").End()
l := &Licenses{}
err := filepath.Walk(config.LicensePatternDir,
func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
license, err := NewLicense(path, config)
if err != nil {
return err
}
l.licenses = append(l.licenses, license)
return nil
})
if err != nil {
return nil, err
}
if len(l.licenses) == 0 {
return nil, errors.New("no licenses")
}
sort.Sort(licenseByPattern(l.licenses))
return l, nil
}
func (l *Licenses) GetFilesWithProhibitedLicenses() []string {
var filesWithProhibitedLicenses []string
set := map[string]bool{}
for _, license := range l.licenses {
if license.ValidType {
continue
}
for _, match := range license.matches {
for _, path := range match.files {
if _, found := set[path]; !found && !contains(license.AllowedDirs, path) {
set[path] = true
filesWithProhibitedLicenses = append(filesWithProhibitedLicenses, path)
}
}
}
}
return filesWithProhibitedLicenses
}
func (l *Licenses) GetFilesWithBadLicenseUsage() []string {
var filesWithBadLicenseUsage []string
set := map[string]bool{}
for _, license := range l.licenses {
if len(license.BadLicenseUsage) > 0 {
for _, path := range license.BadLicenseUsage {
if _, found := set[path]; !found {
set[path] = true
filesWithBadLicenseUsage = append(filesWithBadLicenseUsage, path)
}
}
}
}
return filesWithBadLicenseUsage
}
func CheckLicenseAllowList(license *License, path string) bool {
var licenseAllowed = true
if len(license.AllowedDirs) > 0 && !contains(license.AllowedDirs, path) {
license.BadLicenseUsage = append(license.BadLicenseUsage, path)
licenseAllowed = false
}
return licenseAllowed
}
func (l *Licenses) MatchSingleLicenseFile(data []byte, path string, metrics *Metrics, ft *FileTree) {
for _, license := range l.licenses {
if license.Search(data, path) && CheckLicenseAllowList(license, path) {
metrics.increment("num_single_license_file_match")
ft.Lock()
ft.SingleLicenseFiles[path] = append(ft.SingleLicenseFiles[path], license)
ft.Unlock()
}
}
}
// MatchFile returns true if any License matches input data
// along with the license that matched. It returns false and nil
// if there were no matches.
func (l *Licenses) MatchFile(data []byte, path string, metrics *Metrics) (bool, *License) {
for _, license := range l.licenses {
if license.Search(data, path) && CheckLicenseAllowList(license, path) {
metrics.increment("num_licensed")
return true, license
}
}
return false, nil
}
func contains(matches []string, item string) bool {
for _, m := range matches {
if strings.Contains(item, m) {
return true
}
}
return false
}