| ... | ... |
@@ -387,6 +387,11 @@ |
| 387 | 387 |
"Rev": "5a6d06c02600b1e57e55a9d9f71dbac1bfc9fe6c" |
| 388 | 388 |
}, |
| 389 | 389 |
{
|
| 390 |
+ "ImportPath": "github.com/jteeuwen/go-bindata", |
|
| 391 |
+ "Comment": "v3.0.5-31-g93b909d", |
|
| 392 |
+ "Rev": "93b909d1499a38620121b0a5eb43a18f3bccb083" |
|
| 393 |
+ }, |
|
| 394 |
+ {
|
|
| 390 | 395 |
"ImportPath": "github.com/google/gofuzz", |
| 391 | 396 |
"Rev": "aef70dacbc78771e35beb261bb3a72986adf7906" |
| 392 | 397 |
}, |
| 393 | 398 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,79 @@ |
| 0 |
+## Contribution guidelines. |
|
| 1 |
+ |
|
| 2 |
+So you wish to contribute to this project? Fantastic! |
|
| 3 |
+Here are a few guidelines to help you do this in a |
|
| 4 |
+streamlined fashion. |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+## Bug reports |
|
| 8 |
+ |
|
| 9 |
+When supplying a bug report, please consider the following guidelines. |
|
| 10 |
+These serve to make it easier for us to address the issue and find a solution. |
|
| 11 |
+Most of these are pretty self-evident, but sometimes it is still necessary |
|
| 12 |
+to reiterate them. |
|
| 13 |
+ |
|
| 14 |
+* Be clear in the way you express the problem. Use simple language and |
|
| 15 |
+ just enough of it to clearly define the issue. Not everyone is a native |
|
| 16 |
+ English speaker. And while most can handle themselves pretty well, |
|
| 17 |
+ it helps to stay away from more esoteric vocabulary. |
|
| 18 |
+ |
|
| 19 |
+ Be patient with non-native English speakers. If their bug reports |
|
| 20 |
+ or comments are hard to understand, just ask for clarification. |
|
| 21 |
+ Do not start guessing at their meaning, as this may just lead to |
|
| 22 |
+ more confusion and misunderstandings. |
|
| 23 |
+* Clearly define any information which is relevant to the problem. |
|
| 24 |
+ This includes library versions, operating system and any other |
|
| 25 |
+ external dependencies which may be needed. |
|
| 26 |
+* Where applicable, provide a step-by-step listing of the way to |
|
| 27 |
+ reproduce the problem. Make sure this is the simplest possible |
|
| 28 |
+ way to do so. Omit any and all unneccesary steps, because they may |
|
| 29 |
+ just complicate our understanding of the real problem. |
|
| 30 |
+ If need be, create a whole new code project on your local machine, |
|
| 31 |
+ which specifically tries to create the problem you are running into; |
|
| 32 |
+ nothing more, nothing less. |
|
| 33 |
+ |
|
| 34 |
+ Include this program in the bug report. It often suffices to paste |
|
| 35 |
+ the code in a [Gist](https://gist.github.com) or on the |
|
| 36 |
+ [Go playground](http://play.golang.org). |
|
| 37 |
+* If possible, provide us with a listing of the steps you have already |
|
| 38 |
+ undertaken to solve the problem. This can save us a great deal of |
|
| 39 |
+ wasted time, trying out solutions you have already covered. |
|
| 40 |
+ |
|
| 41 |
+ |
|
| 42 |
+## Pull requests |
|
| 43 |
+ |
|
| 44 |
+Bug reports are great. Supplying fixes to bugs is even better. |
|
| 45 |
+When submitting a pull request, the following guidelines are |
|
| 46 |
+good to keep in mind: |
|
| 47 |
+ |
|
| 48 |
+* `go fmt`: **Always** run your code through `go fmt`, before |
|
| 49 |
+ committing it. Code has to be readable by many different |
|
| 50 |
+ people. And the only way this will be as painless as possible, |
|
| 51 |
+ is if we all stick to the same code style. |
|
| 52 |
+ |
|
| 53 |
+ Some of our projects may have automated build-servers hooked up |
|
| 54 |
+ to commit hooks. These will vet any submitted code and determine |
|
| 55 |
+ if it meets a set of properties. One of which is code formatting. |
|
| 56 |
+ These servers will outright deny a submission which has not been |
|
| 57 |
+ run through `go fmt`, even if the code itself is correct. |
|
| 58 |
+ |
|
| 59 |
+ We try to maintain a zero-tolerance policy on this matter, |
|
| 60 |
+ because consistently formatted code makes life a great deal |
|
| 61 |
+ easier for everyone involved. |
|
| 62 |
+* Commit log messages: When committing changes, do so often and |
|
| 63 |
+ clearly -- Even if you have changed only 1 character in a code |
|
| 64 |
+ comment. This means that commit log messages should clearly state |
|
| 65 |
+ exactly what the change does and why. If it fixes a known issue, |
|
| 66 |
+ then mention the issue number in the commit log. E.g.: |
|
| 67 |
+ |
|
| 68 |
+ > Fixes return value for `foo/boo.Baz()` to be consistent with |
|
| 69 |
+ > the rest of the API. This addresses issue #32 |
|
| 70 |
+ |
|
| 71 |
+ Do not pile a lot of unrelated changes into a single commit. |
|
| 72 |
+ Pick and choose only those changes for a single commit, which are |
|
| 73 |
+ directly related. We would much rather see a hundred commits |
|
| 74 |
+ saying nothing but `"Runs go fmt"` in between any real fixes |
|
| 75 |
+ than have these style changes embedded in those real fixes. |
|
| 76 |
+ It creates a lot of noise when trying to review code. |
|
| 77 |
+ |
|
| 78 |
+ |
| 0 | 3 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,189 @@ |
| 0 |
+## bindata |
|
| 1 |
+ |
|
| 2 |
+This package converts any file into managable Go source code. Useful for |
|
| 3 |
+embedding binary data into a go program. The file data is optionally gzip |
|
| 4 |
+compressed before being converted to a raw byte slice. |
|
| 5 |
+ |
|
| 6 |
+It comes with a command line tool in the `go-bindata` sub directory. |
|
| 7 |
+This tool offers a set of command line options, used to customize the |
|
| 8 |
+output being generated. |
|
| 9 |
+ |
|
| 10 |
+ |
|
| 11 |
+### Installation |
|
| 12 |
+ |
|
| 13 |
+To install the library and command line program, use the following: |
|
| 14 |
+ |
|
| 15 |
+ go get github.com/jteeuwen/go-bindata/... |
|
| 16 |
+ |
|
| 17 |
+ |
|
| 18 |
+### Usage |
|
| 19 |
+ |
|
| 20 |
+Conversion is done on one or more sets of files. They are all embedded in a new |
|
| 21 |
+Go source file, along with a table of contents and an `Asset` function, |
|
| 22 |
+which allows quick access to the asset, based on its name. |
|
| 23 |
+ |
|
| 24 |
+The simplest invocation generates a `bindata.go` file in the current |
|
| 25 |
+working directory. It includes all assets from the `data` directory. |
|
| 26 |
+ |
|
| 27 |
+ $ go-bindata data/ |
|
| 28 |
+ |
|
| 29 |
+To include all input sub-directories recursively, use the elipsis postfix |
|
| 30 |
+as defined for Go import paths. Otherwise it will only consider assets in the |
|
| 31 |
+input directory itself. |
|
| 32 |
+ |
|
| 33 |
+ $ go-bindata data/... |
|
| 34 |
+ |
|
| 35 |
+To specify the name of the output file being generated, we use the following: |
|
| 36 |
+ |
|
| 37 |
+ $ go-bindata -o myfile.go data/ |
|
| 38 |
+ |
|
| 39 |
+Multiple input directories can be specified if necessary. |
|
| 40 |
+ |
|
| 41 |
+ $ go-bindata dir1/... /path/to/dir2/... dir3 |
|
| 42 |
+ |
|
| 43 |
+ |
|
| 44 |
+The following paragraphs detail some of the command line options which can be |
|
| 45 |
+supplied to `go-bindata`. Refer to the `testdata/out` directory for various |
|
| 46 |
+output examples from the assets in `testdata/in`. Each example uses different |
|
| 47 |
+command line options. |
|
| 48 |
+ |
|
| 49 |
+To ignore files, pass in regexes using -ignore, for example: |
|
| 50 |
+ |
|
| 51 |
+ $ go-bindata -ignore=\\.gitignore data/... |
|
| 52 |
+ |
|
| 53 |
+### Accessing an asset |
|
| 54 |
+ |
|
| 55 |
+To access asset data, we use the `Asset(string) []byte` function which |
|
| 56 |
+is included in the generated output. |
|
| 57 |
+ |
|
| 58 |
+ data := Asset("pub/style/foo.css")
|
|
| 59 |
+ if len(data) == 0 {
|
|
| 60 |
+ // Asset was not found. |
|
| 61 |
+ } |
|
| 62 |
+ |
|
| 63 |
+ // use asset data |
|
| 64 |
+ |
|
| 65 |
+ |
|
| 66 |
+### Debug vs Release builds |
|
| 67 |
+ |
|
| 68 |
+When invoking the program with the `-debug` flag, the generated code does |
|
| 69 |
+not actually include the asset data. Instead, it generates function stubs |
|
| 70 |
+which load the data from the original file on disk. The asset API remains |
|
| 71 |
+identical between debug and release builds, so your code will not have to |
|
| 72 |
+change. |
|
| 73 |
+ |
|
| 74 |
+This is useful during development when you expect the assets to change often. |
|
| 75 |
+The host application using these assets uses the same API in both cases and |
|
| 76 |
+will not have to care where the actual data comes from. |
|
| 77 |
+ |
|
| 78 |
+An example is a Go webserver with some embedded, static web content like |
|
| 79 |
+HTML, JS and CSS files. While developing it, you do not want to rebuild the |
|
| 80 |
+whole server and restart it every time you make a change to a bit of |
|
| 81 |
+javascript. You just want to build and launch the server once. Then just press |
|
| 82 |
+refresh in the browser to see those changes. Embedding the assets with the |
|
| 83 |
+`debug` flag allows you to do just that. When you are finished developing and |
|
| 84 |
+ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. |
|
| 85 |
+It will now embed the latest version of the assets. |
|
| 86 |
+ |
|
| 87 |
+ |
|
| 88 |
+### Lower memory footprint |
|
| 89 |
+ |
|
| 90 |
+Using the `-nomemcopy` flag, will alter the way the output file is generated. |
|
| 91 |
+It will employ a hack that allows us to read the file data directly from |
|
| 92 |
+the compiled program's `.rodata` section. This ensures that when we call |
|
| 93 |
+call our generated function, we omit unnecessary memcopies. |
|
| 94 |
+ |
|
| 95 |
+The downside of this, is that it requires dependencies on the `reflect` and |
|
| 96 |
+`unsafe` packages. These may be restricted on platforms like AppEngine and |
|
| 97 |
+thus prevent you from using this mode. |
|
| 98 |
+ |
|
| 99 |
+Another disadvantage is that the byte slice we create, is strictly read-only. |
|
| 100 |
+For most use-cases this is not a problem, but if you ever try to alter the |
|
| 101 |
+returned byte slice, a runtime panic is thrown. Use this mode only on target |
|
| 102 |
+platforms where memory constraints are an issue. |
|
| 103 |
+ |
|
| 104 |
+The default behaviour is to use the old code generation method. This |
|
| 105 |
+prevents the two previously mentioned issues, but will employ at least one |
|
| 106 |
+extra memcopy and thus increase memory requirements. |
|
| 107 |
+ |
|
| 108 |
+For instance, consider the following two examples: |
|
| 109 |
+ |
|
| 110 |
+This would be the default mode, using an extra memcopy but gives a safe |
|
| 111 |
+implementation without dependencies on `reflect` and `unsafe`: |
|
| 112 |
+ |
|
| 113 |
+```go |
|
| 114 |
+func myfile() []byte {
|
|
| 115 |
+ return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
|
| 116 |
+} |
|
| 117 |
+``` |
|
| 118 |
+ |
|
| 119 |
+Here is the same functionality, but uses the `.rodata` hack. |
|
| 120 |
+The byte slice returned from this example can not be written to without |
|
| 121 |
+generating a runtime error. |
|
| 122 |
+ |
|
| 123 |
+```go |
|
| 124 |
+var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" |
|
| 125 |
+ |
|
| 126 |
+func myfile() []byte {
|
|
| 127 |
+ var empty [0]byte |
|
| 128 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) |
|
| 129 |
+ b := empty[:] |
|
| 130 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 131 |
+ bx.Data = sx.Data |
|
| 132 |
+ bx.Len = len(_myfile) |
|
| 133 |
+ bx.Cap = bx.Len |
|
| 134 |
+ return b |
|
| 135 |
+} |
|
| 136 |
+``` |
|
| 137 |
+ |
|
| 138 |
+ |
|
| 139 |
+### Optional compression |
|
| 140 |
+ |
|
| 141 |
+When the `-nocompress` flag is given, the supplied resource is *not* GZIP |
|
| 142 |
+compressed before being turned into Go code. The data should still be accessed |
|
| 143 |
+through a function call, so nothing changes in the usage of the generated file. |
|
| 144 |
+ |
|
| 145 |
+This feature is useful if you do not care for compression, or the supplied |
|
| 146 |
+resource is already compressed. Doing it again would not add any value and may |
|
| 147 |
+even increase the size of the data. |
|
| 148 |
+ |
|
| 149 |
+The default behaviour of the program is to use compression. |
|
| 150 |
+ |
|
| 151 |
+ |
|
| 152 |
+### Path prefix stripping |
|
| 153 |
+ |
|
| 154 |
+The keys used in the `_bindata` map, are the same as the input file name |
|
| 155 |
+passed to `go-bindata`. This includes the path. In most cases, this is not |
|
| 156 |
+desireable, as it puts potentially sensitive information in your code base. |
|
| 157 |
+For this purpose, the tool supplies another command line flag `-prefix`. |
|
| 158 |
+This accepts a portion of a path name, which should be stripped off from |
|
| 159 |
+the map keys and function names. |
|
| 160 |
+ |
|
| 161 |
+For example, running without the `-prefix` flag, we get: |
|
| 162 |
+ |
|
| 163 |
+ $ go-bindata /path/to/templates/ |
|
| 164 |
+ |
|
| 165 |
+ _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html |
|
| 166 |
+ |
|
| 167 |
+Running with the `-prefix` flag, we get: |
|
| 168 |
+ |
|
| 169 |
+ $ go-bindata -prefix "/path/to/" /path/to/templates/ |
|
| 170 |
+ |
|
| 171 |
+ _bindata["templates/foo.html"] = templates_foo_html |
|
| 172 |
+ |
|
| 173 |
+ |
|
| 174 |
+### Build tags |
|
| 175 |
+ |
|
| 176 |
+With the optional `-tags` flag, you can specify any go build tags that |
|
| 177 |
+must be fulfilled for the output file to be included in a build. This |
|
| 178 |
+is useful when including binary data in multiple formats, where the desired |
|
| 179 |
+format is specified at build time with the appropriate tags. |
|
| 180 |
+ |
|
| 181 |
+The tags are appended to a `// +build` line in the beginning of the output file |
|
| 182 |
+and must follow the build tags syntax specified by the go tool. |
|
| 183 |
+ |
|
| 184 |
+### Related projects |
|
| 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 |
+ |
| 0 | 189 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,12 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+// Asset holds information about a single asset to be processed. |
|
| 7 |
+type Asset struct {
|
|
| 8 |
+ Path string // Full file path. |
|
| 9 |
+ Name string // Key used in TOC -- name by which asset is referenced. |
|
| 10 |
+ Func string // Function name for the procedure returning the asset contents. |
|
| 11 |
+} |
| 0 | 12 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,44 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+var ( |
|
| 12 |
+ newline = []byte{'\n'}
|
|
| 13 |
+ dataindent = []byte{'\t', '\t'}
|
|
| 14 |
+ space = []byte{' '}
|
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+type ByteWriter struct {
|
|
| 18 |
+ io.Writer |
|
| 19 |
+ c int |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+func (w *ByteWriter) Write(p []byte) (n int, err error) {
|
|
| 23 |
+ if len(p) == 0 {
|
|
| 24 |
+ return |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ for n = range p {
|
|
| 28 |
+ if w.c%12 == 0 {
|
|
| 29 |
+ w.Writer.Write(newline) |
|
| 30 |
+ w.Writer.Write(dataindent) |
|
| 31 |
+ w.c = 0 |
|
| 32 |
+ } else {
|
|
| 33 |
+ w.Writer.Write(space) |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ fmt.Fprintf(w.Writer, "0x%02x,", p[n]) |
|
| 37 |
+ w.c++ |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ n++ |
|
| 41 |
+ |
|
| 42 |
+ return |
|
| 43 |
+} |
| 0 | 44 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,192 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "os" |
|
| 9 |
+ "path/filepath" |
|
| 10 |
+ "regexp" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// InputConfig defines options on a asset directory to be convert. |
|
| 14 |
+type InputConfig struct {
|
|
| 15 |
+ // Path defines a directory containing asset files to be included |
|
| 16 |
+ // in the generated output. |
|
| 17 |
+ Path string |
|
| 18 |
+ |
|
| 19 |
+ // Recusive defines whether subdirectories of Path |
|
| 20 |
+ // should be recursively included in the conversion. |
|
| 21 |
+ Recursive bool |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// Config defines a set of options for the asset conversion. |
|
| 25 |
+type Config struct {
|
|
| 26 |
+ // Name of the package to use. Defaults to 'main'. |
|
| 27 |
+ Package string |
|
| 28 |
+ |
|
| 29 |
+ // Tags specify a set of optional build tags, which should be |
|
| 30 |
+ // included in the generated output. The tags are appended to a |
|
| 31 |
+ // `// +build` line in the beginning of the output file |
|
| 32 |
+ // and must follow the build tags syntax specified by the go tool. |
|
| 33 |
+ Tags string |
|
| 34 |
+ |
|
| 35 |
+ // Input defines the directory path, containing all asset files as |
|
| 36 |
+ // well as whether to recursively process assets in any sub directories. |
|
| 37 |
+ Input []InputConfig |
|
| 38 |
+ |
|
| 39 |
+ // Output defines the output file for the generated code. |
|
| 40 |
+ // If left empty, this defaults to 'bindata.go' in the current |
|
| 41 |
+ // working directory. |
|
| 42 |
+ Output string |
|
| 43 |
+ |
|
| 44 |
+ // Prefix defines a path prefix which should be stripped from all |
|
| 45 |
+ // file names when generating the keys in the table of contents. |
|
| 46 |
+ // For example, running without the `-prefix` flag, we get: |
|
| 47 |
+ // |
|
| 48 |
+ // $ go-bindata /path/to/templates |
|
| 49 |
+ // go_bindata["/path/to/templates/foo.html"] = _path_to_templates_foo_html |
|
| 50 |
+ // |
|
| 51 |
+ // Running with the `-prefix` flag, we get: |
|
| 52 |
+ // |
|
| 53 |
+ // $ go-bindata -prefix "/path/to/" /path/to/templates/foo.html |
|
| 54 |
+ // go_bindata["templates/foo.html"] = templates_foo_html |
|
| 55 |
+ Prefix string |
|
| 56 |
+ |
|
| 57 |
+ // NoMemCopy will alter the way the output file is generated. |
|
| 58 |
+ // |
|
| 59 |
+ // It will employ a hack that allows us to read the file data directly from |
|
| 60 |
+ // the compiled program's `.rodata` section. This ensures that when we call |
|
| 61 |
+ // call our generated function, we omit unnecessary mem copies. |
|
| 62 |
+ // |
|
| 63 |
+ // The downside of this, is that it requires dependencies on the `reflect` and |
|
| 64 |
+ // `unsafe` packages. These may be restricted on platforms like AppEngine and |
|
| 65 |
+ // thus prevent you from using this mode. |
|
| 66 |
+ // |
|
| 67 |
+ // Another disadvantage is that the byte slice we create, is strictly read-only. |
|
| 68 |
+ // For most use-cases this is not a problem, but if you ever try to alter the |
|
| 69 |
+ // returned byte slice, a runtime panic is thrown. Use this mode only on target |
|
| 70 |
+ // platforms where memory constraints are an issue. |
|
| 71 |
+ // |
|
| 72 |
+ // The default behaviour is to use the old code generation method. This |
|
| 73 |
+ // prevents the two previously mentioned issues, but will employ at least one |
|
| 74 |
+ // extra memcopy and thus increase memory requirements. |
|
| 75 |
+ // |
|
| 76 |
+ // For instance, consider the following two examples: |
|
| 77 |
+ // |
|
| 78 |
+ // This would be the default mode, using an extra memcopy but gives a safe |
|
| 79 |
+ // implementation without dependencies on `reflect` and `unsafe`: |
|
| 80 |
+ // |
|
| 81 |
+ // func myfile() []byte {
|
|
| 82 |
+ // return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
|
| 83 |
+ // } |
|
| 84 |
+ // |
|
| 85 |
+ // Here is the same functionality, but uses the `.rodata` hack. |
|
| 86 |
+ // The byte slice returned from this example can not be written to without |
|
| 87 |
+ // generating a runtime error. |
|
| 88 |
+ // |
|
| 89 |
+ // var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" |
|
| 90 |
+ // |
|
| 91 |
+ // func myfile() []byte {
|
|
| 92 |
+ // var empty [0]byte |
|
| 93 |
+ // sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) |
|
| 94 |
+ // b := empty[:] |
|
| 95 |
+ // bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 96 |
+ // bx.Data = sx.Data |
|
| 97 |
+ // bx.Len = len(_myfile) |
|
| 98 |
+ // bx.Cap = bx.Len |
|
| 99 |
+ // return b |
|
| 100 |
+ // } |
|
| 101 |
+ NoMemCopy bool |
|
| 102 |
+ |
|
| 103 |
+ // NoCompress means the assets are /not/ GZIP compressed before being turned |
|
| 104 |
+ // into Go code. The generated function will automatically unzip |
|
| 105 |
+ // the file data when called. Defaults to false. |
|
| 106 |
+ NoCompress bool |
|
| 107 |
+ |
|
| 108 |
+ // Perform a debug build. This generates an asset file, which |
|
| 109 |
+ // loads the asset contents directly from disk at their original |
|
| 110 |
+ // location, instead of embedding the contents in the code. |
|
| 111 |
+ // |
|
| 112 |
+ // This is mostly useful if you anticipate that the assets are |
|
| 113 |
+ // going to change during your development cycle. You will always |
|
| 114 |
+ // want your code to access the latest version of the asset. |
|
| 115 |
+ // Only in release mode, will the assets actually be embedded |
|
| 116 |
+ // in the code. The default behaviour is Release mode. |
|
| 117 |
+ Debug bool |
|
| 118 |
+ |
|
| 119 |
+ // Recursively process all assets in the input directory and its |
|
| 120 |
+ // sub directories. This defaults to false, so only files in the |
|
| 121 |
+ // input directory itself are read. |
|
| 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 |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+// NewConfig returns a default configuration struct. |
|
| 133 |
+func NewConfig() *Config {
|
|
| 134 |
+ c := new(Config) |
|
| 135 |
+ c.Package = "main" |
|
| 136 |
+ c.NoMemCopy = false |
|
| 137 |
+ c.NoCompress = false |
|
| 138 |
+ c.Debug = false |
|
| 139 |
+ c.Recursive = false |
|
| 140 |
+ c.Output = "./bindata.go" |
|
| 141 |
+ c.Ignore = make([]*regexp.Regexp, 0) |
|
| 142 |
+ return c |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+// validate ensures the config has sane values. |
|
| 146 |
+// Part of which means checking if certain file/directory paths exist. |
|
| 147 |
+func (c *Config) validate() error {
|
|
| 148 |
+ if len(c.Package) == 0 {
|
|
| 149 |
+ return fmt.Errorf("Missing package name")
|
|
| 150 |
+ } |
|
| 151 |
+ |
|
| 152 |
+ for _, input := range c.Input {
|
|
| 153 |
+ _, err := os.Lstat(input.Path) |
|
| 154 |
+ if err != nil {
|
|
| 155 |
+ return fmt.Errorf("Failed to stat input path '%s': %v", input.Path, err)
|
|
| 156 |
+ } |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ if len(c.Output) == 0 {
|
|
| 160 |
+ cwd, err := os.Getwd() |
|
| 161 |
+ if err != nil {
|
|
| 162 |
+ return fmt.Errorf("Unable to determine current working directory.")
|
|
| 163 |
+ } |
|
| 164 |
+ |
|
| 165 |
+ c.Output = filepath.Join(cwd, "bindata.go") |
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 168 |
+ stat, err := os.Lstat(c.Output) |
|
| 169 |
+ if err != nil {
|
|
| 170 |
+ if !os.IsNotExist(err) {
|
|
| 171 |
+ return fmt.Errorf("Output path: %v", err)
|
|
| 172 |
+ } |
|
| 173 |
+ |
|
| 174 |
+ // File does not exist. This is fine, just make |
|
| 175 |
+ // sure the directory it is to be in exists. |
|
| 176 |
+ dir, _ := filepath.Split(c.Output) |
|
| 177 |
+ if dir != "" {
|
|
| 178 |
+ err = os.MkdirAll(dir, 0744) |
|
| 179 |
+ |
|
| 180 |
+ if err != nil {
|
|
| 181 |
+ return fmt.Errorf("Create output directory: %v", err)
|
|
| 182 |
+ } |
|
| 183 |
+ } |
|
| 184 |
+ } |
|
| 185 |
+ |
|
| 186 |
+ if stat != nil && stat.IsDir() {
|
|
| 187 |
+ return fmt.Errorf("Output path is a directory.")
|
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 190 |
+ return nil |
|
| 191 |
+} |
| 0 | 192 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,196 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "bufio" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ "os" |
|
| 10 |
+ "path/filepath" |
|
| 11 |
+ "regexp" |
|
| 12 |
+ "strings" |
|
| 13 |
+ "unicode" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+// Translate reads assets from an input directory, converts them |
|
| 17 |
+// to Go code and writes new files to the output specified |
|
| 18 |
+// in the given configuration. |
|
| 19 |
+func Translate(c *Config) error {
|
|
| 20 |
+ var toc []Asset |
|
| 21 |
+ |
|
| 22 |
+ // Ensure our configuration has sane values. |
|
| 23 |
+ err := c.validate() |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return err |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ // Locate all the assets. |
|
| 29 |
+ for _, input := range c.Input {
|
|
| 30 |
+ err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore) |
|
| 31 |
+ if err != nil {
|
|
| 32 |
+ return err |
|
| 33 |
+ } |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ // Create output file. |
|
| 37 |
+ fd, err := os.Create(c.Output) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return err |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ defer fd.Close() |
|
| 43 |
+ |
|
| 44 |
+ // Create a buffered writer for better performance. |
|
| 45 |
+ bfd := bufio.NewWriter(fd) |
|
| 46 |
+ defer bfd.Flush() |
|
| 47 |
+ |
|
| 48 |
+ // Write build tags, if applicable. |
|
| 49 |
+ if len(c.Tags) > 0 {
|
|
| 50 |
+ _, err = fmt.Fprintf(bfd, "// +build %s\n\n", c.Tags) |
|
| 51 |
+ if err != nil {
|
|
| 52 |
+ return err |
|
| 53 |
+ } |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ // Write package declaration. |
|
| 57 |
+ _, err = fmt.Fprintf(bfd, "package %s\n\n", c.Package) |
|
| 58 |
+ if err != nil {
|
|
| 59 |
+ return err |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ // Write assets. |
|
| 63 |
+ if c.Debug {
|
|
| 64 |
+ err = writeDebug(bfd, toc) |
|
| 65 |
+ } else {
|
|
| 66 |
+ err = writeRelease(bfd, c, toc) |
|
| 67 |
+ } |
|
| 68 |
+ |
|
| 69 |
+ if err != nil {
|
|
| 70 |
+ return err |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ // Write table of contents |
|
| 74 |
+ if err := writeTOC(bfd, toc); err != nil {
|
|
| 75 |
+ return err |
|
| 76 |
+ } |
|
| 77 |
+ // Write hierarchical tree of assets |
|
| 78 |
+ return writeTOCTree(bfd, toc) |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+// findFiles recursively finds all the file paths in the given directory tree. |
|
| 82 |
+// They are added to the given map as keys. Values will be safe function names |
|
| 83 |
+// for each file, which will be used when generating the output code. |
|
| 84 |
+func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp) error {
|
|
| 85 |
+ if len(prefix) > 0 {
|
|
| 86 |
+ dir, _ = filepath.Abs(dir) |
|
| 87 |
+ prefix, _ = filepath.Abs(prefix) |
|
| 88 |
+ prefix = filepath.ToSlash(prefix) |
|
| 89 |
+ } |
|
| 90 |
+ |
|
| 91 |
+ fi, err := os.Stat(dir) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ return err |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ var list []os.FileInfo |
|
| 97 |
+ |
|
| 98 |
+ if !fi.IsDir() {
|
|
| 99 |
+ dir = "" |
|
| 100 |
+ list = []os.FileInfo{fi}
|
|
| 101 |
+ } else {
|
|
| 102 |
+ fd, err := os.Open(dir) |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ return err |
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ defer fd.Close() |
|
| 108 |
+ |
|
| 109 |
+ list, err = fd.Readdir(0) |
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ return err |
|
| 112 |
+ } |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ knownFuncs := make(map[string]int) |
|
| 116 |
+ |
|
| 117 |
+ for _, file := range list {
|
|
| 118 |
+ var asset Asset |
|
| 119 |
+ asset.Path = filepath.Join(dir, file.Name()) |
|
| 120 |
+ asset.Name = filepath.ToSlash(asset.Path) |
|
| 121 |
+ |
|
| 122 |
+ ignoring := false |
|
| 123 |
+ for _, re := range ignore {
|
|
| 124 |
+ if re.MatchString(asset.Path) {
|
|
| 125 |
+ ignoring = true |
|
| 126 |
+ break |
|
| 127 |
+ } |
|
| 128 |
+ } |
|
| 129 |
+ if ignoring {
|
|
| 130 |
+ continue |
|
| 131 |
+ } |
|
| 132 |
+ |
|
| 133 |
+ if file.IsDir() {
|
|
| 134 |
+ if recursive {
|
|
| 135 |
+ findFiles(asset.Path, prefix, recursive, toc, ignore) |
|
| 136 |
+ } |
|
| 137 |
+ continue |
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ if strings.HasPrefix(asset.Name, prefix) {
|
|
| 141 |
+ asset.Name = asset.Name[len(prefix):] |
|
| 142 |
+ } |
|
| 143 |
+ |
|
| 144 |
+ // If we have a leading slash, get rid of it. |
|
| 145 |
+ if len(asset.Name) > 0 && asset.Name[0] == '/' {
|
|
| 146 |
+ asset.Name = asset.Name[1:] |
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ // This shouldn't happen. |
|
| 150 |
+ if len(asset.Name) == 0 {
|
|
| 151 |
+ return fmt.Errorf("Invalid file: %v", asset.Path)
|
|
| 152 |
+ } |
|
| 153 |
+ |
|
| 154 |
+ asset.Func = safeFunctionName(asset.Name, knownFuncs) |
|
| 155 |
+ asset.Path, _ = filepath.Abs(asset.Path) |
|
| 156 |
+ *toc = append(*toc, asset) |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ return nil |
|
| 160 |
+} |
|
| 161 |
+ |
|
| 162 |
+var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`) |
|
| 163 |
+ |
|
| 164 |
+// safeFunctionName converts the given name into a name |
|
| 165 |
+// which qualifies as a valid function identifier. It |
|
| 166 |
+// also compares against a known list of functions to |
|
| 167 |
+// prevent conflict based on name translation. |
|
| 168 |
+func safeFunctionName(name string, knownFuncs map[string]int) string {
|
|
| 169 |
+ name = strings.ToLower(name) |
|
| 170 |
+ name = regFuncName.ReplaceAllString(name, "_") |
|
| 171 |
+ |
|
| 172 |
+ // Get rid of "__" instances for niceness. |
|
| 173 |
+ for strings.Index(name, "__") > -1 {
|
|
| 174 |
+ name = strings.Replace(name, "__", "_", -1) |
|
| 175 |
+ } |
|
| 176 |
+ |
|
| 177 |
+ // Leading underscores are silly (unless they prefix a digit (see below)). |
|
| 178 |
+ for len(name) > 1 && name[0] == '_' {
|
|
| 179 |
+ name = name[1:] |
|
| 180 |
+ } |
|
| 181 |
+ |
|
| 182 |
+ // Identifier can't start with a digit. |
|
| 183 |
+ if unicode.IsDigit(rune(name[0])) {
|
|
| 184 |
+ name = "_" + name |
|
| 185 |
+ } |
|
| 186 |
+ |
|
| 187 |
+ if num, ok := knownFuncs[name]; ok {
|
|
| 188 |
+ knownFuncs[name] = num + 1 |
|
| 189 |
+ name = fmt.Sprintf("%s%d", name, num)
|
|
| 190 |
+ } else {
|
|
| 191 |
+ knownFuncs[name] = 2 |
|
| 192 |
+ } |
|
| 193 |
+ |
|
| 194 |
+ return name |
|
| 195 |
+} |
| 0 | 196 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,65 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// writeDebug writes the debug code file. |
|
| 12 |
+func writeDebug(w io.Writer, toc []Asset) error {
|
|
| 13 |
+ err := writeDebugHeader(w) |
|
| 14 |
+ if err != nil {
|
|
| 15 |
+ return err |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ for i := range toc {
|
|
| 19 |
+ err = writeDebugAsset(w, &toc[i]) |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ return err |
|
| 22 |
+ } |
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ return nil |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+// writeDebugHeader writes output file headers. |
|
| 29 |
+// This targets debug builds. |
|
| 30 |
+func writeDebugHeader(w io.Writer) error {
|
|
| 31 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 32 |
+ "fmt" |
|
| 33 |
+ "io/ioutil" |
|
| 34 |
+ "strings" |
|
| 35 |
+) |
|
| 36 |
+ |
|
| 37 |
+// bindata_read reads the given file from disk. It returns an error on failure. |
|
| 38 |
+func bindata_read(path, name string) ([]byte, error) {
|
|
| 39 |
+ buf, err := ioutil.ReadFile(path) |
|
| 40 |
+ if err != nil {
|
|
| 41 |
+ err = fmt.Errorf("Error reading asset %%s at %%s: %%v", name, path, err)
|
|
| 42 |
+ } |
|
| 43 |
+ return buf, err |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+`) |
|
| 47 |
+ return err |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+// writeDebugAsset write a debug entry for the given asset. |
|
| 51 |
+// A debug entry is simply a function which reads the asset from |
|
| 52 |
+// the original file (e.g.: from disk). |
|
| 53 |
+func writeDebugAsset(w io.Writer, asset *Asset) error {
|
|
| 54 |
+ _, err := fmt.Fprintf(w, `// %s reads file data from disk. It returns an error on failure. |
|
| 55 |
+func %s() ([]byte, error) {
|
|
| 56 |
+ return bindata_read( |
|
| 57 |
+ %q, |
|
| 58 |
+ %q, |
|
| 59 |
+ ) |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+`, asset.Func, asset.Func, asset.Path, asset.Name) |
|
| 63 |
+ return err |
|
| 64 |
+} |
| 0 | 65 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,129 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+bindata converts any file into managable Go source code. Useful for |
|
| 6 |
+embedding binary data into a go program. The file data is optionally gzip |
|
| 7 |
+compressed before being converted to a raw byte slice. |
|
| 8 |
+ |
|
| 9 |
+The following paragraphs cover some of the customization options |
|
| 10 |
+which can be specified in the Config struct, which must be passed into |
|
| 11 |
+the Translate() call. |
|
| 12 |
+ |
|
| 13 |
+ |
|
| 14 |
+Debug vs Release builds |
|
| 15 |
+ |
|
| 16 |
+When used with the `Debug` option, the generated code does not actually include |
|
| 17 |
+the asset data. Instead, it generates function stubs which load the data from |
|
| 18 |
+the original file on disk. The asset API remains identical between debug and |
|
| 19 |
+release builds, so your code will not have to change. |
|
| 20 |
+ |
|
| 21 |
+This is useful during development when you expect the assets to change often. |
|
| 22 |
+The host application using these assets uses the same API in both cases and |
|
| 23 |
+will not have to care where the actual data comes from. |
|
| 24 |
+ |
|
| 25 |
+An example is a Go webserver with some embedded, static web content like |
|
| 26 |
+HTML, JS and CSS files. While developing it, you do not want to rebuild the |
|
| 27 |
+whole server and restart it every time you make a change to a bit of |
|
| 28 |
+javascript. You just want to build and launch the server once. Then just press |
|
| 29 |
+refresh in the browser to see those changes. Embedding the assets with the |
|
| 30 |
+`debug` flag allows you to do just that. When you are finished developing and |
|
| 31 |
+ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. |
|
| 32 |
+It will now embed the latest version of the assets. |
|
| 33 |
+ |
|
| 34 |
+ |
|
| 35 |
+Lower memory footprint |
|
| 36 |
+ |
|
| 37 |
+The `NoMemCopy` option will alter the way the output file is generated. |
|
| 38 |
+It will employ a hack that allows us to read the file data directly from |
|
| 39 |
+the compiled program's `.rodata` section. This ensures that when we call |
|
| 40 |
+call our generated function, we omit unnecessary memcopies. |
|
| 41 |
+ |
|
| 42 |
+The downside of this, is that it requires dependencies on the `reflect` and |
|
| 43 |
+`unsafe` packages. These may be restricted on platforms like AppEngine and |
|
| 44 |
+thus prevent you from using this mode. |
|
| 45 |
+ |
|
| 46 |
+Another disadvantage is that the byte slice we create, is strictly read-only. |
|
| 47 |
+For most use-cases this is not a problem, but if you ever try to alter the |
|
| 48 |
+returned byte slice, a runtime panic is thrown. Use this mode only on target |
|
| 49 |
+platforms where memory constraints are an issue. |
|
| 50 |
+ |
|
| 51 |
+The default behaviour is to use the old code generation method. This |
|
| 52 |
+prevents the two previously mentioned issues, but will employ at least one |
|
| 53 |
+extra memcopy and thus increase memory requirements. |
|
| 54 |
+ |
|
| 55 |
+For instance, consider the following two examples: |
|
| 56 |
+ |
|
| 57 |
+This would be the default mode, using an extra memcopy but gives a safe |
|
| 58 |
+implementation without dependencies on `reflect` and `unsafe`: |
|
| 59 |
+ |
|
| 60 |
+ func myfile() []byte {
|
|
| 61 |
+ return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+Here is the same functionality, but uses the `.rodata` hack. |
|
| 65 |
+The byte slice returned from this example can not be written to without |
|
| 66 |
+generating a runtime error. |
|
| 67 |
+ |
|
| 68 |
+ var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" |
|
| 69 |
+ |
|
| 70 |
+ func myfile() []byte {
|
|
| 71 |
+ var empty [0]byte |
|
| 72 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) |
|
| 73 |
+ b := empty[:] |
|
| 74 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 75 |
+ bx.Data = sx.Data |
|
| 76 |
+ bx.Len = len(_myfile) |
|
| 77 |
+ bx.Cap = bx.Len |
|
| 78 |
+ return b |
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ |
|
| 82 |
+Optional compression |
|
| 83 |
+ |
|
| 84 |
+The NoCompress option indicates that the supplied assets are *not* GZIP |
|
| 85 |
+compressed before being turned into Go code. The data should still be accessed |
|
| 86 |
+through a function call, so nothing changes in the API. |
|
| 87 |
+ |
|
| 88 |
+This feature is useful if you do not care for compression, or the supplied |
|
| 89 |
+resource is already compressed. Doing it again would not add any value and may |
|
| 90 |
+even increase the size of the data. |
|
| 91 |
+ |
|
| 92 |
+The default behaviour of the program is to use compression. |
|
| 93 |
+ |
|
| 94 |
+ |
|
| 95 |
+Path prefix stripping |
|
| 96 |
+ |
|
| 97 |
+The keys used in the `_bindata` map are the same as the input file name |
|
| 98 |
+passed to `go-bindata`. This includes the path. In most cases, this is not |
|
| 99 |
+desireable, as it puts potentially sensitive information in your code base. |
|
| 100 |
+For this purpose, the tool supplies another command line flag `-prefix`. |
|
| 101 |
+This accepts a portion of a path name, which should be stripped off from |
|
| 102 |
+the map keys and function names. |
|
| 103 |
+ |
|
| 104 |
+For example, running without the `-prefix` flag, we get: |
|
| 105 |
+ |
|
| 106 |
+ $ go-bindata /path/to/templates/ |
|
| 107 |
+ |
|
| 108 |
+ _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html |
|
| 109 |
+ |
|
| 110 |
+Running with the `-prefix` flag, we get: |
|
| 111 |
+ |
|
| 112 |
+ $ go-bindata -prefix "/path/to/" /path/to/templates/ |
|
| 113 |
+ |
|
| 114 |
+ _bindata["templates/foo.html"] = templates_foo_html |
|
| 115 |
+ |
|
| 116 |
+ |
|
| 117 |
+Build tags |
|
| 118 |
+ |
|
| 119 |
+With the optional Tags field, you can specify any go build tags that |
|
| 120 |
+must be fulfilled for the output file to be included in a build. This |
|
| 121 |
+is useful when including binary data in multiple formats, where the desired |
|
| 122 |
+format is specified at build time with the appropriate tags. |
|
| 123 |
+ |
|
| 124 |
+The tags are appended to a `// +build` line in the beginning of the output file |
|
| 125 |
+and must follow the build tags syntax specified by the go tool. |
|
| 126 |
+ |
|
| 127 |
+*/ |
|
| 128 |
+package bindata |
| 0 | 129 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 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 |
+} |
| 0 | 22 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,102 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package main |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "flag" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ "github.com/jteeuwen/go-bindata" |
|
| 10 |
+ "os" |
|
| 11 |
+ "path/filepath" |
|
| 12 |
+ "regexp" |
|
| 13 |
+ "strings" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func main() {
|
|
| 17 |
+ cfg := parseArgs() |
|
| 18 |
+ err := bindata.Translate(cfg) |
|
| 19 |
+ |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ fmt.Fprintf(os.Stderr, "bindata: %v\n", err) |
|
| 22 |
+ os.Exit(1) |
|
| 23 |
+ } |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+// parseArgs create s a new, filled configuration instance |
|
| 27 |
+// by reading and parsing command line options. |
|
| 28 |
+// |
|
| 29 |
+// This function exits the program with an error, if |
|
| 30 |
+// any of the command line options are incorrect. |
|
| 31 |
+func parseArgs() *bindata.Config {
|
|
| 32 |
+ var version bool |
|
| 33 |
+ |
|
| 34 |
+ c := bindata.NewConfig() |
|
| 35 |
+ |
|
| 36 |
+ flag.Usage = func() {
|
|
| 37 |
+ fmt.Printf("Usage: %s [options] <input directories>\n\n", os.Args[0])
|
|
| 38 |
+ flag.PrintDefaults() |
|
| 39 |
+ } |
|
| 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.") |
|
| 42 |
+ flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of build tags to include.") |
|
| 43 |
+ flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off asset names.") |
|
| 44 |
+ flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.") |
|
| 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.") |
|
| 46 |
+ flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.") |
|
| 47 |
+ flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.") |
|
| 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 |
+ |
|
| 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 |
|
| 60 |
+ |
|
| 61 |
+ if version {
|
|
| 62 |
+ fmt.Printf("%s\n", Version())
|
|
| 63 |
+ os.Exit(0) |
|
| 64 |
+ } |
|
| 65 |
+ |
|
| 66 |
+ // Make sure we have input paths. |
|
| 67 |
+ if flag.NArg() == 0 {
|
|
| 68 |
+ fmt.Fprintf(os.Stderr, "Missing <input dir>\n\n") |
|
| 69 |
+ flag.Usage() |
|
| 70 |
+ os.Exit(1) |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ // Create input configurations. |
|
| 74 |
+ c.Input = make([]bindata.InputConfig, flag.NArg()) |
|
| 75 |
+ for i := range c.Input {
|
|
| 76 |
+ c.Input[i] = parseInput(flag.Arg(i)) |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ return c |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+// parseRecursive determines whether the given path has a recrusive indicator and |
|
| 83 |
+// returns a new path with the recursive indicator chopped off if it does. |
|
| 84 |
+// |
|
| 85 |
+// ex: |
|
| 86 |
+// /path/to/foo/... -> (/path/to/foo, true) |
|
| 87 |
+// /path/to/bar -> (/path/to/bar, false) |
|
| 88 |
+func parseInput(path string) bindata.InputConfig {
|
|
| 89 |
+ if strings.HasSuffix(path, "/...") {
|
|
| 90 |
+ return bindata.InputConfig{
|
|
| 91 |
+ Path: filepath.Clean(path[:len(path)-4]), |
|
| 92 |
+ Recursive: true, |
|
| 93 |
+ } |
|
| 94 |
+ } else {
|
|
| 95 |
+ return bindata.InputConfig{
|
|
| 96 |
+ Path: filepath.Clean(path), |
|
| 97 |
+ Recursive: false, |
|
| 98 |
+ } |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+} |
| 0 | 102 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,31 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package main |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "runtime" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+const ( |
|
| 12 |
+ AppName = "go-bindata" |
|
| 13 |
+ AppVersionMajor = 3 |
|
| 14 |
+ AppVersionMinor = 1 |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+// revision part of the program version. |
|
| 18 |
+// This will be set automatically at build time like so: |
|
| 19 |
+// |
|
| 20 |
+// go build -ldflags "-X main.AppVersionRev `date -u +%s`" |
|
| 21 |
+var AppVersionRev string |
|
| 22 |
+ |
|
| 23 |
+func Version() string {
|
|
| 24 |
+ if len(AppVersionRev) == 0 {
|
|
| 25 |
+ AppVersionRev = "0" |
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ return fmt.Sprintf("%s %d.%d.%s (Go runtime %s).\nCopyright (c) 2010-2013, Jim Teeuwen.",
|
|
| 29 |
+ AppName, AppVersionMajor, AppVersionMinor, AppVersionRev, runtime.Version()) |
|
| 30 |
+} |
| 0 | 31 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,272 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "compress/gzip" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ "io" |
|
| 10 |
+ "os" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+// writeRelease writes the release code file. |
|
| 14 |
+func writeRelease(w io.Writer, c *Config, toc []Asset) error {
|
|
| 15 |
+ err := writeReleaseHeader(w, c) |
|
| 16 |
+ if err != nil {
|
|
| 17 |
+ return err |
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ for i := range toc {
|
|
| 21 |
+ err = writeReleaseAsset(w, c, &toc[i]) |
|
| 22 |
+ if err != nil {
|
|
| 23 |
+ return err |
|
| 24 |
+ } |
|
| 25 |
+ } |
|
| 26 |
+ |
|
| 27 |
+ return nil |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+// writeReleaseHeader writes output file headers. |
|
| 31 |
+// This targets release builds. |
|
| 32 |
+func writeReleaseHeader(w io.Writer, c *Config) error {
|
|
| 33 |
+ if c.NoCompress {
|
|
| 34 |
+ if c.NoMemCopy {
|
|
| 35 |
+ return header_uncompressed_nomemcopy(w) |
|
| 36 |
+ } else {
|
|
| 37 |
+ return header_uncompressed_memcopy(w) |
|
| 38 |
+ } |
|
| 39 |
+ } else {
|
|
| 40 |
+ if c.NoMemCopy {
|
|
| 41 |
+ return header_compressed_nomemcopy(w) |
|
| 42 |
+ } else {
|
|
| 43 |
+ return header_compressed_memcopy(w) |
|
| 44 |
+ } |
|
| 45 |
+ } |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// writeReleaseAsset write a release entry for the given asset. |
|
| 49 |
+// A release entry is a function which embeds and returns |
|
| 50 |
+// the file's byte content. |
|
| 51 |
+func writeReleaseAsset(w io.Writer, c *Config, asset *Asset) error {
|
|
| 52 |
+ fd, err := os.Open(asset.Path) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return err |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ defer fd.Close() |
|
| 58 |
+ |
|
| 59 |
+ if c.NoCompress {
|
|
| 60 |
+ if c.NoMemCopy {
|
|
| 61 |
+ return uncompressed_nomemcopy(w, asset, fd) |
|
| 62 |
+ } else {
|
|
| 63 |
+ return uncompressed_memcopy(w, asset, fd) |
|
| 64 |
+ } |
|
| 65 |
+ } else {
|
|
| 66 |
+ if c.NoMemCopy {
|
|
| 67 |
+ return compressed_nomemcopy(w, asset, fd) |
|
| 68 |
+ } else {
|
|
| 69 |
+ return compressed_memcopy(w, asset, fd) |
|
| 70 |
+ } |
|
| 71 |
+ } |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+func header_compressed_nomemcopy(w io.Writer) error {
|
|
| 75 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 76 |
+ "bytes" |
|
| 77 |
+ "compress/gzip" |
|
| 78 |
+ "fmt" |
|
| 79 |
+ "io" |
|
| 80 |
+ "reflect" |
|
| 81 |
+ "strings" |
|
| 82 |
+ "unsafe" |
|
| 83 |
+) |
|
| 84 |
+ |
|
| 85 |
+func bindata_read(data, name string) ([]byte, error) {
|
|
| 86 |
+ var empty [0]byte |
|
| 87 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 88 |
+ b := empty[:] |
|
| 89 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 90 |
+ bx.Data = sx.Data |
|
| 91 |
+ bx.Len = len(data) |
|
| 92 |
+ bx.Cap = bx.Len |
|
| 93 |
+ |
|
| 94 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(b)) |
|
| 95 |
+ if err != nil {
|
|
| 96 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ var buf bytes.Buffer |
|
| 100 |
+ _, err = io.Copy(&buf, gz) |
|
| 101 |
+ gz.Close() |
|
| 102 |
+ |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ return buf.Bytes(), nil |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+`) |
|
| 111 |
+ return err |
|
| 112 |
+} |
|
| 113 |
+ |
|
| 114 |
+func header_compressed_memcopy(w io.Writer) error {
|
|
| 115 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 116 |
+ "bytes" |
|
| 117 |
+ "compress/gzip" |
|
| 118 |
+ "fmt" |
|
| 119 |
+ "io" |
|
| 120 |
+ "strings" |
|
| 121 |
+) |
|
| 122 |
+ |
|
| 123 |
+func bindata_read(data []byte, name string) ([]byte, error) {
|
|
| 124 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(data)) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ var buf bytes.Buffer |
|
| 130 |
+ _, err = io.Copy(&buf, gz) |
|
| 131 |
+ gz.Close() |
|
| 132 |
+ |
|
| 133 |
+ if err != nil {
|
|
| 134 |
+ return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ return buf.Bytes(), nil |
|
| 138 |
+} |
|
| 139 |
+ |
|
| 140 |
+`) |
|
| 141 |
+ return err |
|
| 142 |
+} |
|
| 143 |
+ |
|
| 144 |
+func header_uncompressed_nomemcopy(w io.Writer) error {
|
|
| 145 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 146 |
+ "fmt" |
|
| 147 |
+ "reflect" |
|
| 148 |
+ "strings" |
|
| 149 |
+ "unsafe" |
|
| 150 |
+) |
|
| 151 |
+ |
|
| 152 |
+func bindata_read(data, name string) ([]byte, error) {
|
|
| 153 |
+ var empty [0]byte |
|
| 154 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 155 |
+ b := empty[:] |
|
| 156 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 157 |
+ bx.Data = sx.Data |
|
| 158 |
+ bx.Len = len(data) |
|
| 159 |
+ bx.Cap = bx.Len |
|
| 160 |
+ return b, nil |
|
| 161 |
+} |
|
| 162 |
+ |
|
| 163 |
+`) |
|
| 164 |
+ return err |
|
| 165 |
+} |
|
| 166 |
+ |
|
| 167 |
+func header_uncompressed_memcopy(w io.Writer) error {
|
|
| 168 |
+ _, err := fmt.Fprintf(w, `import ( |
|
| 169 |
+ "fmt" |
|
| 170 |
+ "strings" |
|
| 171 |
+) |
|
| 172 |
+`) |
|
| 173 |
+ return err |
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+func compressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 177 |
+ _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) |
|
| 178 |
+ if err != nil {
|
|
| 179 |
+ return err |
|
| 180 |
+ } |
|
| 181 |
+ |
|
| 182 |
+ gz := gzip.NewWriter(&StringWriter{Writer: w})
|
|
| 183 |
+ _, err = io.Copy(gz, r) |
|
| 184 |
+ gz.Close() |
|
| 185 |
+ |
|
| 186 |
+ if err != nil {
|
|
| 187 |
+ return err |
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 190 |
+ _, err = fmt.Fprintf(w, `" |
|
| 191 |
+ |
|
| 192 |
+func %s() ([]byte, error) {
|
|
| 193 |
+ return bindata_read( |
|
| 194 |
+ _%s, |
|
| 195 |
+ %q, |
|
| 196 |
+ ) |
|
| 197 |
+} |
|
| 198 |
+ |
|
| 199 |
+`, asset.Func, asset.Func, asset.Name) |
|
| 200 |
+ return err |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+func compressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 204 |
+ _, err := fmt.Fprintf(w, `func %s() ([]byte, error) {
|
|
| 205 |
+ return bindata_read([]byte{`, asset.Func)
|
|
| 206 |
+ |
|
| 207 |
+ if err != nil {
|
|
| 208 |
+ return nil |
|
| 209 |
+ } |
|
| 210 |
+ |
|
| 211 |
+ gz := gzip.NewWriter(&ByteWriter{Writer: w})
|
|
| 212 |
+ _, err = io.Copy(gz, r) |
|
| 213 |
+ gz.Close() |
|
| 214 |
+ |
|
| 215 |
+ if err != nil {
|
|
| 216 |
+ return err |
|
| 217 |
+ } |
|
| 218 |
+ |
|
| 219 |
+ _, err = fmt.Fprintf(w, ` |
|
| 220 |
+ }, |
|
| 221 |
+ %q, |
|
| 222 |
+ ) |
|
| 223 |
+} |
|
| 224 |
+ |
|
| 225 |
+`, asset.Name) |
|
| 226 |
+ return err |
|
| 227 |
+} |
|
| 228 |
+ |
|
| 229 |
+func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 230 |
+ _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) |
|
| 231 |
+ if err != nil {
|
|
| 232 |
+ return err |
|
| 233 |
+ } |
|
| 234 |
+ |
|
| 235 |
+ _, err = io.Copy(&StringWriter{Writer: w}, r)
|
|
| 236 |
+ if err != nil {
|
|
| 237 |
+ return err |
|
| 238 |
+ } |
|
| 239 |
+ |
|
| 240 |
+ _, err = fmt.Fprintf(w, `" |
|
| 241 |
+ |
|
| 242 |
+func %s() ([]byte, error) {
|
|
| 243 |
+ return bindata_read( |
|
| 244 |
+ _%s, |
|
| 245 |
+ %q, |
|
| 246 |
+ ) |
|
| 247 |
+} |
|
| 248 |
+ |
|
| 249 |
+`, asset.Func, asset.Func, asset.Name) |
|
| 250 |
+ return err |
|
| 251 |
+} |
|
| 252 |
+ |
|
| 253 |
+func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
|
| 254 |
+ _, err := fmt.Fprintf(w, `func %s() ([]byte, error) {
|
|
| 255 |
+ return []byte{`, asset.Func)
|
|
| 256 |
+ if err != nil {
|
|
| 257 |
+ return err |
|
| 258 |
+ } |
|
| 259 |
+ |
|
| 260 |
+ _, err = io.Copy(&ByteWriter{Writer: w}, r)
|
|
| 261 |
+ if err != nil {
|
|
| 262 |
+ return err |
|
| 263 |
+ } |
|
| 264 |
+ |
|
| 265 |
+ _, err = fmt.Fprintf(w, ` |
|
| 266 |
+ }, nil |
|
| 267 |
+} |
|
| 268 |
+ |
|
| 269 |
+`) |
|
| 270 |
+ return err |
|
| 271 |
+} |
| 0 | 272 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,36 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "io" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+const lowerHex = "0123456789abcdef" |
|
| 11 |
+ |
|
| 12 |
+type StringWriter struct {
|
|
| 13 |
+ io.Writer |
|
| 14 |
+ c int |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+func (w *StringWriter) Write(p []byte) (n int, err error) {
|
|
| 18 |
+ if len(p) == 0 {
|
|
| 19 |
+ return |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ buf := []byte(`\x00`) |
|
| 23 |
+ var b byte |
|
| 24 |
+ |
|
| 25 |
+ for n, b = range p {
|
|
| 26 |
+ buf[2] = lowerHex[b/16] |
|
| 27 |
+ buf[3] = lowerHex[b%16] |
|
| 28 |
+ w.Writer.Write(buf) |
|
| 29 |
+ w.c++ |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ n++ |
|
| 33 |
+ |
|
| 34 |
+ return |
|
| 35 |
+} |
| 0 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,86 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "compress/gzip" |
|
| 5 |
+ "io" |
|
| 6 |
+ "log" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func bindata_read(data []byte, name string) []byte {
|
|
| 10 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(data)) |
|
| 11 |
+ if err != nil {
|
|
| 12 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ var buf bytes.Buffer |
|
| 16 |
+ _, err = io.Copy(&buf, gz) |
|
| 17 |
+ gz.Close() |
|
| 18 |
+ |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ return buf.Bytes() |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func in_b_test_asset() []byte {
|
|
| 27 |
+ return bindata_read([]byte{
|
|
| 28 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 29 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 30 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 31 |
+ 0x00, 0x00, 0x00, |
|
| 32 |
+ }, |
|
| 33 |
+ "in/b/test.asset", |
|
| 34 |
+ ) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func in_test_asset() []byte {
|
|
| 38 |
+ return bindata_read([]byte{
|
|
| 39 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 40 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 41 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 42 |
+ 0x00, 0x00, 0x00, |
|
| 43 |
+ }, |
|
| 44 |
+ "in/test.asset", |
|
| 45 |
+ ) |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+func in_a_test_asset() []byte {
|
|
| 49 |
+ return bindata_read([]byte{
|
|
| 50 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 51 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 52 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 53 |
+ 0x00, 0x00, 0x00, |
|
| 54 |
+ }, |
|
| 55 |
+ "in/a/test.asset", |
|
| 56 |
+ ) |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+func in_c_test_asset() []byte {
|
|
| 60 |
+ return bindata_read([]byte{
|
|
| 61 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd7, |
|
| 62 |
+ 0x57, 0x28, 0x4e, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x48, 0xcb, 0xcc, 0x49, |
|
| 63 |
+ 0xe5, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x82, 0x8c, 0x85, 0x0f, |
|
| 64 |
+ 0x00, 0x00, 0x00, |
|
| 65 |
+ }, |
|
| 66 |
+ "in/c/test.asset", |
|
| 67 |
+ ) |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+// Asset loads and returns the asset for the given name. |
|
| 71 |
+// This returns nil of the asset could not be found. |
|
| 72 |
+func Asset(name string) []byte {
|
|
| 73 |
+ if f, ok := _bindata[name]; ok {
|
|
| 74 |
+ return f() |
|
| 75 |
+ } |
|
| 76 |
+ return nil |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 80 |
+var _bindata = map[string]func() []byte{
|
|
| 81 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 82 |
+ "in/test.asset": in_test_asset, |
|
| 83 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 84 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 85 |
+} |
| 0 | 86 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,88 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "compress/gzip" |
|
| 5 |
+ "io" |
|
| 6 |
+ "log" |
|
| 7 |
+ "reflect" |
|
| 8 |
+ "unsafe" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func bindata_read(data, name string) []byte {
|
|
| 12 |
+ var empty [0]byte |
|
| 13 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 14 |
+ b := empty[:] |
|
| 15 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 16 |
+ bx.Data = sx.Data |
|
| 17 |
+ bx.Len = len(data) |
|
| 18 |
+ bx.Cap = bx.Len |
|
| 19 |
+ |
|
| 20 |
+ gz, err := gzip.NewReader(bytes.NewBuffer(b)) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ var buf bytes.Buffer |
|
| 26 |
+ _, err = io.Copy(&buf, gz) |
|
| 27 |
+ gz.Close() |
|
| 28 |
+ |
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ log.Fatalf("Read %q: %v", name, err)
|
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ return buf.Bytes() |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+var _in_b_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 37 |
+ |
|
| 38 |
+func in_b_test_asset() []byte {
|
|
| 39 |
+ return bindata_read( |
|
| 40 |
+ _in_b_test_asset, |
|
| 41 |
+ "in/b/test.asset", |
|
| 42 |
+ ) |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+var _in_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 46 |
+ |
|
| 47 |
+func in_test_asset() []byte {
|
|
| 48 |
+ return bindata_read( |
|
| 49 |
+ _in_test_asset, |
|
| 50 |
+ "in/test.asset", |
|
| 51 |
+ ) |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+var _in_a_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 55 |
+ |
|
| 56 |
+func in_a_test_asset() []byte {
|
|
| 57 |
+ return bindata_read( |
|
| 58 |
+ _in_a_test_asset, |
|
| 59 |
+ "in/a/test.asset", |
|
| 60 |
+ ) |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+var _in_c_test_asset = "\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd2\xd7\x57\x28\x4e\xcc\x2d\xc8\x49\x55\x48\xcb\xcc\x49\xe5\x02\x04\x00\x00\xff\xff\x8a\x82\x8c\x85\x0f\x00\x00\x00" |
|
| 64 |
+ |
|
| 65 |
+func in_c_test_asset() []byte {
|
|
| 66 |
+ return bindata_read( |
|
| 67 |
+ _in_c_test_asset, |
|
| 68 |
+ "in/c/test.asset", |
|
| 69 |
+ ) |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+// Asset loads and returns the asset for the given name. |
|
| 73 |
+// This returns nil of the asset could not be found. |
|
| 74 |
+func Asset(name string) []byte {
|
|
| 75 |
+ if f, ok := _bindata[name]; ok {
|
|
| 76 |
+ return f() |
|
| 77 |
+ } |
|
| 78 |
+ return nil |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 82 |
+var _bindata = map[string]func() []byte{
|
|
| 83 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 84 |
+ "in/test.asset": in_test_asset, |
|
| 85 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 86 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 87 |
+} |
| 0 | 88 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,80 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "io" |
|
| 5 |
+ "log" |
|
| 6 |
+ "os" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// bindata_read reads the given file from disk. |
|
| 10 |
+// It panics if anything went wrong. |
|
| 11 |
+func bindata_read(path, name string) []byte {
|
|
| 12 |
+ fd, err := os.Open(path) |
|
| 13 |
+ if err != nil {
|
|
| 14 |
+ log.Fatalf("Read %s: %v", name, err)
|
|
| 15 |
+ } |
|
| 16 |
+ |
|
| 17 |
+ defer fd.Close() |
|
| 18 |
+ |
|
| 19 |
+ var buf bytes.Buffer |
|
| 20 |
+ _, err = io.Copy(&buf, fd) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ log.Fatalf("Read %s: %v", name, err)
|
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ return buf.Bytes() |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+// in_b_test_asset reads file data from disk. |
|
| 29 |
+// It panics if something went wrong in the process. |
|
| 30 |
+func in_b_test_asset() []byte {
|
|
| 31 |
+ return bindata_read( |
|
| 32 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/b/test.asset", |
|
| 33 |
+ "in/b/test.asset", |
|
| 34 |
+ ) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+// in_test_asset reads file data from disk. |
|
| 38 |
+// It panics if something went wrong in the process. |
|
| 39 |
+func in_test_asset() []byte {
|
|
| 40 |
+ return bindata_read( |
|
| 41 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/test.asset", |
|
| 42 |
+ "in/test.asset", |
|
| 43 |
+ ) |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+// in_a_test_asset reads file data from disk. |
|
| 47 |
+// It panics if something went wrong in the process. |
|
| 48 |
+func in_a_test_asset() []byte {
|
|
| 49 |
+ return bindata_read( |
|
| 50 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/a/test.asset", |
|
| 51 |
+ "in/a/test.asset", |
|
| 52 |
+ ) |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// in_c_test_asset reads file data from disk. |
|
| 56 |
+// It panics if something went wrong in the process. |
|
| 57 |
+func in_c_test_asset() []byte {
|
|
| 58 |
+ return bindata_read( |
|
| 59 |
+ "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/c/test.asset", |
|
| 60 |
+ "in/c/test.asset", |
|
| 61 |
+ ) |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+// Asset loads and returns the asset for the given name. |
|
| 65 |
+// This returns nil of the asset could not be found. |
|
| 66 |
+func Asset(name string) []byte {
|
|
| 67 |
+ if f, ok := _bindata[name]; ok {
|
|
| 68 |
+ return f() |
|
| 69 |
+ } |
|
| 70 |
+ return nil |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 74 |
+var _bindata = map[string]func() []byte{
|
|
| 75 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 76 |
+ "in/test.asset": in_test_asset, |
|
| 77 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 78 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 79 |
+} |
| 0 | 80 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+func in_b_test_asset() []byte {
|
|
| 3 |
+ return []byte{
|
|
| 4 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 5 |
+ 0x6c, 0x65, 0x0a, |
|
| 6 |
+ } |
|
| 7 |
+} |
|
| 8 |
+ |
|
| 9 |
+func in_test_asset() []byte {
|
|
| 10 |
+ return []byte{
|
|
| 11 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 12 |
+ 0x6c, 0x65, 0x0a, |
|
| 13 |
+ } |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+func in_a_test_asset() []byte {
|
|
| 17 |
+ return []byte{
|
|
| 18 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 19 |
+ 0x6c, 0x65, 0x0a, |
|
| 20 |
+ } |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func in_c_test_asset() []byte {
|
|
| 24 |
+ return []byte{
|
|
| 25 |
+ 0x2f, 0x2f, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, |
|
| 26 |
+ 0x6c, 0x65, 0x0a, |
|
| 27 |
+ } |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+// Asset loads and returns the asset for the given name. |
|
| 31 |
+// This returns nil of the asset could not be found. |
|
| 32 |
+func Asset(name string) []byte {
|
|
| 33 |
+ if f, ok := _bindata[name]; ok {
|
|
| 34 |
+ return f() |
|
| 35 |
+ } |
|
| 36 |
+ return nil |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 40 |
+var _bindata = map[string]func() []byte{
|
|
| 41 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 42 |
+ "in/test.asset": in_test_asset, |
|
| 43 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 44 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 45 |
+} |
| 0 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,70 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "reflect" |
|
| 4 |
+ "unsafe" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func bindata_read(data, name string) []byte {
|
|
| 8 |
+ var empty [0]byte |
|
| 9 |
+ sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) |
|
| 10 |
+ b := empty[:] |
|
| 11 |
+ bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) |
|
| 12 |
+ bx.Data = sx.Data |
|
| 13 |
+ bx.Len = len(data) |
|
| 14 |
+ bx.Cap = bx.Len |
|
| 15 |
+ return b |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+var _in_b_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 19 |
+ |
|
| 20 |
+func in_b_test_asset() []byte {
|
|
| 21 |
+ return bindata_read( |
|
| 22 |
+ _in_b_test_asset, |
|
| 23 |
+ "in/b/test.asset", |
|
| 24 |
+ ) |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+var _in_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 28 |
+ |
|
| 29 |
+func in_test_asset() []byte {
|
|
| 30 |
+ return bindata_read( |
|
| 31 |
+ _in_test_asset, |
|
| 32 |
+ "in/test.asset", |
|
| 33 |
+ ) |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+var _in_a_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 37 |
+ |
|
| 38 |
+func in_a_test_asset() []byte {
|
|
| 39 |
+ return bindata_read( |
|
| 40 |
+ _in_a_test_asset, |
|
| 41 |
+ "in/a/test.asset", |
|
| 42 |
+ ) |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+var _in_c_test_asset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" |
|
| 46 |
+ |
|
| 47 |
+func in_c_test_asset() []byte {
|
|
| 48 |
+ return bindata_read( |
|
| 49 |
+ _in_c_test_asset, |
|
| 50 |
+ "in/c/test.asset", |
|
| 51 |
+ ) |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// Asset loads and returns the asset for the given name. |
|
| 55 |
+// This returns nil of the asset could not be found. |
|
| 56 |
+func Asset(name string) []byte {
|
|
| 57 |
+ if f, ok := _bindata[name]; ok {
|
|
| 58 |
+ return f() |
|
| 59 |
+ } |
|
| 60 |
+ return nil |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 64 |
+var _bindata = map[string]func() []byte{
|
|
| 65 |
+ "in/b/test.asset": in_b_test_asset, |
|
| 66 |
+ "in/test.asset": in_test_asset, |
|
| 67 |
+ "in/a/test.asset": in_a_test_asset, |
|
| 68 |
+ "in/c/test.asset": in_c_test_asset, |
|
| 69 |
+} |
| 0 | 70 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,184 @@ |
| 0 |
+// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication |
|
| 1 |
+// license. Its contents can be found at: |
|
| 2 |
+// http://creativecommons.org/publicdomain/zero/1.0/ |
|
| 3 |
+ |
|
| 4 |
+package bindata |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "fmt" |
|
| 8 |
+ "io" |
|
| 9 |
+ "os" |
|
| 10 |
+ "strings" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+type assetTree struct {
|
|
| 14 |
+ Asset Asset |
|
| 15 |
+ Children map[string]*assetTree |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+func newAssetTree() *assetTree {
|
|
| 19 |
+ tree := &assetTree{}
|
|
| 20 |
+ tree.Children = make(map[string]*assetTree) |
|
| 21 |
+ return tree |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func (node *assetTree) child(name string) *assetTree {
|
|
| 25 |
+ rv, ok := node.Children[name] |
|
| 26 |
+ if !ok {
|
|
| 27 |
+ rv = newAssetTree() |
|
| 28 |
+ node.Children[name] = rv |
|
| 29 |
+ } |
|
| 30 |
+ return rv |
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+func (root *assetTree) Add(route []string, asset Asset) {
|
|
| 34 |
+ for _, name := range route {
|
|
| 35 |
+ root = root.child(name) |
|
| 36 |
+ } |
|
| 37 |
+ root.Asset = asset |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+func ident(w io.Writer, n int) {
|
|
| 41 |
+ for i := 0; i < n; i++ {
|
|
| 42 |
+ w.Write([]byte{'\t'})
|
|
| 43 |
+ } |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func (root *assetTree) funcOrNil() string {
|
|
| 47 |
+ if root.Asset.Func == "" {
|
|
| 48 |
+ return "nil" |
|
| 49 |
+ } else {
|
|
| 50 |
+ return root.Asset.Func |
|
| 51 |
+ } |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+func (root *assetTree) writeGoMap(w io.Writer, nident int) {
|
|
| 55 |
+ fmt.Fprintf(w, "&_bintree_t{%s, map[string]*_bintree_t{\n", root.funcOrNil())
|
|
| 56 |
+ for p, child := range root.Children {
|
|
| 57 |
+ ident(w, nident+1) |
|
| 58 |
+ fmt.Fprintf(w, `"%s": `, p) |
|
| 59 |
+ child.writeGoMap(w, nident+1) |
|
| 60 |
+ } |
|
| 61 |
+ ident(w, nident) |
|
| 62 |
+ io.WriteString(w, "}}") |
|
| 63 |
+ if nident > 0 {
|
|
| 64 |
+ io.WriteString(w, ",") |
|
| 65 |
+ } |
|
| 66 |
+ io.WriteString(w, "\n") |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+func (root *assetTree) WriteAsGoMap(w io.Writer) error {
|
|
| 70 |
+ _, err := fmt.Fprint(w, `type _bintree_t struct {
|
|
| 71 |
+ Func func() ([]byte, error) |
|
| 72 |
+ Children map[string]*_bintree_t |
|
| 73 |
+} |
|
| 74 |
+var _bintree = `) |
|
| 75 |
+ root.writeGoMap(w, 0) |
|
| 76 |
+ return err |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func writeTOCTree(w io.Writer, toc []Asset) error {
|
|
| 80 |
+ _, err := fmt.Fprintf(w, `// AssetDir returns the file names below a certain |
|
| 81 |
+// directory embedded in the file by go-bindata. |
|
| 82 |
+// For example if you run go-bindata on data/... and data contains the |
|
| 83 |
+// following hierarchy: |
|
| 84 |
+// data/ |
|
| 85 |
+// foo.txt |
|
| 86 |
+// img/ |
|
| 87 |
+// a.png |
|
| 88 |
+// b.png |
|
| 89 |
+// then AssetDir("data") would return []string{"foo.txt", "img"}
|
|
| 90 |
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
|
| 91 |
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
|
| 92 |
+// AssetDir("") will return []string{"data"}.
|
|
| 93 |
+func AssetDir(name string) ([]string, error) {
|
|
| 94 |
+ node := _bintree |
|
| 95 |
+ if len(name) != 0 {
|
|
| 96 |
+ cannonicalName := strings.Replace(name, "\\", "/", -1) |
|
| 97 |
+ pathList := strings.Split(cannonicalName, "/") |
|
| 98 |
+ for _, p := range pathList {
|
|
| 99 |
+ node = node.Children[p] |
|
| 100 |
+ if node == nil {
|
|
| 101 |
+ return nil, fmt.Errorf("Asset %%s not found", name)
|
|
| 102 |
+ } |
|
| 103 |
+ } |
|
| 104 |
+ } |
|
| 105 |
+ if node.Func != nil {
|
|
| 106 |
+ return nil, fmt.Errorf("Asset %%s not found", name)
|
|
| 107 |
+ } |
|
| 108 |
+ rv := make([]string, 0, len(node.Children)) |
|
| 109 |
+ for name := range node.Children {
|
|
| 110 |
+ rv = append(rv, name) |
|
| 111 |
+ } |
|
| 112 |
+ return rv, nil |
|
| 113 |
+} |
|
| 114 |
+ |
|
| 115 |
+`) |
|
| 116 |
+ if err != nil {
|
|
| 117 |
+ return err |
|
| 118 |
+ } |
|
| 119 |
+ tree := newAssetTree() |
|
| 120 |
+ for i := range toc {
|
|
| 121 |
+ pathList := strings.Split(toc[i].Name, string(os.PathSeparator)) |
|
| 122 |
+ tree.Add(pathList, toc[i]) |
|
| 123 |
+ } |
|
| 124 |
+ return tree.WriteAsGoMap(w) |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+// writeTOC writes the table of contents file. |
|
| 128 |
+func writeTOC(w io.Writer, toc []Asset) error {
|
|
| 129 |
+ err := writeTOCHeader(w) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ return err |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ for i := range toc {
|
|
| 135 |
+ err = writeTOCAsset(w, &toc[i]) |
|
| 136 |
+ if err != nil {
|
|
| 137 |
+ return err |
|
| 138 |
+ } |
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ return writeTOCFooter(w) |
|
| 142 |
+} |
|
| 143 |
+ |
|
| 144 |
+// writeTOCHeader writes the table of contents file header. |
|
| 145 |
+func writeTOCHeader(w io.Writer) error {
|
|
| 146 |
+ _, err := fmt.Fprintf(w, `// Asset loads and returns the asset for the given name. |
|
| 147 |
+// It returns an error if the asset could not be found or |
|
| 148 |
+// could not be loaded. |
|
| 149 |
+func Asset(name string) ([]byte, error) {
|
|
| 150 |
+ cannonicalName := strings.Replace(name, "\\", "/", -1) |
|
| 151 |
+ if f, ok := _bindata[cannonicalName]; ok {
|
|
| 152 |
+ return f() |
|
| 153 |
+ } |
|
| 154 |
+ return nil, fmt.Errorf("Asset %%s not found", name)
|
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+// AssetNames returns the names of the assets. |
|
| 158 |
+func AssetNames() []string {
|
|
| 159 |
+ names := make([]string, 0, len(_bindata)) |
|
| 160 |
+ for name := range _bindata {
|
|
| 161 |
+ names = append(names, name) |
|
| 162 |
+ } |
|
| 163 |
+ return names |
|
| 164 |
+} |
|
| 165 |
+ |
|
| 166 |
+// _bindata is a table, holding each asset generator, mapped to its name. |
|
| 167 |
+var _bindata = map[string]func() ([]byte, error){
|
|
| 168 |
+`) |
|
| 169 |
+ return err |
|
| 170 |
+} |
|
| 171 |
+ |
|
| 172 |
+// writeTOCAsset write a TOC entry for the given asset. |
|
| 173 |
+func writeTOCAsset(w io.Writer, asset *Asset) error {
|
|
| 174 |
+ _, err := fmt.Fprintf(w, "\t%q: %s,\n", asset.Name, asset.Func) |
|
| 175 |
+ return err |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+// writeTOCFooter writes the table of contents file footer. |
|
| 179 |
+func writeTOCFooter(w io.Writer) error {
|
|
| 180 |
+ _, err := fmt.Fprintf(w, `} |
|
| 181 |
+`) |
|
| 182 |
+ return err |
|
| 183 |
+} |