blob: 82fc7ee80b93650263c25ea1745d3ebcf17dbe67 [file] [log] [blame]
// 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 main
import (
"context"
"encoding/json"
"log"
"runtime/trace"
"time"
"go.fuchsia.dev/fuchsia/tools/check-licenses/directory"
"go.fuchsia.dev/fuchsia/tools/check-licenses/file"
"go.fuchsia.dev/fuchsia/tools/check-licenses/project"
"go.fuchsia.dev/fuchsia/tools/check-licenses/project/readme"
"go.fuchsia.dev/fuchsia/tools/check-licenses/result"
)
// Execute kicks-off the check-licenses runthrough.
// It is assumed that all configuration settings have been set before this is called.
func Execute(ctx context.Context) error {
start := time.Now()
// Initialize all package configs.
startInitialize := time.Now()
log.Print("Initializing... ")
if err := initialize(); err != nil {
log.Println("Error!")
return err
}
log.Printf("Done. [%v]\n", time.Since(startInitialize))
// Traverse the repository, generating a tree of Dictionary and File objects in memory.
r := trace.StartRegion(ctx, "directory.NewDirectory("+Config.FuchsiaDir+")")
startDirectory := time.Now()
log.Print("Discovering files and folders... ")
_, err := directory.NewDirectory(".", nil)
if err != nil {
log.Println("Error!")
return err
}
log.Printf("Done. [%v]\n", time.Since(startDirectory))
r.End()
// If we plan on generating an output notice file:
// Filter out the projects that we don't care about (absent from the build graph).
if Config.OutputLicenseFile {
r := trace.StartRegion(ctx, "cmd.FilterProjects("+Config.Target+")")
startFilter := time.Now()
target := Config.Target
if target == "" {
target = "//:default"
}
log.Printf("Filtering out projects that are not in the build graph for [%s]...",
target)
if err := project.FilterProjects(); err != nil {
log.Println("Error!")
return err
}
log.Printf("Done. [%v]\n", time.Since(startFilter))
r.End()
} else {
project.FilteredProjects = project.AllProjects
project.RootProject = project.AllProjects["."]
}
// License analysis happens in CQ.
// There is no need to analyze them if all we want to do is produce a NOTICE file.
if Config.RunAnalysis {
// Analyze the remaining projects, and keep track of all found license texts.
r = trace.StartRegion(ctx, "project.AnalyzeLicenses")
startAnalyze := time.Now()
log.Printf("Searching for license texts [%v projects]... ", len(project.FilteredProjects))
err = project.AnalyzeLicenses()
if err != nil {
log.Println("Error!")
return err
}
log.Printf("Done. [%v]\n", time.Since(startAnalyze))
r.End()
}
// Save the resulting NOTICE file (if necessary), all config files
// and execution metrics to the output directory.
// Also perform checks to ensure the repository is in a good state.
r = trace.StartRegion(ctx, "result.SaveResults")
startSaveResults := time.Now()
log.Print("Saving results... ")
var s string
s, err = result.SaveResults(Config, Metrics)
if err != nil {
return err
}
log.Printf("Done. [%v]\n", time.Since(startSaveResults))
r.End()
// Done.
log.Printf("\nTotal runtime: %v\n============\n", time.Since(start))
log.Println(s)
return nil
}
// Initialize each go package with their updated config files.
func initialize() error {
if err := file.Initialize(Config.File); err != nil {
return err
}
if err := readme.Initialize(); err != nil {
return err
}
if err := project.Initialize(Config.Project); err != nil {
return err
}
if err := directory.Initialize(Config.Directory); err != nil {
return err
}
if err := result.Initialize(Config.Result); err != nil {
return err
}
// Save the config file to the out directory (if defined).
if b, err := json.MarshalIndent(Config, "", " "); err != nil {
return err
} else {
plusFile("_config.json", b)
}
return nil
}