blob: cc4d00ca910c661fa6a28522a3972c2dc8513271 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package commands
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"text/template"
"github.com/spf13/cobra"
"github.com/apache/skywalking-eyes/internal/logger"
"github.com/apache/skywalking-eyes/pkg/deps"
)
var outDir string
var summaryTplPath string
var summaryTpl *template.Template
func init() {
DepsResolveCommand.PersistentFlags().StringVarP(&outDir, "output", "o", "",
"the directory to output the resolved dependencies' licenses, if not set the dependencies' licenses won't be saved")
DepsResolveCommand.PersistentFlags().StringVarP(&summaryTplPath, "summary", "s", "",
"the template file to write the summary of dependencies' licenses, a new file named \"LICENSE\" will be "+
"created in the same directory as the template file, to save the final summary.")
}
var fileNamePattern = regexp.MustCompile(`[^a-zA-Z0-9\\.\-]`)
var DepsResolveCommand = &cobra.Command{
Use: "resolve",
Aliases: []string{"r"},
Long: "resolves all dependencies of a module and their transitive dependencies",
PreRunE: func(cmd *cobra.Command, args []string) error {
if outDir != "" {
absPath, err := filepath.Abs(outDir)
if err != nil {
return err
}
outDir = absPath
if err := os.MkdirAll(outDir, 0o700); err != nil && !os.IsExist(err) {
return err
}
}
if summaryTplPath != "" {
absPath, err := filepath.Abs(summaryTplPath)
if err != nil {
return err
}
summaryTplPath = absPath
tpl, err := deps.ParseTemplate(summaryTplPath)
if err != nil {
return err
}
summaryTpl = tpl
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
report := deps.Report{}
configDeps := Config.Dependencies()
if err := deps.Resolve(configDeps, &report); err != nil {
return err
}
if summaryTpl != nil {
if err := writeSummary(&report); err != nil {
return err
}
}
if outDir != "" {
for _, result := range report.Resolved {
writeLicense(result)
}
}
fmt.Println(report.String())
if skipped := len(report.Skipped); skipped > 0 {
pkgs := make([]string, skipped)
for i, s := range report.Skipped {
pkgs[i] = s.Dependency
}
return fmt.Errorf(
"failed to identify the licenses of following packages (%d):\n%s",
len(pkgs), strings.Join(pkgs, "\n"),
)
}
return nil
},
}
func writeLicense(result *deps.Result) {
filename := string(fileNamePattern.ReplaceAll([]byte(result.Dependency), []byte("-")))
filename = filepath.Join(outDir, "license-"+filename+".txt")
file, err := os.Create(filename)
if err != nil {
logger.Log.Errorf("failed to create license file %v: %v", filename, err)
return
}
defer func(file *os.File) { _ = file.Close() }(file)
_, err = file.WriteString(result.LicenseContent)
if err != nil {
logger.Log.Errorf("failed to write license file, %v: %v", filename, err)
return
}
}
func writeSummary(rep *deps.Report) error {
file, err := os.Create(filepath.Join(filepath.Dir(summaryTplPath), "LICENSE"))
if err != nil {
return err
}
defer file.Close()
headers := Config.Headers()
if len(headers) > 1 {
return fmt.Errorf("unable to write summary as multiple licenses were provided in configuration")
}
summary, err := deps.GenerateSummary(summaryTpl, headers[0], rep)
if err != nil {
return err
}
_, err = file.WriteString(summary)
return err
}