bindata/convert.go

121 lines
2.7 KiB
Go
Raw Normal View History

// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
// license. Its contents can be found at:
// http://creativecommons.org/publicdomain/zero/1.0/
package bindata
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"unicode"
)
// ProgressFunc is a callback handler which is fired whenever
// bindata begins translating a new file.
//
// It takes the file path and the current and total file counts.
// This can be used to indicate progress of the conversion.
//
// If this handler returns true, the processing is stopped and
// Translate() returns immediately.
type ProgressFunc func(file string, current, total int) bool
// Translate reads assets from an input directory, converts them
// to Go code and writes new files to the output directory specified
// in the given configuration.
func Translate(c *Config, pf ProgressFunc) error {
toc := make(map[string]string)
err := findFiles(c.Input, c.Prefix, toc)
if err != nil {
return err
}
var current int
for key, value := range toc {
if pf != nil {
current++
if pf(key, current, len(toc)) {
return nil
}
}
_ = value
}
return nil
}
// fillTOC recursively finds all the file paths in the given directory tree.
// They are added to the given map as keys. Values will be safe function names
// for each file, which will be used when generating the output code.
func findFiles(dir, prefix string, toc map[string]string) error {
if len(prefix) > 0 {
dir, _ = filepath.Abs(dir)
prefix, _ = filepath.Abs(prefix)
}
fd, err := os.Open(dir)
if err != nil {
return err
}
defer fd.Close()
list, err := fd.Readdir(0)
if err != nil {
return err
}
for _, file := range list {
key := filepath.Join(dir, file.Name())
if file.IsDir() {
findFiles(key, prefix, toc)
} else {
if strings.HasPrefix(key, prefix) {
key = key[len(prefix):]
}
// If we have a leading slash, get rid of it.
if len(key) > 0 && key[0] == '/' {
key = key[1:]
}
// This shouldn't happen.
if len(key) == 0 {
return fmt.Errorf("Invalid file: %v", filepath.Join(dir, file.Name()))
}
value := safeFunctionName(key)
toc[key] = value
}
}
return nil
}
var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`)
// safeFunctionName converts the given name into a name
// which qualifies as a valid function identifier.
func safeFunctionName(name string) string {
name = strings.ToLower(name)
name = regFuncName.ReplaceAllString(name, "_")
// Identifier can't start with a digit.
if unicode.IsDigit(rune(name[0])) {
name = "_" + name
}
// Get rid of "__" instances for niceness.
for strings.Index(name, "__") > -1 {
name = strings.Replace(name, "__", "_", -1)
}
return name
}