From c15090e68a45dc7b298c5d2a14173f4bc22afe1a Mon Sep 17 00:00:00 2001 From: Elazar Leibovich Date: Sun, 13 Jul 2014 09:59:24 +0300 Subject: [PATCH] Support directory listing with AssetDir(dirname string) Signed-off-by: Elazar Leibovich --- convert.go | 6 ++- toc.go | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/convert.go b/convert.go index 0d4dd38..94f46fe 100644 --- a/convert.go +++ b/convert.go @@ -72,7 +72,11 @@ func Translate(c *Config) error { } // Write table of contents - return writeTOC(bfd, toc) + if err := writeTOC(bfd, toc); err != nil { + return err + } + // Write hierarchical tree of assets + return writeTOCTree(bfd, toc) } // findFiles recursively finds all the file paths in the given directory tree. diff --git a/toc.go b/toc.go index ead6379..d2608bd 100644 --- a/toc.go +++ b/toc.go @@ -7,8 +7,121 @@ package bindata import ( "fmt" "io" + "os" + "strings" ) +type assetTree struct { + Asset Asset + Children map[string]*assetTree +} + +func newAssetTree() *assetTree { + tree := &assetTree{} + tree.Children = make(map[string]*assetTree) + return tree +} + +func (node *assetTree) child(name string) *assetTree { + rv, ok := node.Children[name] + if !ok { + rv = newAssetTree() + node.Children[name] = rv + } + return rv +} + +func (root *assetTree) Add(route []string, asset Asset) { + for _, name := range route { + root = root.child(name) + } + root.Asset = asset +} + +func ident(w io.Writer, n int) { + for i := 0; i < n; i++ { + w.Write([]byte{'\t'}) + } +} + +func (root *assetTree) funcOrNil() string { + if root.Asset.Func == "" { + return "nil" + } else { + return root.Asset.Func + } +} + +func (root *assetTree) writeGoMap(w io.Writer, nident int) { + fmt.Fprintf(w, "&_bintree_t{%s, map[string]*_bintree_t{\n", root.funcOrNil()) + for p, child := range root.Children { + ident(w, nident+1) + fmt.Fprintf(w, `"%s": `, p) + child.writeGoMap(w, nident+1) + } + ident(w, nident) + io.WriteString(w, "}}") + if nident > 0 { + io.WriteString(w, ",") + } + io.WriteString(w, "\n") +} + +func (root *assetTree) WriteAsGoMap(w io.Writer) error { + _, err := fmt.Fprint(w, `type _bintree_t struct { + Func func() ([]byte, error) + Children map[string]*_bintree_t +} +var _bintree = `) + root.writeGoMap(w, 0) + return err +} + +func writeTOCTree(w io.Writer, toc []Asset) error { + _, err := fmt.Fprintf(w, `// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +func AssetDir(name string) ([]string, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + node := _bintree + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %%s not found", name) + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %%s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for name := range node.Children { + rv = append(rv, name) + } + return rv, nil +} + +`) + if err != nil { + return err + } + tree := newAssetTree() + for i := range toc { + pathList := strings.Split(toc[i].Name, string(os.PathSeparator)) + tree.Add(pathList, toc[i]) + } + return tree.WriteAsGoMap(w) +} + // writeTOC writes the table of contents file. func writeTOC(w io.Writer, toc []Asset) error { err := writeTOCHeader(w)