blob: 2a7913cdcd34adf8d6a50eea10ca7e110ad59737 [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 (
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"sort"
"strings"
"text/template"
"go.fuchsia.dev/fuchsia/tools/check-licenses/templates"
)
// saveToOutputFile writes to output the serialized licenses.
//
// It writes an uncompressed version too if a compressed version is requested.
func saveToOutputFile(path string, licenses *Licenses) error {
// Sort the licenses in alphabetical order for consistency.
sort.Slice(licenses.licenses, func(i, j int) bool { return licenses.licenses[i].Category < licenses.licenses[j].Category })
data := struct {
Used []*License
Unused []*License
}{}
for _, l := range licenses.licenses {
if len(l.matches) == 0 {
data.Unused = append(data.Unused, l)
} else {
data.Used = append(data.Used, l)
}
}
templateStr := ""
switch {
case strings.HasSuffix(path, ".txt"):
templateStr = templates.TemplateTxt
case strings.HasSuffix(path, ".html") || strings.HasSuffix(path, ".html.gz"):
// TODO(omerlevran): Use html/template instead of text/template.
// text/template is inherently unsafe to generate HTML.
templateStr = templates.TemplateHtml
case strings.HasSuffix(path, ".json"):
// TODO(omerlevran): Use encoding/json instead of hand-rolling out json.
templateStr = templates.TemplateJson
default:
return fmt.Errorf("no template found for %s", path)
}
buf := bytes.Buffer{}
tmpl := template.Must(template.New("name").Funcs(funcMap).Parse(templateStr))
if err := tmpl.Execute(&buf, data); err != nil {
return err
}
// Special handling for compressed file.
const gz = ".gz"
if strings.HasSuffix(path, gz) {
// First write uncompressed, then compressed.
if err := ioutil.WriteFile(path[:len(path)-len(gz)], buf.Bytes(), 0666); err != nil {
return err
}
d, err := compressGZ(buf.Bytes())
if err != nil {
return err
}
return ioutil.WriteFile(path, d, 0666)
}
return ioutil.WriteFile(path, buf.Bytes(), 0666)
}
// compressGZ returns the compressed buffer with gzip format.
func compressGZ(d []byte) ([]byte, error) {
buf := bytes.Buffer{}
zw := gzip.NewWriter(&buf)
if _, err := zw.Write(d); err != nil {
return nil, err
}
if err := zw.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var funcMap = template.FuncMap{
"getPattern": func(l *License) string {
return l.pattern.String()
},
"getText": func(l *License, author string) string {
return l.matches[author].value
},
"getHTMLText": func(l *License, author string) string {
return strings.Replace(l.matches[author].value, "\n", "<br />", -1)
},
"getEscapedText": func(l *License, author string) string {
return strings.Replace(l.matches[author].value, "\"", "\\\"", -1)
},
"getCategory": func(l *License) string {
return strings.TrimSuffix(l.Category, ".lic")
},
"getFiles": func(l *License, author string) []string {
var files []string
for _, file := range l.matches[author].files {
files = append(files, file)
}
sort.Strings(files)
return files
},
"getAuthors": func(l *License) []string {
var authors []string
for author := range l.matches {
authors = append(authors, author)
}
sort.Strings(authors)
return authors
},
}