| // Copyright 2022 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 result |
| |
| import ( |
| "fmt" |
| "regexp" |
| "strings" |
| |
| "go.fuchsia.dev/fuchsia/tools/check-licenses/filetree" |
| "go.fuchsia.dev/fuchsia/tools/check-licenses/license" |
| "go.fuchsia.dev/fuchsia/tools/check-licenses/project" |
| ) |
| |
| func RunChecks() error { |
| if err := AllFuchsiaAuthorSourceFilesMustHaveCopyrightHeaders(); err != nil { |
| return err |
| } |
| if err := AllLicenseTextsMustBeRecognized(); err != nil { |
| return err |
| } |
| if err := AllLicensePatternUsagesMustBeApproved(); err != nil { |
| // TODO: Enable this check after license pattern review. |
| return nil |
| } |
| if err := AllProjectsMustHaveALicense(); err != nil { |
| // TODO: Enable this check after all projects have been addressed. |
| return nil |
| } |
| if err := AllFilesAndFoldersMustBeIncludedInAProject(); err != nil { |
| // TODO: Enable this check after all projects have been addressed. |
| return nil |
| } |
| if err := AllReadmeFuchsiaFilesMustBeFormattedCorrectly(); err != nil { |
| // TODO: Enable this check after all projects have been addressed. |
| return nil |
| } |
| return nil |
| } |
| |
| // ============================================================================= |
| |
| func AllFuchsiaAuthorSourceFilesMustHaveCopyrightHeaders() error { |
| var b strings.Builder |
| b.WriteString("All source files owned by The Fuchsia Authors must contain a copyright header.\n") |
| b.WriteString("The following files have missing or incorrectly worded copyright header information:\n\n") |
| |
| var fuchsia *project.Project |
| for _, p := range project.AllProjects { |
| if p.Root == "." { |
| fuchsia = p |
| break |
| } |
| } |
| |
| if fuchsia == nil { |
| return fmt.Errorf("Couldn't find Fuchsia project to verify this check!!\n") |
| } |
| count := 0 |
| for _, f := range fuchsia.SearchableFiles { |
| if len(f.Data) == 0 { |
| return fmt.Errorf("Found a file that hasn't been parsed yet?? %v\n", f.Path) |
| } |
| OUTER: |
| for _, fd := range f.Data { |
| for _, p := range license.AllCopyrightPatterns { |
| if _, ok := p.PreviousMatches[fd.Hash()]; ok { |
| continue OUTER |
| } |
| } |
| b.WriteString(fmt.Sprintf("-> %v\n", fd.FilePath)) |
| count = count + 1 |
| } |
| } |
| b.WriteString(fmt.Sprintf("\nPlease add the standard Fuchsia copyright header info to the above %v files.\n", count)) |
| if count > 0 { |
| return fmt.Errorf(b.String()) |
| } |
| return nil |
| } |
| |
| func AllLicenseTextsMustBeRecognized() error { |
| if len(license.Unrecognized.Matches) > 0 { |
| var b strings.Builder |
| b.WriteString("Found license texts that were unrecognized:\n\n") |
| for _, m := range license.Unrecognized.Matches { |
| b.WriteString(fmt.Sprintf("-> Line %v of %v\n", m.LineNumber, m.FilePath)) |
| b.WriteString(fmt.Sprintf("\n%v\n\n", string(m.Data))) |
| } |
| b.WriteString("\nPlease add the relevant license pattern to //tools/check-licenses/license/pattern/*, and have it reviewed by the OSRB team.\n") |
| return fmt.Errorf(b.String()) |
| } |
| return nil |
| } |
| |
| func AllLicensePatternUsagesMustBeApproved() error { |
| var b strings.Builder |
| OUTER: |
| for _, sr := range license.AllSearchResults { |
| filepath := sr.LicenseData.FilePath |
| allowlist := sr.Pattern.AllowList |
| for _, entry := range allowlist { |
| re, err := regexp.Compile("(" + entry + ")") |
| if err != nil { |
| return err |
| } |
| if m := re.Find([]byte(filepath)); m != nil { |
| continue OUTER |
| } |
| } |
| b.WriteString(fmt.Sprintf("File %v was not approved to use license pattern %v\n", filepath, sr.Pattern.Name)) |
| } |
| |
| result := b.String() |
| if len(result) > 0 { |
| return fmt.Errorf("Encountered license texts that were not approved for usage:\n%v", result) |
| } |
| return nil |
| } |
| |
| func AllProjectsMustHaveALicense() error { |
| var b strings.Builder |
| b.WriteString("All projects should include relevant license information, and a README.fuchsia file pointing to the file.\n") |
| b.WriteString("The following projects were found without any license information:\n\n") |
| count := 0 |
| for _, p := range project.AllProjects { |
| if len(p.LicenseFile) == 0 { |
| count = count + 1 |
| b.WriteString(fmt.Sprintf("-> %v (README.fuchsia file: %v)\n", p.Root, p.ReadmePath)) |
| } |
| } |
| b.WriteString("\nPlease add a LICENSE file to the above projects, and point to them in the associated README.fuchsia file.\n") |
| if count > 0 { |
| return fmt.Errorf(b.String()) |
| } |
| return nil |
| } |
| |
| func AllFilesAndFoldersMustBeIncludedInAProject() error { |
| var b strings.Builder |
| var recurse func(*filetree.FileTree) |
| count := 0 |
| |
| b.WriteString("All files and folders must have proper license attribution.\n") |
| b.WriteString("This means a license file needs to accompany all first and third party projects,\n") |
| b.WriteString("and a README.fuchsia file must exist and specify where the license file lives.\n") |
| b.WriteString("The following directories are not included in a project:\n\n") |
| recurse = func(ft *filetree.FileTree) { |
| if ft.Project == nil { |
| b.WriteString(fmt.Sprintf("-> %v\n", ft.Path)) |
| count = count + 1 |
| return |
| } |
| for _, child := range ft.Children { |
| recurse(child) |
| } |
| } |
| b.WriteString("\nPlease add a LICENSE file to the above projects, and point to them in an associated README.fuchsia file.\n") |
| |
| recurse(filetree.RootFileTree) |
| if count > 0 { |
| return fmt.Errorf(b.String()) |
| } |
| return nil |
| } |
| |
| func AllReadmeFuchsiaFilesMustBeFormattedCorrectly() error { |
| //TODO |
| return nil |
| } |