Imported Upstream version 3.0.7
Dmitry Smirnov
8 years ago
69 | 69 | > the rest of the API. This addresses issue #32 |
70 | 70 | |
71 | 71 | Do not pile a lot of unrelated changes into a single commit. |
72 | Pick and chose only those changes for a single commit, which are | |
72 | Pick and choose only those changes for a single commit, which are | |
73 | 73 | directly related. We would much rather see a hundred commits |
74 | 74 | saying nothing but `"Runs go fmt"` in between any real fixes |
75 | 75 | than have these style changes embedded in those real fixes. |
41 | 41 | $ go-bindata dir1/... /path/to/dir2/... dir3 |
42 | 42 | |
43 | 43 | |
44 | The following paragraphs detail some of the command line options which can | |
44 | The following paragraphs detail some of the command line options which can be | |
45 | 45 | supplied to `go-bindata`. Refer to the `testdata/out` directory for various |
46 | 46 | output examples from the assets in `testdata/in`. Each example uses different |
47 | 47 | command line options. |
48 | 48 | |
49 | To ignore files, pass in regexes using -ignore, for example: | |
50 | ||
51 | $ go-bindata -ignore=\\.gitignore data/... | |
49 | 52 | |
50 | 53 | ### Accessing an asset |
51 | 54 | |
52 | To access asset data, we use the `Asset(string) []byte` function which | |
55 | To access asset data, we use the `Asset(string) ([]byte, error)` function which | |
53 | 56 | is included in the generated output. |
54 | 57 | |
55 | data := Asset("pub/style/foo.css") | |
56 | if len(data) == 0 { | |
58 | data, err := Asset("pub/style/foo.css") | |
59 | if err != nil { | |
57 | 60 | // Asset was not found. |
58 | 61 | } |
59 | ||
62 | ||
60 | 63 | // use asset data |
61 | 64 | |
62 | 65 | |
178 | 181 | The tags are appended to a `// +build` line in the beginning of the output file |
179 | 182 | and must follow the build tags syntax specified by the go tool. |
180 | 183 | |
184 | ### Related projects | |
181 | 185 | |
186 | [go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) - | |
187 | implements `http.FileSystem` interface. Allows you to serve assets with `net/http`. | |
188 |
9 | 9 | Name string // Key used in TOC -- name by which asset is referenced. |
10 | 10 | Func string // Function name for the procedure returning the asset contents. |
11 | 11 | } |
12 | ||
13 | // Implement sort.Interface for []Asset based on Path field | |
14 | type ByPath []Asset | |
15 | ||
16 | func (v ByPath) Len() int { return len(v) } | |
17 | func (v ByPath) Swap(i, j int) { v[i], v[j] = v[j], v[i] } | |
18 | func (v ByPath) Less(i, j int) bool { return v[i].Path < v[j].Path } |
7 | 7 | "fmt" |
8 | 8 | "os" |
9 | 9 | "path/filepath" |
10 | "regexp" | |
10 | 11 | ) |
11 | 12 | |
12 | 13 | // InputConfig defines options on a asset directory to be convert. |
119 | 120 | // sub directories. This defaults to false, so only files in the |
120 | 121 | // input directory itself are read. |
121 | 122 | Recursive bool |
123 | ||
124 | // Ignores any filenames matching the regex pattern specified, e.g. | |
125 | // path/to/file.ext will ignore only that file, or \\.gitignore | |
126 | // will match any .gitignore file. | |
127 | // | |
128 | // This parameter can be provided multiple times. | |
129 | Ignore []*regexp.Regexp | |
122 | 130 | } |
123 | 131 | |
124 | 132 | // NewConfig returns a default configuration struct. |
130 | 138 | c.Debug = false |
131 | 139 | c.Recursive = false |
132 | 140 | c.Output = "./bindata.go" |
141 | c.Ignore = make([]*regexp.Regexp, 0) | |
133 | 142 | return c |
134 | 143 | } |
135 | 144 | |
141 | 150 | } |
142 | 151 | |
143 | 152 | for _, input := range c.Input { |
144 | stat, err := os.Lstat(input.Path) | |
153 | _, err := os.Lstat(input.Path) | |
145 | 154 | if err != nil { |
146 | 155 | return fmt.Errorf("Failed to stat input path '%s': %v", input.Path, err) |
147 | } | |
148 | ||
149 | if !stat.IsDir() { | |
150 | return fmt.Errorf("Input path '%s' is not a directory.", input.Path) | |
151 | 156 | } |
152 | 157 | } |
153 | 158 | |
169 | 174 | // File does not exist. This is fine, just make |
170 | 175 | // sure the directory it is to be in exists. |
171 | 176 | dir, _ := filepath.Split(c.Output) |
172 | err = os.MkdirAll(dir, 0744) | |
177 | if dir != "" { | |
178 | err = os.MkdirAll(dir, 0744) | |
173 | 179 | |
174 | if err != nil { | |
175 | return fmt.Errorf("Create output directory: %v", err) | |
180 | if err != nil { | |
181 | return fmt.Errorf("Create output directory: %v", err) | |
182 | } | |
176 | 183 | } |
177 | 184 | } |
178 | 185 |
9 | 9 | "os" |
10 | 10 | "path/filepath" |
11 | 11 | "regexp" |
12 | "sort" | |
12 | 13 | "strings" |
13 | 14 | "unicode" |
14 | 15 | ) |
27 | 28 | |
28 | 29 | // Locate all the assets. |
29 | 30 | for _, input := range c.Input { |
30 | err = findFiles(input.Path, c.Prefix, input.Recursive, &toc) | |
31 | if err != nil { | |
32 | return err | |
33 | } | |
34 | } | |
31 | err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore) | |
32 | if err != nil { | |
33 | return err | |
34 | } | |
35 | } | |
36 | ||
37 | // Sort to make output stable between invocations | |
38 | sort.Sort(ByPath(toc)) | |
35 | 39 | |
36 | 40 | // Create output file. |
37 | 41 | fd, err := os.Create(c.Output) |
71 | 75 | } |
72 | 76 | |
73 | 77 | // Write table of contents |
74 | return writeTOC(bfd, toc) | |
78 | if err := writeTOC(bfd, toc); err != nil { | |
79 | return err | |
80 | } | |
81 | // Write hierarchical tree of assets | |
82 | return writeTOCTree(bfd, toc) | |
75 | 83 | } |
76 | 84 | |
77 | 85 | // findFiles recursively finds all the file paths in the given directory tree. |
78 | 86 | // They are added to the given map as keys. Values will be safe function names |
79 | 87 | // for each file, which will be used when generating the output code. |
80 | func findFiles(dir, prefix string, recursive bool, toc *[]Asset) error { | |
88 | func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp) error { | |
81 | 89 | if len(prefix) > 0 { |
82 | 90 | dir, _ = filepath.Abs(dir) |
83 | 91 | prefix, _ = filepath.Abs(prefix) |
84 | } | |
85 | ||
86 | fd, err := os.Open(dir) | |
87 | if err != nil { | |
88 | return err | |
89 | } | |
90 | ||
91 | defer fd.Close() | |
92 | ||
93 | list, err := fd.Readdir(0) | |
94 | if err != nil { | |
95 | return err | |
96 | } | |
92 | prefix = filepath.ToSlash(prefix) | |
93 | } | |
94 | ||
95 | fi, err := os.Stat(dir) | |
96 | if err != nil { | |
97 | return err | |
98 | } | |
99 | ||
100 | var list []os.FileInfo | |
101 | ||
102 | if !fi.IsDir() { | |
103 | dir = "" | |
104 | list = []os.FileInfo{fi} | |
105 | } else { | |
106 | fd, err := os.Open(dir) | |
107 | if err != nil { | |
108 | return err | |
109 | } | |
110 | ||
111 | defer fd.Close() | |
112 | ||
113 | list, err = fd.Readdir(0) | |
114 | if err != nil { | |
115 | return err | |
116 | } | |
117 | } | |
118 | ||
119 | knownFuncs := make(map[string]int) | |
97 | 120 | |
98 | 121 | for _, file := range list { |
99 | 122 | var asset Asset |
100 | 123 | asset.Path = filepath.Join(dir, file.Name()) |
101 | asset.Name = asset.Path | |
124 | asset.Name = filepath.ToSlash(asset.Path) | |
125 | ||
126 | ignoring := false | |
127 | for _, re := range ignore { | |
128 | if re.MatchString(asset.Path) { | |
129 | ignoring = true | |
130 | break | |
131 | } | |
132 | } | |
133 | if ignoring { | |
134 | continue | |
135 | } | |
102 | 136 | |
103 | 137 | if file.IsDir() { |
104 | 138 | if recursive { |
105 | findFiles(asset.Path, prefix, recursive, toc) | |
139 | findFiles(asset.Path, prefix, recursive, toc, ignore) | |
106 | 140 | } |
107 | 141 | continue |
108 | 142 | } |
121 | 155 | return fmt.Errorf("Invalid file: %v", asset.Path) |
122 | 156 | } |
123 | 157 | |
124 | asset.Func = safeFunctionName(asset.Name) | |
158 | asset.Func = safeFunctionName(asset.Name, knownFuncs) | |
125 | 159 | asset.Path, _ = filepath.Abs(asset.Path) |
126 | 160 | *toc = append(*toc, asset) |
127 | 161 | } |
132 | 166 | var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`) |
133 | 167 | |
134 | 168 | // safeFunctionName converts the given name into a name |
135 | // which qualifies as a valid function identifier. | |
136 | func safeFunctionName(name string) string { | |
169 | // which qualifies as a valid function identifier. It | |
170 | // also compares against a known list of functions to | |
171 | // prevent conflict based on name translation. | |
172 | func safeFunctionName(name string, knownFuncs map[string]int) string { | |
137 | 173 | name = strings.ToLower(name) |
138 | 174 | name = regFuncName.ReplaceAllString(name, "_") |
139 | 175 | |
152 | 188 | name = "_" + name |
153 | 189 | } |
154 | 190 | |
191 | if num, ok := knownFuncs[name]; ok { | |
192 | knownFuncs[name] = num + 1 | |
193 | name = fmt.Sprintf("%s%d", name, num) | |
194 | } else { | |
195 | knownFuncs[name] = 2 | |
196 | } | |
197 | ||
155 | 198 | return name |
156 | 199 | } |
31 | 31 | _, err := fmt.Fprintf(w, `import ( |
32 | 32 | "fmt" |
33 | 33 | "io/ioutil" |
34 | "strings" | |
34 | 35 | ) |
35 | 36 | |
36 | // bindata_read reads the given file from disk. It returns | |
37 | // an error on failure. | |
37 | // bindata_read reads the given file from disk. It returns an error on failure. | |
38 | 38 | func bindata_read(path, name string) ([]byte, error) { |
39 | 39 | buf, err := ioutil.ReadFile(path) |
40 | 40 | if err != nil { |
51 | 51 | // A debug entry is simply a function which reads the asset from |
52 | 52 | // the original file (e.g.: from disk). |
53 | 53 | func writeDebugAsset(w io.Writer, asset *Asset) error { |
54 | _, err := fmt.Fprintf(w, ` | |
55 | // %s reads file data from disk. | |
56 | // It panics if something went wrong in the process. | |
54 | _, err := fmt.Fprintf(w, `// %s reads file data from disk. It returns an error on failure. | |
57 | 55 | func %s() ([]byte, error) { |
58 | 56 | return bindata_read( |
59 | 57 | %q, |
60 | 58 | %q, |
61 | 59 | ) |
62 | 60 | } |
61 | ||
63 | 62 | `, asset.Func, asset.Func, asset.Path, asset.Name) |
64 | 63 | return err |
65 | 64 | } |
0 | package main | |
1 | ||
2 | import "strings" | |
3 | ||
4 | // borrowed from https://github.com/hashicorp/serf/blob/master/command/agent/flag_slice_value.go | |
5 | ||
6 | // AppendSliceValue implements the flag.Value interface and allows multiple | |
7 | // calls to the same variable to append a list. | |
8 | type AppendSliceValue []string | |
9 | ||
10 | func (s *AppendSliceValue) String() string { | |
11 | return strings.Join(*s, ",") | |
12 | } | |
13 | ||
14 | func (s *AppendSliceValue) Set(value string) error { | |
15 | if *s == nil { | |
16 | *s = make([]string, 0, 1) | |
17 | } | |
18 | ||
19 | *s = append(*s, value) | |
20 | return nil | |
21 | } |
9 | 9 | "github.com/jteeuwen/go-bindata" |
10 | 10 | "os" |
11 | 11 | "path/filepath" |
12 | "regexp" | |
12 | 13 | "strings" |
13 | 14 | ) |
14 | 15 | |
38 | 39 | } |
39 | 40 | |
40 | 41 | flag.BoolVar(&c.Debug, "debug", c.Debug, "Do not embed the assets, but provide the embedding API. Contents will still be loaded from disk.") |
41 | flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of uild tags to include.") | |
42 | flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of build tags to include.") | |
42 | 43 | flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off asset names.") |
43 | 44 | flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.") |
44 | 45 | flag.BoolVar(&c.NoMemCopy, "nomemcopy", c.NoMemCopy, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.") |
45 | 46 | flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.") |
46 | 47 | flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.") |
47 | 48 | flag.BoolVar(&version, "version", false, "Displays version information.") |
49 | ||
50 | ignore := make([]string, 0) | |
51 | flag.Var((*AppendSliceValue)(&ignore), "ignore", "Regex pattern to ignore") | |
52 | ||
48 | 53 | flag.Parse() |
54 | ||
55 | patterns := make([]*regexp.Regexp, 0) | |
56 | for _, pattern := range ignore { | |
57 | patterns = append(patterns, regexp.MustCompile(pattern)) | |
58 | } | |
59 | c.Ignore = patterns | |
49 | 60 | |
50 | 61 | if version { |
51 | 62 | fmt.Printf("%s\n", Version()) |
4 | 4 | package bindata |
5 | 5 | |
6 | 6 | import ( |
7 | "bytes" | |
7 | 8 | "compress/gzip" |
8 | 9 | "fmt" |
9 | 10 | "io" |
11 | "io/ioutil" | |
10 | 12 | "os" |
13 | "unicode/utf8" | |
11 | 14 | ) |
12 | 15 | |
13 | 16 | // writeRelease writes the release code file. |
69 | 72 | return compressed_memcopy(w, asset, fd) |
70 | 73 | } |
71 | 74 | } |
72 | ||
73 | return nil | |
75 | } | |
76 | ||
77 | // sanitize prepares a valid UTF-8 string as a raw string constant. | |
78 | // Based on https://code.google.com/p/go/source/browse/godoc/static/makestatic.go?repo=tools | |
79 | func sanitize(b []byte) []byte { | |
80 | // Replace ` with `+"`"+` | |
81 | b = bytes.Replace(b, []byte("`"), []byte("`+\"`\"+`"), -1) | |
82 | ||
83 | // Replace BOM with `+"\xEF\xBB\xBF"+` | |
84 | // (A BOM is valid UTF-8 but not permitted in Go source files. | |
85 | // I wouldn't bother handling this, but for some insane reason | |
86 | // jquery.js has a BOM somewhere in the middle.) | |
87 | return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1) | |
74 | 88 | } |
75 | 89 | |
76 | 90 | func header_compressed_nomemcopy(w io.Writer) error { |
77 | 91 | _, err := fmt.Fprintf(w, `import ( |
78 | "bytes" | |
79 | "compress/gzip" | |
80 | "fmt" | |
81 | "io" | |
82 | "reflect" | |
83 | "unsafe" | |
92 | "bytes" | |
93 | "compress/gzip" | |
94 | "fmt" | |
95 | "io" | |
96 | "reflect" | |
97 | "strings" | |
98 | "unsafe" | |
84 | 99 | ) |
85 | 100 | |
86 | 101 | func bindata_read(data, name string) ([]byte, error) { |
114 | 129 | |
115 | 130 | func header_compressed_memcopy(w io.Writer) error { |
116 | 131 | _, err := fmt.Fprintf(w, `import ( |
117 | "bytes" | |
118 | "compress/gzip" | |
119 | "fmt" | |
120 | "io" | |
132 | "bytes" | |
133 | "compress/gzip" | |
134 | "fmt" | |
135 | "io" | |
136 | "strings" | |
121 | 137 | ) |
122 | 138 | |
123 | 139 | func bindata_read(data []byte, name string) ([]byte, error) { |
143 | 159 | |
144 | 160 | func header_uncompressed_nomemcopy(w io.Writer) error { |
145 | 161 | _, err := fmt.Fprintf(w, `import ( |
146 | "fmt" | |
147 | "reflect" | |
148 | "unsafe" | |
162 | "fmt" | |
163 | "reflect" | |
164 | "strings" | |
165 | "unsafe" | |
149 | 166 | ) |
150 | 167 | |
151 | 168 | func bindata_read(data, name string) ([]byte, error) { |
165 | 182 | |
166 | 183 | func header_uncompressed_memcopy(w io.Writer) error { |
167 | 184 | _, err := fmt.Fprintf(w, `import ( |
168 | "fmt" | |
185 | "fmt" | |
186 | "strings" | |
169 | 187 | ) |
170 | 188 | `) |
171 | 189 | return err |
199 | 217 | } |
200 | 218 | |
201 | 219 | func compressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error { |
202 | _, err := fmt.Fprintf(w, `func %s() ([]byte, error) { | |
203 | return bindata_read([]byte{`, asset.Func) | |
204 | ||
205 | if err != nil { | |
206 | return nil | |
207 | } | |
208 | ||
209 | gz := gzip.NewWriter(&ByteWriter{Writer: w}) | |
220 | _, err := fmt.Fprintf(w, `var _%s = []byte("`, asset.Func) | |
221 | if err != nil { | |
222 | return err | |
223 | } | |
224 | ||
225 | gz := gzip.NewWriter(&StringWriter{Writer: w}) | |
210 | 226 | _, err = io.Copy(gz, r) |
211 | 227 | gz.Close() |
212 | 228 | |
214 | 230 | return err |
215 | 231 | } |
216 | 232 | |
217 | _, err = fmt.Fprintf(w, ` | |
218 | }, | |
219 | %q, | |
220 | ) | |
221 | } | |
222 | ||
223 | `, asset.Name) | |
224 | return err | |
225 | } | |
226 | ||
227 | func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error { | |
228 | _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) | |
229 | if err != nil { | |
230 | return err | |
231 | } | |
232 | ||
233 | _, err = io.Copy(&StringWriter{Writer: w}, r) | |
234 | if err != nil { | |
235 | return err | |
236 | } | |
237 | ||
238 | _, err = fmt.Fprintf(w, `" | |
233 | _, err = fmt.Fprintf(w, `") | |
239 | 234 | |
240 | 235 | func %s() ([]byte, error) { |
241 | 236 | return bindata_read( |
248 | 243 | return err |
249 | 244 | } |
250 | 245 | |
246 | func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error { | |
247 | _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) | |
248 | if err != nil { | |
249 | return err | |
250 | } | |
251 | ||
252 | _, err = io.Copy(&StringWriter{Writer: w}, r) | |
253 | if err != nil { | |
254 | return err | |
255 | } | |
256 | ||
257 | _, err = fmt.Fprintf(w, `" | |
258 | ||
259 | func %s() ([]byte, error) { | |
260 | return bindata_read( | |
261 | _%s, | |
262 | %q, | |
263 | ) | |
264 | } | |
265 | ||
266 | `, asset.Func, asset.Func, asset.Name) | |
267 | return err | |
268 | } | |
269 | ||
251 | 270 | func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error { |
252 | _, err := fmt.Fprintf(w, `func %s() ([]byte, error) { | |
253 | return []byte{`, asset.Func) | |
254 | if err != nil { | |
255 | return err | |
256 | } | |
257 | ||
258 | _, err = io.Copy(&ByteWriter{Writer: w}, r) | |
259 | if err != nil { | |
260 | return err | |
261 | } | |
262 | ||
263 | _, err = fmt.Fprintf(w, ` | |
264 | }, nil | |
265 | } | |
266 | ||
267 | `) | |
268 | return err | |
269 | } | |
271 | _, err := fmt.Fprintf(w, `var _%s = []byte(`, asset.Func) | |
272 | if err != nil { | |
273 | return err | |
274 | } | |
275 | ||
276 | b, err := ioutil.ReadAll(r) | |
277 | if err != nil { | |
278 | return err | |
279 | } | |
280 | if utf8.Valid(b) { | |
281 | fmt.Fprintf(w, "`%s`", sanitize(b)) | |
282 | } else { | |
283 | fmt.Fprintf(w, "%q", b) | |
284 | } | |
285 | ||
286 | _, err = fmt.Fprintf(w, `) | |
287 | ||
288 | func %s() ([]byte, error) { | |
289 | return _%s, nil | |
290 | } | |
291 | ||
292 | `, asset.Func, asset.Func) | |
293 | return err | |
294 | } |
6 | 6 | import ( |
7 | 7 | "fmt" |
8 | 8 | "io" |
9 | "os" | |
10 | "sort" | |
11 | "strings" | |
9 | 12 | ) |
13 | ||
14 | type assetTree struct { | |
15 | Asset Asset | |
16 | Children map[string]*assetTree | |
17 | } | |
18 | ||
19 | func newAssetTree() *assetTree { | |
20 | tree := &assetTree{} | |
21 | tree.Children = make(map[string]*assetTree) | |
22 | return tree | |
23 | } | |
24 | ||
25 | func (node *assetTree) child(name string) *assetTree { | |
26 | rv, ok := node.Children[name] | |
27 | if !ok { | |
28 | rv = newAssetTree() | |
29 | node.Children[name] = rv | |
30 | } | |
31 | return rv | |
32 | } | |
33 | ||
34 | func (root *assetTree) Add(route []string, asset Asset) { | |
35 | for _, name := range route { | |
36 | root = root.child(name) | |
37 | } | |
38 | root.Asset = asset | |
39 | } | |
40 | ||
41 | func ident(w io.Writer, n int) { | |
42 | for i := 0; i < n; i++ { | |
43 | w.Write([]byte{'\t'}) | |
44 | } | |
45 | } | |
46 | ||
47 | func (root *assetTree) funcOrNil() string { | |
48 | if root.Asset.Func == "" { | |
49 | return "nil" | |
50 | } else { | |
51 | return root.Asset.Func | |
52 | } | |
53 | } | |
54 | ||
55 | func (root *assetTree) writeGoMap(w io.Writer, nident int) { | |
56 | fmt.Fprintf(w, "&_bintree_t{%s, map[string]*_bintree_t{\n", root.funcOrNil()) | |
57 | ||
58 | // Sort to make output stable between invocations | |
59 | filenames := make([]string, len(root.Children)) | |
60 | i := 0 | |
61 | for filename, _ := range root.Children { | |
62 | filenames[i] = filename | |
63 | i++ | |
64 | } | |
65 | sort.Strings(filenames) | |
66 | ||
67 | for _, p := range filenames { | |
68 | ident(w, nident+1) | |
69 | fmt.Fprintf(w, `"%s": `, p) | |
70 | root.Children[p].writeGoMap(w, nident+1) | |
71 | } | |
72 | ident(w, nident) | |
73 | io.WriteString(w, "}}") | |
74 | if nident > 0 { | |
75 | io.WriteString(w, ",") | |
76 | } | |
77 | io.WriteString(w, "\n") | |
78 | } | |
79 | ||
80 | func (root *assetTree) WriteAsGoMap(w io.Writer) error { | |
81 | _, err := fmt.Fprint(w, `type _bintree_t struct { | |
82 | Func func() ([]byte, error) | |
83 | Children map[string]*_bintree_t | |
84 | } | |
85 | var _bintree = `) | |
86 | root.writeGoMap(w, 0) | |
87 | return err | |
88 | } | |
89 | ||
90 | func writeTOCTree(w io.Writer, toc []Asset) error { | |
91 | _, err := fmt.Fprintf(w, `// AssetDir returns the file names below a certain | |
92 | // directory embedded in the file by go-bindata. | |
93 | // For example if you run go-bindata on data/... and data contains the | |
94 | // following hierarchy: | |
95 | // data/ | |
96 | // foo.txt | |
97 | // img/ | |
98 | // a.png | |
99 | // b.png | |
100 | // then AssetDir("data") would return []string{"foo.txt", "img"} | |
101 | // AssetDir("data/img") would return []string{"a.png", "b.png"} | |
102 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error | |
103 | // AssetDir("") will return []string{"data"}. | |
104 | func AssetDir(name string) ([]string, error) { | |
105 | node := _bintree | |
106 | if len(name) != 0 { | |
107 | cannonicalName := strings.Replace(name, "\\", "/", -1) | |
108 | pathList := strings.Split(cannonicalName, "/") | |
109 | for _, p := range pathList { | |
110 | node = node.Children[p] | |
111 | if node == nil { | |
112 | return nil, fmt.Errorf("Asset %%s not found", name) | |
113 | } | |
114 | } | |
115 | } | |
116 | if node.Func != nil { | |
117 | return nil, fmt.Errorf("Asset %%s not found", name) | |
118 | } | |
119 | rv := make([]string, 0, len(node.Children)) | |
120 | for name := range node.Children { | |
121 | rv = append(rv, name) | |
122 | } | |
123 | return rv, nil | |
124 | } | |
125 | ||
126 | `) | |
127 | if err != nil { | |
128 | return err | |
129 | } | |
130 | tree := newAssetTree() | |
131 | for i := range toc { | |
132 | pathList := strings.Split(toc[i].Name, string(os.PathSeparator)) | |
133 | tree.Add(pathList, toc[i]) | |
134 | } | |
135 | return tree.WriteAsGoMap(w) | |
136 | } | |
10 | 137 | |
11 | 138 | // writeTOC writes the table of contents file. |
12 | 139 | func writeTOC(w io.Writer, toc []Asset) error { |
27 | 154 | |
28 | 155 | // writeTOCHeader writes the table of contents file header. |
29 | 156 | func writeTOCHeader(w io.Writer) error { |
30 | _, err := fmt.Fprintf(w, ` | |
31 | // Asset loads and returns the asset for the given name. | |
157 | _, err := fmt.Fprintf(w, `// Asset loads and returns the asset for the given name. | |
32 | 158 | // It returns an error if the asset could not be found or |
33 | 159 | // could not be loaded. |
34 | 160 | func Asset(name string) ([]byte, error) { |
35 | if f, ok := _bindata[name]; ok { | |
161 | cannonicalName := strings.Replace(name, "\\", "/", -1) | |
162 | if f, ok := _bindata[cannonicalName]; ok { | |
36 | 163 | return f() |
37 | 164 | } |
38 | 165 | return nil, fmt.Errorf("Asset %%s not found", name) |
39 | 166 | } |
40 | 167 | |
168 | // AssetNames returns the names of the assets. | |
169 | func AssetNames() []string { | |
170 | names := make([]string, 0, len(_bindata)) | |
171 | for name := range _bindata { | |
172 | names = append(names, name) | |
173 | } | |
174 | return names | |
175 | } | |
176 | ||
41 | 177 | // _bindata is a table, holding each asset generator, mapped to its name. |
42 | var _bindata = map[string] func() ([]byte, error) { | |
178 | var _bindata = map[string]func() ([]byte, error){ | |
43 | 179 | `) |
44 | 180 | return err |
45 | 181 | } |
52 | 188 | |
53 | 189 | // writeTOCFooter writes the table of contents file footer. |
54 | 190 | func writeTOCFooter(w io.Writer) error { |
55 | _, err := fmt.Fprintf(w, ` | |
56 | } | |
191 | _, err := fmt.Fprintf(w, `} | |
57 | 192 | `) |
58 | 193 | return err |
59 | 194 | } |