blob: 958928f0d2cc585a489d183278dfe89c1d5db35a [file] [log] [blame]
// Utility to generate web extension manifest files from GJSON (Generic JSON)
// templates, given some dependencies.
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"regexp"
"strings"
)
var beginningOfIfStatement = regexp.MustCompile(`^\s*#if defined\(([^\(\)]*)\)\s*$`)
var endOfIfStatement = regexp.MustCompile(`^\s*#endif\s*$`)
var (
quietMode = flag.Bool("quiet", false, "Quiet mode")
templateFile = flag.String("template", "", "Template file")
destFile = flag.String("dest", "", "Destination file")
)
// findWithCaseFolding returns whether there is some element of slice which is
// equal to val under Unicode case-folding.
func findWithCaseFolding(slice []string, val string) bool {
for _, item := range slice {
if strings.EqualFold(item, val) {
return true
}
}
return false
}
// Given a Generic JSON (GJSON) template and the dependencies met,
// WriteManifest will write at dest the manifest file generated from the
// template according to the dependencies.
func WriteManifest(template io.Reader, dest io.Writer, dependencies []string) error {
level := 0
activeLevel := 0
scanner := bufio.NewScanner(template)
for scanner.Scan() {
line := scanner.Text()
considerLine := false
if m := beginningOfIfStatement.FindStringSubmatch(line); m != nil {
if level == activeLevel {
statementDeps := m[1]
deps := strings.Split(statementDeps, "||")
for _, dep := range deps {
dep = strings.TrimSpace(dep)
if findWithCaseFolding(dependencies, dep) {
activeLevel++
break
}
}
}
level++
} else if m := endOfIfStatement.MatchString(line); m {
if activeLevel == level {
activeLevel--
}
level--
} else {
considerLine = level == activeLevel
}
if considerLine {
_, err := io.WriteString(dest, line+"\n")
if err != nil {
return fmt.Errorf("Can't write manifest: %v", err)
}
}
}
return nil
}
// WriteManifestFileNames is the same as WriteManifest, but instead of receiving
// read and write handlers for each file, this function receives the file names
// as strings and reads/writes from/to those files.
func WriteManifestFileNames(templateFile string, destFile string, dependencies []string) error {
template, err := os.Open(templateFile)
if err != nil {
return fmt.Errorf("Couldn't open file %v: %v", templateFile, err)
}
defer template.Close()
dest, err := os.Create(destFile)
if err != nil {
return fmt.Errorf("Couldn't create file %v: %v", destFile, err)
}
defer dest.Close()
return WriteManifest(template, dest, dependencies)
}
func main() {
log.SetPrefix("generatemanifest: ")
log.SetFlags(0)
flag.Parse()
dependencies := flag.Args()
if len(dependencies) == 0 {
log.Fatalf("Pass the dependencies as arguments (for instance, run `go run generateManifest.go CHROMIUM`).")
}
if (*templateFile == "") {
log.Fatalf("Pass the template file name via the -template flag.")
}
if (*destFile == "") {
log.Fatalf("Pass the destination file name via the -dest flag.")
}
err := WriteManifestFileNames(*templateFile, *destFile, dependencies)
if err != nil {
log.Fatalf("%v", err)
} else if !*quietMode {
log.Println("Manifest has been generated successfully")
}
}