121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
|
// 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
|
||
|
}
|