// +build ignore
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os/exec"
"path/filepath"
)
// ignoreFile uses "git check-ignore" to determine if we should ignore a file.
func ignoreFile(p string) (ok bool, err error) {
err = exec.Command("git", "check-ignore", p).Run()
if err == nil {
return true, nil
}
exitErr, ok := err.(*exec.ExitError)
if ok {
if sys := exitErr.Sys(); sys != nil {
e, ok := sys.(interface {
// Is the returned value something that returns an exit status?
ExitStatus() int
})
if ok && e.ExitStatus() == 1 {
return false, nil
return false, err
// Maps aren't deterministic, use a struct instead.
type fileData struct {
name string
data string
func main() {
// ReadDir guarentees result in sorted order.
dir, err := ioutil.ReadDir("web/templates")
if err != nil {
log.Fatal(err)
files := []fileData{}
for _, file := range dir {
p := filepath.Join("web/templates", file.Name())
ignore, err := ignoreFile(p)
if ignore {
continue
data, err := ioutil.ReadFile(p)
if bytes.Contains(data, []byte{'`'}) {
log.Fatalf("file %s contains escape character '`' and cannot be compiled into go source", p)
files = append(files, fileData{file.Name(), string(data)})
f := new(bytes.Buffer)
fmt.Fprintln(f, "// This file was generated by the makefile. Do not edit.")
fmt.Fprintln(f)
fmt.Fprintln(f, "package server")
fmt.Fprintln(f, "// defaultTemplates is a key for file name to file data of the files in web/templates.")
fmt.Fprintln(f, "var defaultTemplates = map[string]string{")
for _, file := range files {
fmt.Fprintf(f, "\t%q: `%s`,\n", file.name, file.data)
fmt.Fprintln(f, "}")
if err := ioutil.WriteFile("server/templates_default.go", f.Bytes(), 0644); err != nil {