├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── asset.go ├── bytewriter.go ├── config.go ├── convert.go ├── convert_test.go ├── debug.go ├── doc.go ├── go-bindata ├── AppendSliceValue.go ├── main.go └── version.go ├── release.go ├── restore.go ├── stringwriter.go ├── testdata ├── Makefile ├── dupname │ ├── foo │ │ └── bar │ └── foo_bar ├── in │ ├── a │ │ └── test.asset │ ├── b │ │ └── test.asset │ ├── c │ │ └── test.asset │ └── test.asset ├── out │ ├── compress-memcopy.go │ ├── compress-nomemcopy.go │ ├── debug.go │ ├── debug.go-bindata │ ├── nocompress-memcopy.go │ └── nocompress-nomemcopy.go ├── symlinkFile │ └── file1 ├── symlinkParent │ └── symlinkTarget ├── symlinkRecursiveParent │ ├── file1 │ └── symlinkTarget └── symlinkSrc │ ├── file1 │ ├── file2 │ ├── file3 │ └── file4 └── toc.go /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contribution guidelines. 2 | 3 | So you wish to contribute to this project? Fantastic! 4 | Here are a few guidelines to help you do this in a 5 | streamlined fashion. 6 | 7 | 8 | ## Bug reports 9 | 10 | When supplying a bug report, please consider the following guidelines. 11 | These serve to make it easier for us to address the issue and find a solution. 12 | Most of these are pretty self-evident, but sometimes it is still necessary 13 | to reiterate them. 14 | 15 | * Be clear in the way you express the problem. Use simple language and 16 | just enough of it to clearly define the issue. Not everyone is a native 17 | English speaker. And while most can handle themselves pretty well, 18 | it helps to stay away from more esoteric vocabulary. 19 | 20 | Be patient with non-native English speakers. If their bug reports 21 | or comments are hard to understand, just ask for clarification. 22 | Do not start guessing at their meaning, as this may just lead to 23 | more confusion and misunderstandings. 24 | * Clearly define any information which is relevant to the problem. 25 | This includes library versions, operating system and any other 26 | external dependencies which may be needed. 27 | * Where applicable, provide a step-by-step listing of the way to 28 | reproduce the problem. Make sure this is the simplest possible 29 | way to do so. Omit any and all unneccesary steps, because they may 30 | just complicate our understanding of the real problem. 31 | If need be, create a whole new code project on your local machine, 32 | which specifically tries to create the problem you are running into; 33 | nothing more, nothing less. 34 | 35 | Include this program in the bug report. It often suffices to paste 36 | the code in a [Gist](https://gist.github.com) or on the 37 | [Go playground](http://play.golang.org). 38 | * If possible, provide us with a listing of the steps you have already 39 | undertaken to solve the problem. This can save us a great deal of 40 | wasted time, trying out solutions you have already covered. 41 | 42 | 43 | ## Pull requests 44 | 45 | Bug reports are great. Supplying fixes to bugs is even better. 46 | When submitting a pull request, the following guidelines are 47 | good to keep in mind: 48 | 49 | * `go fmt`: **Always** run your code through `go fmt`, before 50 | committing it. Code has to be readable by many different 51 | people. And the only way this will be as painless as possible, 52 | is if we all stick to the same code style. 53 | 54 | Some of our projects may have automated build-servers hooked up 55 | to commit hooks. These will vet any submitted code and determine 56 | if it meets a set of properties. One of which is code formatting. 57 | These servers will outright deny a submission which has not been 58 | run through `go fmt`, even if the code itself is correct. 59 | 60 | We try to maintain a zero-tolerance policy on this matter, 61 | because consistently formatted code makes life a great deal 62 | easier for everyone involved. 63 | * Commit log messages: When committing changes, do so often and 64 | clearly -- Even if you have changed only 1 character in a code 65 | comment. This means that commit log messages should clearly state 66 | exactly what the change does and why. If it fixes a known issue, 67 | then mention the issue number in the commit log. E.g.: 68 | 69 | > Fixes return value for `foo/boo.Baz()` to be consistent with 70 | > the rest of the API. This addresses issue #32 71 | 72 | Do not pile a lot of unrelated changes into a single commit. 73 | Pick and choose only those changes for a single commit, which are 74 | directly related. We would much rather see a hundred commits 75 | saying nothing but `"Runs go fmt"` in between any real fixes 76 | than have these style changes embedded in those real fixes. 77 | It creates a lot of noise when trying to review code. 78 | 79 | 80 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | license. Its contents can be found at: 3 | http://creativecommons.org/publicdomain/zero/1.0 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | make -C testdata 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Warning 2 | 3 | **this repository is not maintained. Questions or suggestions can be posted [here](https://github.com/jteeuwen/discussions/issues).** 4 | 5 | ## bindata 6 | 7 | This package converts any file into managable Go source code. Useful for 8 | embedding binary data into a go program. The file data is optionally gzip 9 | compressed before being converted to a raw byte slice. 10 | 11 | It comes with a command line tool in the `go-bindata` sub directory. 12 | This tool offers a set of command line options, used to customize the 13 | output being generated. 14 | 15 | 16 | ### Installation 17 | 18 | To install the library and command line program, use the following: 19 | 20 | go get -u github.com/jteeuwen/go-bindata/... 21 | 22 | 23 | ### Usage 24 | 25 | Conversion is done on one or more sets of files. They are all embedded in a new 26 | Go source file, along with a table of contents and an `Asset` function, 27 | which allows quick access to the asset, based on its name. 28 | 29 | The simplest invocation generates a `bindata.go` file in the current 30 | working directory. It includes all assets from the `data` directory. 31 | 32 | $ go-bindata data/ 33 | 34 | To include all input sub-directories recursively, use the elipsis postfix 35 | as defined for Go import paths. Otherwise it will only consider assets in the 36 | input directory itself. 37 | 38 | $ go-bindata data/... 39 | 40 | To specify the name of the output file being generated, we use the following: 41 | 42 | $ go-bindata -o myfile.go data/ 43 | 44 | Multiple input directories can be specified if necessary. 45 | 46 | $ go-bindata dir1/... /path/to/dir2/... dir3 47 | 48 | 49 | The following paragraphs detail some of the command line options which can be 50 | supplied to `go-bindata`. Refer to the `testdata/out` directory for various 51 | output examples from the assets in `testdata/in`. Each example uses different 52 | command line options. 53 | 54 | To ignore files, pass in regexes using -ignore, for example: 55 | 56 | $ go-bindata -ignore=\\.gitignore data/... 57 | 58 | ### Accessing an asset 59 | 60 | To access asset data, we use the `Asset(string) ([]byte, error)` function which 61 | is included in the generated output. 62 | 63 | data, err := Asset("pub/style/foo.css") 64 | if err != nil { 65 | // Asset was not found. 66 | } 67 | 68 | // use asset data 69 | 70 | 71 | ### Debug vs Release builds 72 | 73 | When invoking the program with the `-debug` flag, the generated code does 74 | not actually include the asset data. Instead, it generates function stubs 75 | which load the data from the original file on disk. The asset API remains 76 | identical between debug and release builds, so your code will not have to 77 | change. 78 | 79 | This is useful during development when you expect the assets to change often. 80 | The host application using these assets uses the same API in both cases and 81 | will not have to care where the actual data comes from. 82 | 83 | An example is a Go webserver with some embedded, static web content like 84 | HTML, JS and CSS files. While developing it, you do not want to rebuild the 85 | whole server and restart it every time you make a change to a bit of 86 | javascript. You just want to build and launch the server once. Then just press 87 | refresh in the browser to see those changes. Embedding the assets with the 88 | `debug` flag allows you to do just that. When you are finished developing and 89 | ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. 90 | It will now embed the latest version of the assets. 91 | 92 | 93 | ### Lower memory footprint 94 | 95 | Using the `-nomemcopy` flag, will alter the way the output file is generated. 96 | It will employ a hack that allows us to read the file data directly from 97 | the compiled program's `.rodata` section. This ensures that when we call 98 | call our generated function, we omit unnecessary memcopies. 99 | 100 | The downside of this, is that it requires dependencies on the `reflect` and 101 | `unsafe` packages. These may be restricted on platforms like AppEngine and 102 | thus prevent you from using this mode. 103 | 104 | Another disadvantage is that the byte slice we create, is strictly read-only. 105 | For most use-cases this is not a problem, but if you ever try to alter the 106 | returned byte slice, a runtime panic is thrown. Use this mode only on target 107 | platforms where memory constraints are an issue. 108 | 109 | The default behaviour is to use the old code generation method. This 110 | prevents the two previously mentioned issues, but will employ at least one 111 | extra memcopy and thus increase memory requirements. 112 | 113 | For instance, consider the following two examples: 114 | 115 | This would be the default mode, using an extra memcopy but gives a safe 116 | implementation without dependencies on `reflect` and `unsafe`: 117 | 118 | ```go 119 | func myfile() []byte { 120 | return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a} 121 | } 122 | ``` 123 | 124 | Here is the same functionality, but uses the `.rodata` hack. 125 | The byte slice returned from this example can not be written to without 126 | generating a runtime error. 127 | 128 | ```go 129 | var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" 130 | 131 | func myfile() []byte { 132 | var empty [0]byte 133 | sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) 134 | b := empty[:] 135 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 136 | bx.Data = sx.Data 137 | bx.Len = len(_myfile) 138 | bx.Cap = bx.Len 139 | return b 140 | } 141 | ``` 142 | 143 | 144 | ### Optional compression 145 | 146 | When the `-nocompress` flag is given, the supplied resource is *not* GZIP 147 | compressed before being turned into Go code. The data should still be accessed 148 | through a function call, so nothing changes in the usage of the generated file. 149 | 150 | This feature is useful if you do not care for compression, or the supplied 151 | resource is already compressed. Doing it again would not add any value and may 152 | even increase the size of the data. 153 | 154 | The default behaviour of the program is to use compression. 155 | 156 | 157 | ### Path prefix stripping 158 | 159 | The keys used in the `_bindata` map, are the same as the input file name 160 | passed to `go-bindata`. This includes the path. In most cases, this is not 161 | desireable, as it puts potentially sensitive information in your code base. 162 | For this purpose, the tool supplies another command line flag `-prefix`. 163 | This accepts a portion of a path name, which should be stripped off from 164 | the map keys and function names. 165 | 166 | For example, running without the `-prefix` flag, we get: 167 | 168 | $ go-bindata /path/to/templates/ 169 | 170 | _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html 171 | 172 | Running with the `-prefix` flag, we get: 173 | 174 | $ go-bindata -prefix "/path/to/" /path/to/templates/ 175 | 176 | _bindata["templates/foo.html"] = templates_foo_html 177 | 178 | 179 | ### Build tags 180 | 181 | With the optional `-tags` flag, you can specify any go build tags that 182 | must be fulfilled for the output file to be included in a build. This 183 | is useful when including binary data in multiple formats, where the desired 184 | format is specified at build time with the appropriate tags. 185 | 186 | The tags are appended to a `// +build` line in the beginning of the output file 187 | and must follow the build tags syntax specified by the go tool. 188 | 189 | ### Related projects 190 | 191 | [go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) - 192 | implements `http.FileSystem` interface. Allows you to serve assets with `net/http`. 193 | 194 | -------------------------------------------------------------------------------- /asset.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | // Asset holds information about a single asset to be processed. 8 | type Asset struct { 9 | Path string // Full file path. 10 | Name string // Key used in TOC -- name by which asset is referenced. 11 | Func string // Function name for the procedure returning the asset contents. 12 | } 13 | -------------------------------------------------------------------------------- /bytewriter.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | ) 11 | 12 | var ( 13 | newline = []byte{'\n'} 14 | dataindent = []byte{'\t', '\t'} 15 | space = []byte{' '} 16 | ) 17 | 18 | type ByteWriter struct { 19 | io.Writer 20 | c int 21 | } 22 | 23 | func (w *ByteWriter) Write(p []byte) (n int, err error) { 24 | if len(p) == 0 { 25 | return 26 | } 27 | 28 | for n = range p { 29 | if w.c%12 == 0 { 30 | w.Writer.Write(newline) 31 | w.Writer.Write(dataindent) 32 | w.c = 0 33 | } else { 34 | w.Writer.Write(space) 35 | } 36 | 37 | fmt.Fprintf(w.Writer, "0x%02x,", p[n]) 38 | w.c++ 39 | } 40 | 41 | n++ 42 | 43 | return 44 | } 45 | -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "path/filepath" 11 | "regexp" 12 | ) 13 | 14 | // InputConfig defines options on a asset directory to be convert. 15 | type InputConfig struct { 16 | // Path defines a directory containing asset files to be included 17 | // in the generated output. 18 | Path string 19 | 20 | // Recusive defines whether subdirectories of Path 21 | // should be recursively included in the conversion. 22 | Recursive bool 23 | } 24 | 25 | // Config defines a set of options for the asset conversion. 26 | type Config struct { 27 | // Name of the package to use. Defaults to 'main'. 28 | Package string 29 | 30 | // Tags specify a set of optional build tags, which should be 31 | // included in the generated output. The tags are appended to a 32 | // `// +build` line in the beginning of the output file 33 | // and must follow the build tags syntax specified by the go tool. 34 | Tags string 35 | 36 | // Input defines the directory path, containing all asset files as 37 | // well as whether to recursively process assets in any sub directories. 38 | Input []InputConfig 39 | 40 | // Output defines the output file for the generated code. 41 | // If left empty, this defaults to 'bindata.go' in the current 42 | // working directory. 43 | Output string 44 | 45 | // Prefix defines a path prefix which should be stripped from all 46 | // file names when generating the keys in the table of contents. 47 | // For example, running without the `-prefix` flag, we get: 48 | // 49 | // $ go-bindata /path/to/templates 50 | // go_bindata["/path/to/templates/foo.html"] = _path_to_templates_foo_html 51 | // 52 | // Running with the `-prefix` flag, we get: 53 | // 54 | // $ go-bindata -prefix "/path/to/" /path/to/templates/foo.html 55 | // go_bindata["templates/foo.html"] = templates_foo_html 56 | Prefix string 57 | 58 | // NoMemCopy will alter the way the output file is generated. 59 | // 60 | // It will employ a hack that allows us to read the file data directly from 61 | // the compiled program's `.rodata` section. This ensures that when we call 62 | // call our generated function, we omit unnecessary mem copies. 63 | // 64 | // The downside of this, is that it requires dependencies on the `reflect` and 65 | // `unsafe` packages. These may be restricted on platforms like AppEngine and 66 | // thus prevent you from using this mode. 67 | // 68 | // Another disadvantage is that the byte slice we create, is strictly read-only. 69 | // For most use-cases this is not a problem, but if you ever try to alter the 70 | // returned byte slice, a runtime panic is thrown. Use this mode only on target 71 | // platforms where memory constraints are an issue. 72 | // 73 | // The default behaviour is to use the old code generation method. This 74 | // prevents the two previously mentioned issues, but will employ at least one 75 | // extra memcopy and thus increase memory requirements. 76 | // 77 | // For instance, consider the following two examples: 78 | // 79 | // This would be the default mode, using an extra memcopy but gives a safe 80 | // implementation without dependencies on `reflect` and `unsafe`: 81 | // 82 | // func myfile() []byte { 83 | // return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a} 84 | // } 85 | // 86 | // Here is the same functionality, but uses the `.rodata` hack. 87 | // The byte slice returned from this example can not be written to without 88 | // generating a runtime error. 89 | // 90 | // var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" 91 | // 92 | // func myfile() []byte { 93 | // var empty [0]byte 94 | // sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) 95 | // b := empty[:] 96 | // bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 97 | // bx.Data = sx.Data 98 | // bx.Len = len(_myfile) 99 | // bx.Cap = bx.Len 100 | // return b 101 | // } 102 | NoMemCopy bool 103 | 104 | // NoCompress means the assets are /not/ GZIP compressed before being turned 105 | // into Go code. The generated function will automatically unzip 106 | // the file data when called. Defaults to false. 107 | NoCompress bool 108 | 109 | // Perform a debug build. This generates an asset file, which 110 | // loads the asset contents directly from disk at their original 111 | // location, instead of embedding the contents in the code. 112 | // 113 | // This is mostly useful if you anticipate that the assets are 114 | // going to change during your development cycle. You will always 115 | // want your code to access the latest version of the asset. 116 | // Only in release mode, will the assets actually be embedded 117 | // in the code. The default behaviour is Release mode. 118 | Debug bool 119 | 120 | // Perform a dev build, which is nearly identical to the debug option. The 121 | // only difference is that instead of absolute file paths in generated code, 122 | // it expects a variable, `rootDir`, to be set in the generated code's 123 | // package (the author needs to do this manually), which it then prepends to 124 | // an asset's name to construct the file path on disk. 125 | // 126 | // This is mainly so you can push the generated code file to a shared 127 | // repository. 128 | Dev bool 129 | 130 | // When true, size, mode and modtime are not preserved from files 131 | NoMetadata bool 132 | // When nonzero, use this as mode for all files. 133 | Mode uint 134 | // When nonzero, use this as unix timestamp for all files. 135 | ModTime int64 136 | 137 | // Ignores any filenames matching the regex pattern specified, e.g. 138 | // path/to/file.ext will ignore only that file, or \\.gitignore 139 | // will match any .gitignore file. 140 | // 141 | // This parameter can be provided multiple times. 142 | Ignore []*regexp.Regexp 143 | } 144 | 145 | // NewConfig returns a default configuration struct. 146 | func NewConfig() *Config { 147 | c := new(Config) 148 | c.Package = "main" 149 | c.NoMemCopy = false 150 | c.NoCompress = false 151 | c.Debug = false 152 | c.Output = "./bindata.go" 153 | c.Ignore = make([]*regexp.Regexp, 0) 154 | return c 155 | } 156 | 157 | // validate ensures the config has sane values. 158 | // Part of which means checking if certain file/directory paths exist. 159 | func (c *Config) validate() error { 160 | if len(c.Package) == 0 { 161 | return fmt.Errorf("Missing package name") 162 | } 163 | 164 | for _, input := range c.Input { 165 | _, err := os.Lstat(input.Path) 166 | if err != nil { 167 | return fmt.Errorf("Failed to stat input path '%s': %v", input.Path, err) 168 | } 169 | } 170 | 171 | if len(c.Output) == 0 { 172 | cwd, err := os.Getwd() 173 | if err != nil { 174 | return fmt.Errorf("Unable to determine current working directory.") 175 | } 176 | 177 | c.Output = filepath.Join(cwd, "bindata.go") 178 | } 179 | 180 | stat, err := os.Lstat(c.Output) 181 | if err != nil { 182 | if !os.IsNotExist(err) { 183 | return fmt.Errorf("Output path: %v", err) 184 | } 185 | 186 | // File does not exist. This is fine, just make 187 | // sure the directory it is to be in exists. 188 | dir, _ := filepath.Split(c.Output) 189 | if dir != "" { 190 | err = os.MkdirAll(dir, 0744) 191 | 192 | if err != nil { 193 | return fmt.Errorf("Create output directory: %v", err) 194 | } 195 | } 196 | } 197 | 198 | if stat != nil && stat.IsDir() { 199 | return fmt.Errorf("Output path is a directory.") 200 | } 201 | 202 | return nil 203 | } 204 | -------------------------------------------------------------------------------- /convert.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "os" 11 | "path/filepath" 12 | "regexp" 13 | "sort" 14 | "strings" 15 | "unicode" 16 | ) 17 | 18 | // Translate reads assets from an input directory, converts them 19 | // to Go code and writes new files to the output specified 20 | // in the given configuration. 21 | func Translate(c *Config) error { 22 | var toc []Asset 23 | 24 | // Ensure our configuration has sane values. 25 | err := c.validate() 26 | if err != nil { 27 | return err 28 | } 29 | 30 | var knownFuncs = make(map[string]int) 31 | var visitedPaths = make(map[string]bool) 32 | // Locate all the assets. 33 | for _, input := range c.Input { 34 | err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore, knownFuncs, visitedPaths) 35 | if err != nil { 36 | return err 37 | } 38 | } 39 | 40 | // Create output file. 41 | fd, err := os.Create(c.Output) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | defer fd.Close() 47 | 48 | // Create a buffered writer for better performance. 49 | bfd := bufio.NewWriter(fd) 50 | defer bfd.Flush() 51 | 52 | // Write the header. This makes e.g. Github ignore diffs in generated files. 53 | if _, err = fmt.Fprint(bfd, "// Code generated by go-bindata.\n"); err != nil { 54 | return err 55 | } 56 | if _, err = fmt.Fprint(bfd, "// sources:\n"); err != nil { 57 | return err 58 | } 59 | 60 | wd, err := os.Getwd() 61 | if err != nil { 62 | return err 63 | } 64 | 65 | for _, asset := range toc { 66 | relative, _ := filepath.Rel(wd, asset.Path) 67 | if _, err = fmt.Fprintf(bfd, "// %s\n", filepath.ToSlash(relative)); err != nil { 68 | return err 69 | } 70 | } 71 | if _, err = fmt.Fprint(bfd, "// DO NOT EDIT!\n\n"); err != nil { 72 | return err 73 | } 74 | 75 | // Write build tags, if applicable. 76 | if len(c.Tags) > 0 { 77 | if _, err = fmt.Fprintf(bfd, "// +build %s\n\n", c.Tags); err != nil { 78 | return err 79 | } 80 | } 81 | 82 | // Write package declaration. 83 | _, err = fmt.Fprintf(bfd, "package %s\n\n", c.Package) 84 | if err != nil { 85 | return err 86 | } 87 | 88 | // Write assets. 89 | if c.Debug || c.Dev { 90 | err = writeDebug(bfd, c, toc) 91 | } else { 92 | err = writeRelease(bfd, c, toc) 93 | } 94 | 95 | if err != nil { 96 | return err 97 | } 98 | 99 | // Write table of contents 100 | if err := writeTOC(bfd, toc); err != nil { 101 | return err 102 | } 103 | // Write hierarchical tree of assets 104 | if err := writeTOCTree(bfd, toc); err != nil { 105 | return err 106 | } 107 | 108 | // Write restore procedure 109 | return writeRestore(bfd) 110 | } 111 | 112 | // Implement sort.Interface for []os.FileInfo based on Name() 113 | type ByName []os.FileInfo 114 | 115 | func (v ByName) Len() int { return len(v) } 116 | func (v ByName) Swap(i, j int) { v[i], v[j] = v[j], v[i] } 117 | func (v ByName) Less(i, j int) bool { return v[i].Name() < v[j].Name() } 118 | 119 | // findFiles recursively finds all the file paths in the given directory tree. 120 | // They are added to the given map as keys. Values will be safe function names 121 | // for each file, which will be used when generating the output code. 122 | func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp, knownFuncs map[string]int, visitedPaths map[string]bool) error { 123 | dirpath := dir 124 | if len(prefix) > 0 { 125 | dirpath, _ = filepath.Abs(dirpath) 126 | prefix, _ = filepath.Abs(prefix) 127 | prefix = filepath.ToSlash(prefix) 128 | } 129 | 130 | fi, err := os.Stat(dirpath) 131 | if err != nil { 132 | return err 133 | } 134 | 135 | var list []os.FileInfo 136 | 137 | if !fi.IsDir() { 138 | dirpath = filepath.Dir(dirpath) 139 | list = []os.FileInfo{fi} 140 | } else { 141 | visitedPaths[dirpath] = true 142 | fd, err := os.Open(dirpath) 143 | if err != nil { 144 | return err 145 | } 146 | 147 | defer fd.Close() 148 | 149 | list, err = fd.Readdir(0) 150 | if err != nil { 151 | return err 152 | } 153 | 154 | // Sort to make output stable between invocations 155 | sort.Sort(ByName(list)) 156 | } 157 | 158 | for _, file := range list { 159 | var asset Asset 160 | asset.Path = filepath.Join(dirpath, file.Name()) 161 | asset.Name = filepath.ToSlash(asset.Path) 162 | 163 | ignoring := false 164 | for _, re := range ignore { 165 | if re.MatchString(asset.Path) { 166 | ignoring = true 167 | break 168 | } 169 | } 170 | if ignoring { 171 | continue 172 | } 173 | 174 | if file.IsDir() { 175 | if recursive { 176 | recursivePath := filepath.Join(dir, file.Name()) 177 | visitedPaths[asset.Path] = true 178 | findFiles(recursivePath, prefix, recursive, toc, ignore, knownFuncs, visitedPaths) 179 | } 180 | continue 181 | } else if file.Mode()&os.ModeSymlink == os.ModeSymlink { 182 | var linkPath string 183 | if linkPath, err = os.Readlink(asset.Path); err != nil { 184 | return err 185 | } 186 | if !filepath.IsAbs(linkPath) { 187 | if linkPath, err = filepath.Abs(dirpath + "/" + linkPath); err != nil { 188 | return err 189 | } 190 | } 191 | if _, ok := visitedPaths[linkPath]; !ok { 192 | visitedPaths[linkPath] = true 193 | findFiles(asset.Path, prefix, recursive, toc, ignore, knownFuncs, visitedPaths) 194 | } 195 | continue 196 | } 197 | 198 | if strings.HasPrefix(asset.Name, prefix) { 199 | asset.Name = asset.Name[len(prefix):] 200 | } else { 201 | asset.Name = filepath.Join(dir, file.Name()) 202 | } 203 | 204 | // If we have a leading slash, get rid of it. 205 | if len(asset.Name) > 0 && asset.Name[0] == '/' { 206 | asset.Name = asset.Name[1:] 207 | } 208 | 209 | // This shouldn't happen. 210 | if len(asset.Name) == 0 { 211 | return fmt.Errorf("Invalid file: %v", asset.Path) 212 | } 213 | 214 | asset.Func = safeFunctionName(asset.Name, knownFuncs) 215 | asset.Path, _ = filepath.Abs(asset.Path) 216 | *toc = append(*toc, asset) 217 | } 218 | 219 | return nil 220 | } 221 | 222 | var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`) 223 | 224 | // safeFunctionName converts the given name into a name 225 | // which qualifies as a valid function identifier. It 226 | // also compares against a known list of functions to 227 | // prevent conflict based on name translation. 228 | func safeFunctionName(name string, knownFuncs map[string]int) string { 229 | var inBytes, outBytes []byte 230 | var toUpper bool 231 | 232 | name = strings.ToLower(name) 233 | inBytes = []byte(name) 234 | 235 | for i := 0; i < len(inBytes); i++ { 236 | if regFuncName.Match([]byte{inBytes[i]}) { 237 | toUpper = true 238 | } else if toUpper { 239 | outBytes = append(outBytes, []byte(strings.ToUpper(string(inBytes[i])))...) 240 | toUpper = false 241 | } else { 242 | outBytes = append(outBytes, inBytes[i]) 243 | } 244 | } 245 | 246 | name = string(outBytes) 247 | 248 | // Identifier can't start with a digit. 249 | if unicode.IsDigit(rune(name[0])) { 250 | name = "_" + name 251 | } 252 | 253 | if num, ok := knownFuncs[name]; ok { 254 | knownFuncs[name] = num + 1 255 | name = fmt.Sprintf("%s%d", name, num) 256 | } else { 257 | knownFuncs[name] = 2 258 | } 259 | 260 | return name 261 | } 262 | -------------------------------------------------------------------------------- /convert_test.go: -------------------------------------------------------------------------------- 1 | package bindata 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestSafeFunctionName(t *testing.T) { 10 | var knownFuncs = make(map[string]int) 11 | name1 := safeFunctionName("foo/bar", knownFuncs) 12 | name2 := safeFunctionName("foo_bar", knownFuncs) 13 | if name1 == name2 { 14 | t.Errorf("name collision") 15 | } 16 | } 17 | 18 | func TestFindFiles(t *testing.T) { 19 | var toc []Asset 20 | var knownFuncs = make(map[string]int) 21 | var visitedPaths = make(map[string]bool) 22 | err := findFiles("testdata/dupname", "testdata/dupname", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 23 | if err != nil { 24 | t.Errorf("expected to be no error: %+v", err) 25 | } 26 | if toc[0].Func == toc[1].Func { 27 | t.Errorf("name collision") 28 | } 29 | } 30 | 31 | func TestFindFilesWithSymlinks(t *testing.T) { 32 | var tocSrc []Asset 33 | var tocTarget []Asset 34 | 35 | var knownFuncs = make(map[string]int) 36 | var visitedPaths = make(map[string]bool) 37 | err := findFiles("testdata/symlinkSrc", "testdata/symlinkSrc", true, &tocSrc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 38 | if err != nil { 39 | t.Errorf("expected to be no error: %+v", err) 40 | } 41 | 42 | knownFuncs = make(map[string]int) 43 | visitedPaths = make(map[string]bool) 44 | err = findFiles("testdata/symlinkParent", "testdata/symlinkParent", true, &tocTarget, []*regexp.Regexp{}, knownFuncs, visitedPaths) 45 | if err != nil { 46 | t.Errorf("expected to be no error: %+v", err) 47 | } 48 | 49 | if len(tocSrc) != len(tocTarget) { 50 | t.Errorf("Symlink source and target should have the same number of assets. Expected %d got %d", len(tocTarget), len(tocSrc)) 51 | } else { 52 | for i, _ := range tocSrc { 53 | targetFunc := strings.TrimPrefix(tocTarget[i].Func, "symlinktarget") 54 | targetFunc = strings.ToLower(targetFunc[:1]) + targetFunc[1:] 55 | if tocSrc[i].Func != targetFunc { 56 | t.Errorf("Symlink source and target produced different function lists. Expected %s to be %s", targetFunc, tocSrc[i].Func) 57 | } 58 | } 59 | } 60 | } 61 | 62 | func TestFindFilesWithRecursiveSymlinks(t *testing.T) { 63 | var toc []Asset 64 | 65 | var knownFuncs = make(map[string]int) 66 | var visitedPaths = make(map[string]bool) 67 | err := findFiles("testdata/symlinkRecursiveParent", "testdata/symlinkRecursiveParent", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 68 | if err != nil { 69 | t.Errorf("expected to be no error: %+v", err) 70 | } 71 | 72 | if len(toc) != 1 { 73 | t.Errorf("Only one asset should have been found. Got %d: %v", len(toc), toc) 74 | } 75 | } 76 | 77 | func TestFindFilesWithSymlinkedFile(t *testing.T) { 78 | var toc []Asset 79 | 80 | var knownFuncs = make(map[string]int) 81 | var visitedPaths = make(map[string]bool) 82 | err := findFiles("testdata/symlinkFile", "testdata/symlinkFile", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 83 | if err != nil { 84 | t.Errorf("expected to be no error: %+v", err) 85 | } 86 | 87 | if len(toc) != 1 { 88 | t.Errorf("Only one asset should have been found. Got %d: %v", len(toc), toc) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /debug.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | ) 11 | 12 | // writeDebug writes the debug code file. 13 | func writeDebug(w io.Writer, c *Config, toc []Asset) error { 14 | err := writeDebugHeader(w) 15 | if err != nil { 16 | return err 17 | } 18 | 19 | for i := range toc { 20 | err = writeDebugAsset(w, c, &toc[i]) 21 | if err != nil { 22 | return err 23 | } 24 | } 25 | 26 | return nil 27 | } 28 | 29 | // writeDebugHeader writes output file headers. 30 | // This targets debug builds. 31 | func writeDebugHeader(w io.Writer) error { 32 | _, err := fmt.Fprintf(w, `import ( 33 | "fmt" 34 | "io/ioutil" 35 | "os" 36 | "path/filepath" 37 | "strings" 38 | ) 39 | 40 | // bindataRead reads the given file from disk. It returns an error on failure. 41 | func bindataRead(path, name string) ([]byte, error) { 42 | buf, err := ioutil.ReadFile(path) 43 | if err != nil { 44 | err = fmt.Errorf("Error reading asset %%s at %%s: %%v", name, path, err) 45 | } 46 | return buf, err 47 | } 48 | 49 | type asset struct { 50 | bytes []byte 51 | info os.FileInfo 52 | } 53 | 54 | `) 55 | return err 56 | } 57 | 58 | // writeDebugAsset write a debug entry for the given asset. 59 | // A debug entry is simply a function which reads the asset from 60 | // the original file (e.g.: from disk). 61 | func writeDebugAsset(w io.Writer, c *Config, asset *Asset) error { 62 | pathExpr := fmt.Sprintf("%q", asset.Path) 63 | if c.Dev { 64 | pathExpr = fmt.Sprintf("filepath.Join(rootDir, %q)", asset.Name) 65 | } 66 | 67 | _, err := fmt.Fprintf(w, `// %s reads file data from disk. It returns an error on failure. 68 | func %s() (*asset, error) { 69 | path := %s 70 | name := %q 71 | bytes, err := bindataRead(path, name) 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | fi, err := os.Stat(path) 77 | if err != nil { 78 | err = fmt.Errorf("Error reading asset info %%s at %%s: %%v", name, path, err) 79 | } 80 | 81 | a := &asset{bytes: bytes, info: fi} 82 | return a, err 83 | } 84 | 85 | `, asset.Func, asset.Func, pathExpr, asset.Name) 86 | return err 87 | } 88 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | /* 6 | bindata converts any file into managable Go source code. Useful for 7 | embedding binary data into a go program. The file data is optionally gzip 8 | compressed before being converted to a raw byte slice. 9 | 10 | The following paragraphs cover some of the customization options 11 | which can be specified in the Config struct, which must be passed into 12 | the Translate() call. 13 | 14 | 15 | Debug vs Release builds 16 | 17 | When used with the `Debug` option, the generated code does not actually include 18 | the asset data. Instead, it generates function stubs which load the data from 19 | the original file on disk. The asset API remains identical between debug and 20 | release builds, so your code will not have to change. 21 | 22 | This is useful during development when you expect the assets to change often. 23 | The host application using these assets uses the same API in both cases and 24 | will not have to care where the actual data comes from. 25 | 26 | An example is a Go webserver with some embedded, static web content like 27 | HTML, JS and CSS files. While developing it, you do not want to rebuild the 28 | whole server and restart it every time you make a change to a bit of 29 | javascript. You just want to build and launch the server once. Then just press 30 | refresh in the browser to see those changes. Embedding the assets with the 31 | `debug` flag allows you to do just that. When you are finished developing and 32 | ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. 33 | It will now embed the latest version of the assets. 34 | 35 | 36 | Lower memory footprint 37 | 38 | The `NoMemCopy` option will alter the way the output file is generated. 39 | It will employ a hack that allows us to read the file data directly from 40 | the compiled program's `.rodata` section. This ensures that when we call 41 | call our generated function, we omit unnecessary memcopies. 42 | 43 | The downside of this, is that it requires dependencies on the `reflect` and 44 | `unsafe` packages. These may be restricted on platforms like AppEngine and 45 | thus prevent you from using this mode. 46 | 47 | Another disadvantage is that the byte slice we create, is strictly read-only. 48 | For most use-cases this is not a problem, but if you ever try to alter the 49 | returned byte slice, a runtime panic is thrown. Use this mode only on target 50 | platforms where memory constraints are an issue. 51 | 52 | The default behaviour is to use the old code generation method. This 53 | prevents the two previously mentioned issues, but will employ at least one 54 | extra memcopy and thus increase memory requirements. 55 | 56 | For instance, consider the following two examples: 57 | 58 | This would be the default mode, using an extra memcopy but gives a safe 59 | implementation without dependencies on `reflect` and `unsafe`: 60 | 61 | func myfile() []byte { 62 | return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a} 63 | } 64 | 65 | Here is the same functionality, but uses the `.rodata` hack. 66 | The byte slice returned from this example can not be written to without 67 | generating a runtime error. 68 | 69 | var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" 70 | 71 | func myfile() []byte { 72 | var empty [0]byte 73 | sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) 74 | b := empty[:] 75 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 76 | bx.Data = sx.Data 77 | bx.Len = len(_myfile) 78 | bx.Cap = bx.Len 79 | return b 80 | } 81 | 82 | 83 | Optional compression 84 | 85 | The NoCompress option indicates that the supplied assets are *not* GZIP 86 | compressed before being turned into Go code. The data should still be accessed 87 | through a function call, so nothing changes in the API. 88 | 89 | This feature is useful if you do not care for compression, or the supplied 90 | resource is already compressed. Doing it again would not add any value and may 91 | even increase the size of the data. 92 | 93 | The default behaviour of the program is to use compression. 94 | 95 | 96 | Path prefix stripping 97 | 98 | The keys used in the `_bindata` map are the same as the input file name 99 | passed to `go-bindata`. This includes the path. In most cases, this is not 100 | desireable, as it puts potentially sensitive information in your code base. 101 | For this purpose, the tool supplies another command line flag `-prefix`. 102 | This accepts a portion of a path name, which should be stripped off from 103 | the map keys and function names. 104 | 105 | For example, running without the `-prefix` flag, we get: 106 | 107 | $ go-bindata /path/to/templates/ 108 | 109 | _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html 110 | 111 | Running with the `-prefix` flag, we get: 112 | 113 | $ go-bindata -prefix "/path/to/" /path/to/templates/ 114 | 115 | _bindata["templates/foo.html"] = templates_foo_html 116 | 117 | 118 | Build tags 119 | 120 | With the optional Tags field, you can specify any go build tags that 121 | must be fulfilled for the output file to be included in a build. This 122 | is useful when including binary data in multiple formats, where the desired 123 | format is specified at build time with the appropriate tags. 124 | 125 | The tags are appended to a `// +build` line in the beginning of the output file 126 | and must follow the build tags syntax specified by the go tool. 127 | 128 | */ 129 | package bindata 130 | -------------------------------------------------------------------------------- /go-bindata/AppendSliceValue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "strings" 4 | 5 | // borrowed from https://github.com/hashicorp/serf/blob/master/command/agent/flag_slice_value.go 6 | 7 | // AppendSliceValue implements the flag.Value interface and allows multiple 8 | // calls to the same variable to append a list. 9 | type AppendSliceValue []string 10 | 11 | func (s *AppendSliceValue) String() string { 12 | return strings.Join(*s, ",") 13 | } 14 | 15 | func (s *AppendSliceValue) Set(value string) error { 16 | if *s == nil { 17 | *s = make([]string, 0, 1) 18 | } 19 | 20 | *s = append(*s, value) 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /go-bindata/main.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "os" 11 | "path/filepath" 12 | "regexp" 13 | "strings" 14 | 15 | "github.com/jteeuwen/go-bindata" 16 | ) 17 | 18 | func main() { 19 | cfg := parseArgs() 20 | err := bindata.Translate(cfg) 21 | 22 | if err != nil { 23 | fmt.Fprintf(os.Stderr, "bindata: %v\n", err) 24 | os.Exit(1) 25 | } 26 | } 27 | 28 | // parseArgs create s a new, filled configuration instance 29 | // by reading and parsing command line options. 30 | // 31 | // This function exits the program with an error, if 32 | // any of the command line options are incorrect. 33 | func parseArgs() *bindata.Config { 34 | var version bool 35 | 36 | c := bindata.NewConfig() 37 | 38 | flag.Usage = func() { 39 | fmt.Printf("Usage: %s [options] \n\n", os.Args[0]) 40 | flag.PrintDefaults() 41 | } 42 | 43 | flag.BoolVar(&c.Debug, "debug", c.Debug, "Do not embed the assets, but provide the embedding API. Contents will still be loaded from disk.") 44 | flag.BoolVar(&c.Dev, "dev", c.Dev, "Similar to debug, but does not emit absolute paths. Expects a rootDir variable to already exist in the generated code's package.") 45 | flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of build tags to include.") 46 | flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off asset names.") 47 | flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.") 48 | 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.") 49 | flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.") 50 | flag.BoolVar(&c.NoMetadata, "nometadata", c.NoMetadata, "Assets will not preserve size, mode, and modtime info.") 51 | flag.UintVar(&c.Mode, "mode", c.Mode, "Optional file mode override for all files.") 52 | flag.Int64Var(&c.ModTime, "modtime", c.ModTime, "Optional modification unix timestamp override for all files.") 53 | flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.") 54 | flag.BoolVar(&version, "version", false, "Displays version information.") 55 | 56 | ignore := make([]string, 0) 57 | flag.Var((*AppendSliceValue)(&ignore), "ignore", "Regex pattern to ignore") 58 | 59 | flag.Parse() 60 | 61 | patterns := make([]*regexp.Regexp, 0) 62 | for _, pattern := range ignore { 63 | patterns = append(patterns, regexp.MustCompile(pattern)) 64 | } 65 | c.Ignore = patterns 66 | 67 | if version { 68 | fmt.Printf("%s\n", Version()) 69 | os.Exit(0) 70 | } 71 | 72 | // Make sure we have input paths. 73 | if flag.NArg() == 0 { 74 | fmt.Fprintf(os.Stderr, "Missing \n\n") 75 | flag.Usage() 76 | os.Exit(1) 77 | } 78 | 79 | // Create input configurations. 80 | c.Input = make([]bindata.InputConfig, flag.NArg()) 81 | for i := range c.Input { 82 | c.Input[i] = parseInput(flag.Arg(i)) 83 | } 84 | 85 | return c 86 | } 87 | 88 | // parseRecursive determines whether the given path has a recrusive indicator and 89 | // returns a new path with the recursive indicator chopped off if it does. 90 | // 91 | // ex: 92 | // /path/to/foo/... -> (/path/to/foo, true) 93 | // /path/to/bar -> (/path/to/bar, false) 94 | func parseInput(path string) bindata.InputConfig { 95 | if strings.HasSuffix(path, "/...") { 96 | return bindata.InputConfig{ 97 | Path: filepath.Clean(path[:len(path)-4]), 98 | Recursive: true, 99 | } 100 | } else { 101 | return bindata.InputConfig{ 102 | Path: filepath.Clean(path), 103 | Recursive: false, 104 | } 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /go-bindata/version.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "runtime" 10 | ) 11 | 12 | const ( 13 | AppName = "go-bindata" 14 | AppVersionMajor = 3 15 | AppVersionMinor = 1 16 | ) 17 | 18 | // revision part of the program version. 19 | // This will be set automatically at build time like so: 20 | // 21 | // go build -ldflags "-X main.AppVersionRev `date -u +%s`" 22 | var AppVersionRev string 23 | 24 | func Version() string { 25 | if len(AppVersionRev) == 0 { 26 | AppVersionRev = "0" 27 | } 28 | 29 | return fmt.Sprintf("%s %d.%d.%s (Go runtime %s).\nCopyright (c) 2010-2013, Jim Teeuwen.", 30 | AppName, AppVersionMajor, AppVersionMinor, AppVersionRev, runtime.Version()) 31 | } 32 | -------------------------------------------------------------------------------- /release.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "bytes" 9 | "compress/gzip" 10 | "fmt" 11 | "io" 12 | "io/ioutil" 13 | "os" 14 | "unicode/utf8" 15 | ) 16 | 17 | // writeRelease writes the release code file. 18 | func writeRelease(w io.Writer, c *Config, toc []Asset) error { 19 | err := writeReleaseHeader(w, c) 20 | if err != nil { 21 | return err 22 | } 23 | 24 | for i := range toc { 25 | err = writeReleaseAsset(w, c, &toc[i]) 26 | if err != nil { 27 | return err 28 | } 29 | } 30 | 31 | return nil 32 | } 33 | 34 | // writeReleaseHeader writes output file headers. 35 | // This targets release builds. 36 | func writeReleaseHeader(w io.Writer, c *Config) error { 37 | var err error 38 | if c.NoCompress { 39 | if c.NoMemCopy { 40 | err = header_uncompressed_nomemcopy(w) 41 | } else { 42 | err = header_uncompressed_memcopy(w) 43 | } 44 | } else { 45 | if c.NoMemCopy { 46 | err = header_compressed_nomemcopy(w) 47 | } else { 48 | err = header_compressed_memcopy(w) 49 | } 50 | } 51 | if err != nil { 52 | return err 53 | } 54 | return header_release_common(w) 55 | } 56 | 57 | // writeReleaseAsset write a release entry for the given asset. 58 | // A release entry is a function which embeds and returns 59 | // the file's byte content. 60 | func writeReleaseAsset(w io.Writer, c *Config, asset *Asset) error { 61 | fd, err := os.Open(asset.Path) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | defer fd.Close() 67 | 68 | if c.NoCompress { 69 | if c.NoMemCopy { 70 | err = uncompressed_nomemcopy(w, asset, fd) 71 | } else { 72 | err = uncompressed_memcopy(w, asset, fd) 73 | } 74 | } else { 75 | if c.NoMemCopy { 76 | err = compressed_nomemcopy(w, asset, fd) 77 | } else { 78 | err = compressed_memcopy(w, asset, fd) 79 | } 80 | } 81 | if err != nil { 82 | return err 83 | } 84 | return asset_release_common(w, c, asset) 85 | } 86 | 87 | // sanitize prepares a valid UTF-8 string as a raw string constant. 88 | // Based on https://code.google.com/p/go/source/browse/godoc/static/makestatic.go?repo=tools 89 | func sanitize(b []byte) []byte { 90 | // Replace ` with `+"`"+` 91 | b = bytes.Replace(b, []byte("`"), []byte("`+\"`\"+`"), -1) 92 | 93 | // Replace BOM with `+"\xEF\xBB\xBF"+` 94 | // (A BOM is valid UTF-8 but not permitted in Go source files. 95 | // I wouldn't bother handling this, but for some insane reason 96 | // jquery.js has a BOM somewhere in the middle.) 97 | return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1) 98 | } 99 | 100 | func header_compressed_nomemcopy(w io.Writer) error { 101 | _, err := fmt.Fprintf(w, `import ( 102 | "bytes" 103 | "compress/gzip" 104 | "fmt" 105 | "io" 106 | "io/ioutil" 107 | "os" 108 | "path/filepath" 109 | "strings" 110 | "time" 111 | ) 112 | 113 | func bindataRead(data, name string) ([]byte, error) { 114 | gz, err := gzip.NewReader(strings.NewReader(data)) 115 | if err != nil { 116 | return nil, fmt.Errorf("Read %%q: %%v", name, err) 117 | } 118 | 119 | var buf bytes.Buffer 120 | _, err = io.Copy(&buf, gz) 121 | clErr := gz.Close() 122 | 123 | if err != nil { 124 | return nil, fmt.Errorf("Read %%q: %%v", name, err) 125 | } 126 | if clErr != nil { 127 | return nil, err 128 | } 129 | 130 | return buf.Bytes(), nil 131 | } 132 | 133 | `) 134 | return err 135 | } 136 | 137 | func header_compressed_memcopy(w io.Writer) error { 138 | _, err := fmt.Fprintf(w, `import ( 139 | "bytes" 140 | "compress/gzip" 141 | "fmt" 142 | "io" 143 | "io/ioutil" 144 | "os" 145 | "path/filepath" 146 | "strings" 147 | "time" 148 | ) 149 | 150 | func bindataRead(data []byte, name string) ([]byte, error) { 151 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 152 | if err != nil { 153 | return nil, fmt.Errorf("Read %%q: %%v", name, err) 154 | } 155 | 156 | var buf bytes.Buffer 157 | _, err = io.Copy(&buf, gz) 158 | clErr := gz.Close() 159 | 160 | if err != nil { 161 | return nil, fmt.Errorf("Read %%q: %%v", name, err) 162 | } 163 | if clErr != nil { 164 | return nil, err 165 | } 166 | 167 | return buf.Bytes(), nil 168 | } 169 | 170 | `) 171 | return err 172 | } 173 | 174 | func header_uncompressed_nomemcopy(w io.Writer) error { 175 | _, err := fmt.Fprintf(w, `import ( 176 | "fmt" 177 | "io/ioutil" 178 | "os" 179 | "path/filepath" 180 | "reflect" 181 | "strings" 182 | "time" 183 | "unsafe" 184 | ) 185 | 186 | func bindataRead(data, name string) ([]byte, error) { 187 | var empty [0]byte 188 | sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) 189 | b := empty[:] 190 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 191 | bx.Data = sx.Data 192 | bx.Len = len(data) 193 | bx.Cap = bx.Len 194 | return b, nil 195 | } 196 | 197 | `) 198 | return err 199 | } 200 | 201 | func header_uncompressed_memcopy(w io.Writer) error { 202 | _, err := fmt.Fprintf(w, `import ( 203 | "fmt" 204 | "io/ioutil" 205 | "os" 206 | "path/filepath" 207 | "strings" 208 | "time" 209 | ) 210 | `) 211 | return err 212 | } 213 | 214 | func header_release_common(w io.Writer) error { 215 | _, err := fmt.Fprintf(w, `type asset struct { 216 | bytes []byte 217 | info os.FileInfo 218 | } 219 | 220 | type bindataFileInfo struct { 221 | name string 222 | size int64 223 | mode os.FileMode 224 | modTime time.Time 225 | } 226 | 227 | func (fi bindataFileInfo) Name() string { 228 | return fi.name 229 | } 230 | func (fi bindataFileInfo) Size() int64 { 231 | return fi.size 232 | } 233 | func (fi bindataFileInfo) Mode() os.FileMode { 234 | return fi.mode 235 | } 236 | func (fi bindataFileInfo) ModTime() time.Time { 237 | return fi.modTime 238 | } 239 | func (fi bindataFileInfo) IsDir() bool { 240 | return false 241 | } 242 | func (fi bindataFileInfo) Sys() interface{} { 243 | return nil 244 | } 245 | 246 | `) 247 | return err 248 | } 249 | 250 | func compressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error { 251 | _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) 252 | if err != nil { 253 | return err 254 | } 255 | 256 | gz := gzip.NewWriter(&StringWriter{Writer: w}) 257 | _, err = io.Copy(gz, r) 258 | gz.Close() 259 | 260 | if err != nil { 261 | return err 262 | } 263 | 264 | _, err = fmt.Fprintf(w, `" 265 | 266 | func %sBytes() ([]byte, error) { 267 | return bindataRead( 268 | _%s, 269 | %q, 270 | ) 271 | } 272 | 273 | `, asset.Func, asset.Func, asset.Name) 274 | return err 275 | } 276 | 277 | func compressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error { 278 | _, err := fmt.Fprintf(w, `var _%s = []byte("`, asset.Func) 279 | if err != nil { 280 | return err 281 | } 282 | 283 | gz := gzip.NewWriter(&StringWriter{Writer: w}) 284 | _, err = io.Copy(gz, r) 285 | gz.Close() 286 | 287 | if err != nil { 288 | return err 289 | } 290 | 291 | _, err = fmt.Fprintf(w, `") 292 | 293 | func %sBytes() ([]byte, error) { 294 | return bindataRead( 295 | _%s, 296 | %q, 297 | ) 298 | } 299 | 300 | `, asset.Func, asset.Func, asset.Name) 301 | return err 302 | } 303 | 304 | func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error { 305 | _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) 306 | if err != nil { 307 | return err 308 | } 309 | 310 | _, err = io.Copy(&StringWriter{Writer: w}, r) 311 | if err != nil { 312 | return err 313 | } 314 | 315 | _, err = fmt.Fprintf(w, `" 316 | 317 | func %sBytes() ([]byte, error) { 318 | return bindataRead( 319 | _%s, 320 | %q, 321 | ) 322 | } 323 | 324 | `, asset.Func, asset.Func, asset.Name) 325 | return err 326 | } 327 | 328 | func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error { 329 | _, err := fmt.Fprintf(w, `var _%s = []byte(`, asset.Func) 330 | if err != nil { 331 | return err 332 | } 333 | 334 | b, err := ioutil.ReadAll(r) 335 | if err != nil { 336 | return err 337 | } 338 | if utf8.Valid(b) && !bytes.Contains(b, []byte{0}) { 339 | fmt.Fprintf(w, "`%s`", sanitize(b)) 340 | } else { 341 | fmt.Fprintf(w, "%+q", b) 342 | } 343 | 344 | _, err = fmt.Fprintf(w, `) 345 | 346 | func %sBytes() ([]byte, error) { 347 | return _%s, nil 348 | } 349 | 350 | `, asset.Func, asset.Func) 351 | return err 352 | } 353 | 354 | func asset_release_common(w io.Writer, c *Config, asset *Asset) error { 355 | fi, err := os.Stat(asset.Path) 356 | if err != nil { 357 | return err 358 | } 359 | 360 | mode := uint(fi.Mode()) 361 | modTime := fi.ModTime().Unix() 362 | size := fi.Size() 363 | if c.NoMetadata { 364 | mode = 0 365 | modTime = 0 366 | size = 0 367 | } 368 | if c.Mode > 0 { 369 | mode = uint(os.ModePerm) & c.Mode 370 | } 371 | if c.ModTime > 0 { 372 | modTime = c.ModTime 373 | } 374 | _, err = fmt.Fprintf(w, `func %s() (*asset, error) { 375 | bytes, err := %sBytes() 376 | if err != nil { 377 | return nil, err 378 | } 379 | 380 | info := bindataFileInfo{name: %q, size: %d, mode: os.FileMode(%d), modTime: time.Unix(%d, 0)} 381 | a := &asset{bytes: bytes, info: info} 382 | return a, nil 383 | } 384 | 385 | `, asset.Func, asset.Func, asset.Name, size, mode, modTime) 386 | return err 387 | } 388 | -------------------------------------------------------------------------------- /restore.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | ) 11 | 12 | func writeRestore(w io.Writer) error { 13 | _, err := fmt.Fprintf(w, ` 14 | // RestoreAsset restores an asset under the given directory 15 | func RestoreAsset(dir, name string) error { 16 | data, err := Asset(name) 17 | if err != nil { 18 | return err 19 | } 20 | info, err := AssetInfo(name) 21 | if err != nil { 22 | return err 23 | } 24 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 25 | if err != nil { 26 | return err 27 | } 28 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 29 | if err != nil { 30 | return err 31 | } 32 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 33 | if err != nil { 34 | return err 35 | } 36 | return nil 37 | } 38 | 39 | // RestoreAssets restores an asset under the given directory recursively 40 | func RestoreAssets(dir, name string) error { 41 | children, err := AssetDir(name) 42 | // File 43 | if err != nil { 44 | return RestoreAsset(dir, name) 45 | } 46 | // Dir 47 | for _, child := range children { 48 | err = RestoreAssets(dir, filepath.Join(name, child)) 49 | if err != nil { 50 | return err 51 | } 52 | } 53 | return nil 54 | } 55 | 56 | func _filePath(dir, name string) string { 57 | cannonicalName := strings.Replace(name, "\\", "/", -1) 58 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 59 | } 60 | 61 | `) 62 | return err 63 | } 64 | -------------------------------------------------------------------------------- /stringwriter.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "io" 9 | ) 10 | 11 | const lowerHex = "0123456789abcdef" 12 | 13 | type StringWriter struct { 14 | io.Writer 15 | c int 16 | } 17 | 18 | func (w *StringWriter) Write(p []byte) (n int, err error) { 19 | if len(p) == 0 { 20 | return 21 | } 22 | 23 | buf := []byte(`\x00`) 24 | var b byte 25 | 26 | for n, b = range p { 27 | buf[2] = lowerHex[b/16] 28 | buf[3] = lowerHex[b%16] 29 | w.Writer.Write(buf) 30 | w.c++ 31 | } 32 | 33 | n++ 34 | 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /testdata/Makefile: -------------------------------------------------------------------------------- 1 | FILES:=$(wildcard out/*.go) 2 | 3 | .PHONY: check 4 | check: errcheck vet golint $(FILES:.go=.checked) 5 | 6 | out/%.checked: out/%.go 7 | errcheck $< 8 | go tool vet --all $< 9 | go tool vet --shadow $< 10 | golint $< 11 | 12 | $(GOPATH)/bin/go-bindata: $(wildcard ../*.go) $(wildcard ../**/*.go) 13 | go install ../... 14 | 15 | out/compress-memcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 16 | $(GOPATH)/bin/go-bindata -o $@ in/... 17 | 18 | out/compress-nomemcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 19 | $(GOPATH)/bin/go-bindata -nomemcopy -o $@ in/... 20 | 21 | out/debug.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 22 | $(GOPATH)/bin/go-bindata -debug -o $@ in/... 23 | 24 | out/nocompress-memcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 25 | $(GOPATH)/bin/go-bindata -nocompress -o $@ in/... 26 | 27 | out/nocompress-nomemcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 28 | $(GOPATH)/bin/go-bindata -nocompress -nomemcopy -o $@ in/... 29 | 30 | errcheck: 31 | go get github.com/kisielk/errcheck 32 | 33 | vet: 34 | go get golang.org/x/tools/cmd/vet 35 | 36 | golint: 37 | go get github.com/golang/lint/golint 38 | -------------------------------------------------------------------------------- /testdata/dupname/foo/bar: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/dupname/foo_bar: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/in/a/test.asset: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/in/b/test.asset: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/in/c/test.asset: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/in/test.asset: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/out/compress-memcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // in/a/test.asset 4 | // in/b/test.asset 5 | // in/c/test.asset 6 | // in/test.asset 7 | // DO NOT EDIT! 8 | 9 | package main 10 | 11 | import ( 12 | "bytes" 13 | "compress/gzip" 14 | "fmt" 15 | "io" 16 | "io/ioutil" 17 | "os" 18 | "path/filepath" 19 | "strings" 20 | "time" 21 | ) 22 | 23 | func bindataRead(data []byte, name string) ([]byte, error) { 24 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 25 | if err != nil { 26 | return nil, fmt.Errorf("Read %q: %v", name, err) 27 | } 28 | 29 | var buf bytes.Buffer 30 | _, err = io.Copy(&buf, gz) 31 | clErr := gz.Close() 32 | 33 | if err != nil { 34 | return nil, fmt.Errorf("Read %q: %v", name, err) 35 | } 36 | if clErr != nil { 37 | return nil, err 38 | } 39 | 40 | return buf.Bytes(), nil 41 | } 42 | 43 | type asset struct { 44 | bytes []byte 45 | info os.FileInfo 46 | } 47 | 48 | type bindataFileInfo struct { 49 | name string 50 | size int64 51 | mode os.FileMode 52 | modTime time.Time 53 | } 54 | 55 | func (fi bindataFileInfo) Name() string { 56 | return fi.name 57 | } 58 | func (fi bindataFileInfo) Size() int64 { 59 | return fi.size 60 | } 61 | func (fi bindataFileInfo) Mode() os.FileMode { 62 | return fi.mode 63 | } 64 | func (fi bindataFileInfo) ModTime() time.Time { 65 | return fi.modTime 66 | } 67 | func (fi bindataFileInfo) IsDir() bool { 68 | return false 69 | } 70 | func (fi bindataFileInfo) Sys() interface{} { 71 | return nil 72 | } 73 | 74 | var _inATestAsset = []byte("\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") 75 | 76 | func inATestAssetBytes() ([]byte, error) { 77 | return bindataRead( 78 | _inATestAsset, 79 | "in/a/test.asset", 80 | ) 81 | } 82 | 83 | func inATestAsset() (*asset, error) { 84 | bytes, err := inATestAssetBytes() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | info := bindataFileInfo{name: "in/a/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 90 | a := &asset{bytes: bytes, info: info} 91 | return a, nil 92 | } 93 | 94 | var _inBTestAsset = []byte("\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") 95 | 96 | func inBTestAssetBytes() ([]byte, error) { 97 | return bindataRead( 98 | _inBTestAsset, 99 | "in/b/test.asset", 100 | ) 101 | } 102 | 103 | func inBTestAsset() (*asset, error) { 104 | bytes, err := inBTestAssetBytes() 105 | if err != nil { 106 | return nil, err 107 | } 108 | 109 | info := bindataFileInfo{name: "in/b/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 110 | a := &asset{bytes: bytes, info: info} 111 | return a, nil 112 | } 113 | 114 | var _inCTestAsset = []byte("\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") 115 | 116 | func inCTestAssetBytes() ([]byte, error) { 117 | return bindataRead( 118 | _inCTestAsset, 119 | "in/c/test.asset", 120 | ) 121 | } 122 | 123 | func inCTestAsset() (*asset, error) { 124 | bytes, err := inCTestAssetBytes() 125 | if err != nil { 126 | return nil, err 127 | } 128 | 129 | info := bindataFileInfo{name: "in/c/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 130 | a := &asset{bytes: bytes, info: info} 131 | return a, nil 132 | } 133 | 134 | var _inTestAsset = []byte("\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") 135 | 136 | func inTestAssetBytes() ([]byte, error) { 137 | return bindataRead( 138 | _inTestAsset, 139 | "in/test.asset", 140 | ) 141 | } 142 | 143 | func inTestAsset() (*asset, error) { 144 | bytes, err := inTestAssetBytes() 145 | if err != nil { 146 | return nil, err 147 | } 148 | 149 | info := bindataFileInfo{name: "in/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 150 | a := &asset{bytes: bytes, info: info} 151 | return a, nil 152 | } 153 | 154 | // Asset loads and returns the asset for the given name. 155 | // It returns an error if the asset could not be found or 156 | // could not be loaded. 157 | func Asset(name string) ([]byte, error) { 158 | cannonicalName := strings.Replace(name, "\\", "/", -1) 159 | if f, ok := _bindata[cannonicalName]; ok { 160 | a, err := f() 161 | if err != nil { 162 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 163 | } 164 | return a.bytes, nil 165 | } 166 | return nil, fmt.Errorf("Asset %s not found", name) 167 | } 168 | 169 | // MustAsset is like Asset but panics when Asset would return an error. 170 | // It simplifies safe initialization of global variables. 171 | func MustAsset(name string) []byte { 172 | a, err := Asset(name) 173 | if err != nil { 174 | panic("asset: Asset(" + name + "): " + err.Error()) 175 | } 176 | 177 | return a 178 | } 179 | 180 | // AssetInfo loads and returns the asset info for the given name. 181 | // It returns an error if the asset could not be found or 182 | // could not be loaded. 183 | func AssetInfo(name string) (os.FileInfo, error) { 184 | cannonicalName := strings.Replace(name, "\\", "/", -1) 185 | if f, ok := _bindata[cannonicalName]; ok { 186 | a, err := f() 187 | if err != nil { 188 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 189 | } 190 | return a.info, nil 191 | } 192 | return nil, fmt.Errorf("AssetInfo %s not found", name) 193 | } 194 | 195 | // AssetNames returns the names of the assets. 196 | func AssetNames() []string { 197 | names := make([]string, 0, len(_bindata)) 198 | for name := range _bindata { 199 | names = append(names, name) 200 | } 201 | return names 202 | } 203 | 204 | // _bindata is a table, holding each asset generator, mapped to its name. 205 | var _bindata = map[string]func() (*asset, error){ 206 | "in/a/test.asset": inATestAsset, 207 | "in/b/test.asset": inBTestAsset, 208 | "in/c/test.asset": inCTestAsset, 209 | "in/test.asset": inTestAsset, 210 | } 211 | 212 | // AssetDir returns the file names below a certain 213 | // directory embedded in the file by go-bindata. 214 | // For example if you run go-bindata on data/... and data contains the 215 | // following hierarchy: 216 | // data/ 217 | // foo.txt 218 | // img/ 219 | // a.png 220 | // b.png 221 | // then AssetDir("data") would return []string{"foo.txt", "img"} 222 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 223 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 224 | // AssetDir("") will return []string{"data"}. 225 | func AssetDir(name string) ([]string, error) { 226 | node := _bintree 227 | if len(name) != 0 { 228 | cannonicalName := strings.Replace(name, "\\", "/", -1) 229 | pathList := strings.Split(cannonicalName, "/") 230 | for _, p := range pathList { 231 | node = node.Children[p] 232 | if node == nil { 233 | return nil, fmt.Errorf("Asset %s not found", name) 234 | } 235 | } 236 | } 237 | if node.Func != nil { 238 | return nil, fmt.Errorf("Asset %s not found", name) 239 | } 240 | rv := make([]string, 0, len(node.Children)) 241 | for childName := range node.Children { 242 | rv = append(rv, childName) 243 | } 244 | return rv, nil 245 | } 246 | 247 | type bintree struct { 248 | Func func() (*asset, error) 249 | Children map[string]*bintree 250 | } 251 | var _bintree = &bintree{nil, map[string]*bintree{ 252 | "in": &bintree{nil, map[string]*bintree{ 253 | "a": &bintree{nil, map[string]*bintree{ 254 | "test.asset": &bintree{inATestAsset, map[string]*bintree{}}, 255 | }}, 256 | "b": &bintree{nil, map[string]*bintree{ 257 | "test.asset": &bintree{inBTestAsset, map[string]*bintree{}}, 258 | }}, 259 | "c": &bintree{nil, map[string]*bintree{ 260 | "test.asset": &bintree{inCTestAsset, map[string]*bintree{}}, 261 | }}, 262 | "test.asset": &bintree{inTestAsset, map[string]*bintree{}}, 263 | }}, 264 | }} 265 | 266 | // RestoreAsset restores an asset under the given directory 267 | func RestoreAsset(dir, name string) error { 268 | data, err := Asset(name) 269 | if err != nil { 270 | return err 271 | } 272 | info, err := AssetInfo(name) 273 | if err != nil { 274 | return err 275 | } 276 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 277 | if err != nil { 278 | return err 279 | } 280 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 281 | if err != nil { 282 | return err 283 | } 284 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 285 | if err != nil { 286 | return err 287 | } 288 | return nil 289 | } 290 | 291 | // RestoreAssets restores an asset under the given directory recursively 292 | func RestoreAssets(dir, name string) error { 293 | children, err := AssetDir(name) 294 | // File 295 | if err != nil { 296 | return RestoreAsset(dir, name) 297 | } 298 | // Dir 299 | for _, child := range children { 300 | err = RestoreAssets(dir, filepath.Join(name, child)) 301 | if err != nil { 302 | return err 303 | } 304 | } 305 | return nil 306 | } 307 | 308 | func _filePath(dir, name string) string { 309 | cannonicalName := strings.Replace(name, "\\", "/", -1) 310 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 311 | } 312 | 313 | -------------------------------------------------------------------------------- /testdata/out/compress-nomemcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // in/a/test.asset 4 | // in/b/test.asset 5 | // in/c/test.asset 6 | // in/test.asset 7 | // DO NOT EDIT! 8 | 9 | package main 10 | 11 | import ( 12 | "bytes" 13 | "compress/gzip" 14 | "fmt" 15 | "io" 16 | "io/ioutil" 17 | "os" 18 | "path/filepath" 19 | "strings" 20 | "time" 21 | ) 22 | 23 | func bindataRead(data, name string) ([]byte, error) { 24 | gz, err := gzip.NewReader(strings.NewReader(data)) 25 | if err != nil { 26 | return nil, fmt.Errorf("Read %q: %v", name, err) 27 | } 28 | 29 | var buf bytes.Buffer 30 | _, err = io.Copy(&buf, gz) 31 | clErr := gz.Close() 32 | 33 | if err != nil { 34 | return nil, fmt.Errorf("Read %q: %v", name, err) 35 | } 36 | if clErr != nil { 37 | return nil, err 38 | } 39 | 40 | return buf.Bytes(), nil 41 | } 42 | 43 | type asset struct { 44 | bytes []byte 45 | info os.FileInfo 46 | } 47 | 48 | type bindataFileInfo struct { 49 | name string 50 | size int64 51 | mode os.FileMode 52 | modTime time.Time 53 | } 54 | 55 | func (fi bindataFileInfo) Name() string { 56 | return fi.name 57 | } 58 | func (fi bindataFileInfo) Size() int64 { 59 | return fi.size 60 | } 61 | func (fi bindataFileInfo) Mode() os.FileMode { 62 | return fi.mode 63 | } 64 | func (fi bindataFileInfo) ModTime() time.Time { 65 | return fi.modTime 66 | } 67 | func (fi bindataFileInfo) IsDir() bool { 68 | return false 69 | } 70 | func (fi bindataFileInfo) Sys() interface{} { 71 | return nil 72 | } 73 | 74 | var _inATestAsset = "\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" 75 | 76 | func inATestAssetBytes() ([]byte, error) { 77 | return bindataRead( 78 | _inATestAsset, 79 | "in/a/test.asset", 80 | ) 81 | } 82 | 83 | func inATestAsset() (*asset, error) { 84 | bytes, err := inATestAssetBytes() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | info := bindataFileInfo{name: "in/a/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 90 | a := &asset{bytes: bytes, info: info} 91 | return a, nil 92 | } 93 | 94 | var _inBTestAsset = "\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" 95 | 96 | func inBTestAssetBytes() ([]byte, error) { 97 | return bindataRead( 98 | _inBTestAsset, 99 | "in/b/test.asset", 100 | ) 101 | } 102 | 103 | func inBTestAsset() (*asset, error) { 104 | bytes, err := inBTestAssetBytes() 105 | if err != nil { 106 | return nil, err 107 | } 108 | 109 | info := bindataFileInfo{name: "in/b/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 110 | a := &asset{bytes: bytes, info: info} 111 | return a, nil 112 | } 113 | 114 | var _inCTestAsset = "\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" 115 | 116 | func inCTestAssetBytes() ([]byte, error) { 117 | return bindataRead( 118 | _inCTestAsset, 119 | "in/c/test.asset", 120 | ) 121 | } 122 | 123 | func inCTestAsset() (*asset, error) { 124 | bytes, err := inCTestAssetBytes() 125 | if err != nil { 126 | return nil, err 127 | } 128 | 129 | info := bindataFileInfo{name: "in/c/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 130 | a := &asset{bytes: bytes, info: info} 131 | return a, nil 132 | } 133 | 134 | var _inTestAsset = "\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" 135 | 136 | func inTestAssetBytes() ([]byte, error) { 137 | return bindataRead( 138 | _inTestAsset, 139 | "in/test.asset", 140 | ) 141 | } 142 | 143 | func inTestAsset() (*asset, error) { 144 | bytes, err := inTestAssetBytes() 145 | if err != nil { 146 | return nil, err 147 | } 148 | 149 | info := bindataFileInfo{name: "in/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 150 | a := &asset{bytes: bytes, info: info} 151 | return a, nil 152 | } 153 | 154 | // Asset loads and returns the asset for the given name. 155 | // It returns an error if the asset could not be found or 156 | // could not be loaded. 157 | func Asset(name string) ([]byte, error) { 158 | cannonicalName := strings.Replace(name, "\\", "/", -1) 159 | if f, ok := _bindata[cannonicalName]; ok { 160 | a, err := f() 161 | if err != nil { 162 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 163 | } 164 | return a.bytes, nil 165 | } 166 | return nil, fmt.Errorf("Asset %s not found", name) 167 | } 168 | 169 | // MustAsset is like Asset but panics when Asset would return an error. 170 | // It simplifies safe initialization of global variables. 171 | func MustAsset(name string) []byte { 172 | a, err := Asset(name) 173 | if err != nil { 174 | panic("asset: Asset(" + name + "): " + err.Error()) 175 | } 176 | 177 | return a 178 | } 179 | 180 | // AssetInfo loads and returns the asset info for the given name. 181 | // It returns an error if the asset could not be found or 182 | // could not be loaded. 183 | func AssetInfo(name string) (os.FileInfo, error) { 184 | cannonicalName := strings.Replace(name, "\\", "/", -1) 185 | if f, ok := _bindata[cannonicalName]; ok { 186 | a, err := f() 187 | if err != nil { 188 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 189 | } 190 | return a.info, nil 191 | } 192 | return nil, fmt.Errorf("AssetInfo %s not found", name) 193 | } 194 | 195 | // AssetNames returns the names of the assets. 196 | func AssetNames() []string { 197 | names := make([]string, 0, len(_bindata)) 198 | for name := range _bindata { 199 | names = append(names, name) 200 | } 201 | return names 202 | } 203 | 204 | // _bindata is a table, holding each asset generator, mapped to its name. 205 | var _bindata = map[string]func() (*asset, error){ 206 | "in/a/test.asset": inATestAsset, 207 | "in/b/test.asset": inBTestAsset, 208 | "in/c/test.asset": inCTestAsset, 209 | "in/test.asset": inTestAsset, 210 | } 211 | 212 | // AssetDir returns the file names below a certain 213 | // directory embedded in the file by go-bindata. 214 | // For example if you run go-bindata on data/... and data contains the 215 | // following hierarchy: 216 | // data/ 217 | // foo.txt 218 | // img/ 219 | // a.png 220 | // b.png 221 | // then AssetDir("data") would return []string{"foo.txt", "img"} 222 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 223 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 224 | // AssetDir("") will return []string{"data"}. 225 | func AssetDir(name string) ([]string, error) { 226 | node := _bintree 227 | if len(name) != 0 { 228 | cannonicalName := strings.Replace(name, "\\", "/", -1) 229 | pathList := strings.Split(cannonicalName, "/") 230 | for _, p := range pathList { 231 | node = node.Children[p] 232 | if node == nil { 233 | return nil, fmt.Errorf("Asset %s not found", name) 234 | } 235 | } 236 | } 237 | if node.Func != nil { 238 | return nil, fmt.Errorf("Asset %s not found", name) 239 | } 240 | rv := make([]string, 0, len(node.Children)) 241 | for childName := range node.Children { 242 | rv = append(rv, childName) 243 | } 244 | return rv, nil 245 | } 246 | 247 | type bintree struct { 248 | Func func() (*asset, error) 249 | Children map[string]*bintree 250 | } 251 | var _bintree = &bintree{nil, map[string]*bintree{ 252 | "in": &bintree{nil, map[string]*bintree{ 253 | "a": &bintree{nil, map[string]*bintree{ 254 | "test.asset": &bintree{inATestAsset, map[string]*bintree{}}, 255 | }}, 256 | "b": &bintree{nil, map[string]*bintree{ 257 | "test.asset": &bintree{inBTestAsset, map[string]*bintree{}}, 258 | }}, 259 | "c": &bintree{nil, map[string]*bintree{ 260 | "test.asset": &bintree{inCTestAsset, map[string]*bintree{}}, 261 | }}, 262 | "test.asset": &bintree{inTestAsset, map[string]*bintree{}}, 263 | }}, 264 | }} 265 | 266 | // RestoreAsset restores an asset under the given directory 267 | func RestoreAsset(dir, name string) error { 268 | data, err := Asset(name) 269 | if err != nil { 270 | return err 271 | } 272 | info, err := AssetInfo(name) 273 | if err != nil { 274 | return err 275 | } 276 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 277 | if err != nil { 278 | return err 279 | } 280 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 281 | if err != nil { 282 | return err 283 | } 284 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 285 | if err != nil { 286 | return err 287 | } 288 | return nil 289 | } 290 | 291 | // RestoreAssets restores an asset under the given directory recursively 292 | func RestoreAssets(dir, name string) error { 293 | children, err := AssetDir(name) 294 | // File 295 | if err != nil { 296 | return RestoreAsset(dir, name) 297 | } 298 | // Dir 299 | for _, child := range children { 300 | err = RestoreAssets(dir, filepath.Join(name, child)) 301 | if err != nil { 302 | return err 303 | } 304 | } 305 | return nil 306 | } 307 | 308 | func _filePath(dir, name string) string { 309 | cannonicalName := strings.Replace(name, "\\", "/", -1) 310 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 311 | } 312 | 313 | -------------------------------------------------------------------------------- /testdata/out/debug.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // in/a/test.asset 4 | // in/b/test.asset 5 | // in/c/test.asset 6 | // in/test.asset 7 | // DO NOT EDIT! 8 | 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | "io/ioutil" 14 | "os" 15 | "path/filepath" 16 | "strings" 17 | ) 18 | 19 | // bindataRead reads the given file from disk. It returns an error on failure. 20 | func bindataRead(path, name string) ([]byte, error) { 21 | buf, err := ioutil.ReadFile(path) 22 | if err != nil { 23 | err = fmt.Errorf("Error reading asset %s at %s: %v", name, path, err) 24 | } 25 | return buf, err 26 | } 27 | 28 | type asset struct { 29 | bytes []byte 30 | info os.FileInfo 31 | } 32 | 33 | // inATestAsset reads file data from disk. It returns an error on failure. 34 | func inATestAsset() (*asset, error) { 35 | path := "/home/ts/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/a/test.asset" 36 | name := "in/a/test.asset" 37 | bytes, err := bindataRead(path, name) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | fi, err := os.Stat(path) 43 | if err != nil { 44 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 45 | } 46 | 47 | a := &asset{bytes: bytes, info: fi} 48 | return a, err 49 | } 50 | 51 | // inBTestAsset reads file data from disk. It returns an error on failure. 52 | func inBTestAsset() (*asset, error) { 53 | path := "/home/ts/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/b/test.asset" 54 | name := "in/b/test.asset" 55 | bytes, err := bindataRead(path, name) 56 | if err != nil { 57 | return nil, err 58 | } 59 | 60 | fi, err := os.Stat(path) 61 | if err != nil { 62 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 63 | } 64 | 65 | a := &asset{bytes: bytes, info: fi} 66 | return a, err 67 | } 68 | 69 | // inCTestAsset reads file data from disk. It returns an error on failure. 70 | func inCTestAsset() (*asset, error) { 71 | path := "/home/ts/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/c/test.asset" 72 | name := "in/c/test.asset" 73 | bytes, err := bindataRead(path, name) 74 | if err != nil { 75 | return nil, err 76 | } 77 | 78 | fi, err := os.Stat(path) 79 | if err != nil { 80 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 81 | } 82 | 83 | a := &asset{bytes: bytes, info: fi} 84 | return a, err 85 | } 86 | 87 | // inTestAsset reads file data from disk. It returns an error on failure. 88 | func inTestAsset() (*asset, error) { 89 | path := "/home/ts/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/test.asset" 90 | name := "in/test.asset" 91 | bytes, err := bindataRead(path, name) 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | fi, err := os.Stat(path) 97 | if err != nil { 98 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 99 | } 100 | 101 | a := &asset{bytes: bytes, info: fi} 102 | return a, err 103 | } 104 | 105 | // Asset loads and returns the asset for the given name. 106 | // It returns an error if the asset could not be found or 107 | // could not be loaded. 108 | func Asset(name string) ([]byte, error) { 109 | cannonicalName := strings.Replace(name, "\\", "/", -1) 110 | if f, ok := _bindata[cannonicalName]; ok { 111 | a, err := f() 112 | if err != nil { 113 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 114 | } 115 | return a.bytes, nil 116 | } 117 | return nil, fmt.Errorf("Asset %s not found", name) 118 | } 119 | 120 | // MustAsset is like Asset but panics when Asset would return an error. 121 | // It simplifies safe initialization of global variables. 122 | func MustAsset(name string) []byte { 123 | a, err := Asset(name) 124 | if err != nil { 125 | panic("asset: Asset(" + name + "): " + err.Error()) 126 | } 127 | 128 | return a 129 | } 130 | 131 | // AssetInfo loads and returns the asset info for the given name. 132 | // It returns an error if the asset could not be found or 133 | // could not be loaded. 134 | func AssetInfo(name string) (os.FileInfo, error) { 135 | cannonicalName := strings.Replace(name, "\\", "/", -1) 136 | if f, ok := _bindata[cannonicalName]; ok { 137 | a, err := f() 138 | if err != nil { 139 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 140 | } 141 | return a.info, nil 142 | } 143 | return nil, fmt.Errorf("AssetInfo %s not found", name) 144 | } 145 | 146 | // AssetNames returns the names of the assets. 147 | func AssetNames() []string { 148 | names := make([]string, 0, len(_bindata)) 149 | for name := range _bindata { 150 | names = append(names, name) 151 | } 152 | return names 153 | } 154 | 155 | // _bindata is a table, holding each asset generator, mapped to its name. 156 | var _bindata = map[string]func() (*asset, error){ 157 | "in/a/test.asset": inATestAsset, 158 | "in/b/test.asset": inBTestAsset, 159 | "in/c/test.asset": inCTestAsset, 160 | "in/test.asset": inTestAsset, 161 | } 162 | 163 | // AssetDir returns the file names below a certain 164 | // directory embedded in the file by go-bindata. 165 | // For example if you run go-bindata on data/... and data contains the 166 | // following hierarchy: 167 | // data/ 168 | // foo.txt 169 | // img/ 170 | // a.png 171 | // b.png 172 | // then AssetDir("data") would return []string{"foo.txt", "img"} 173 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 174 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 175 | // AssetDir("") will return []string{"data"}. 176 | func AssetDir(name string) ([]string, error) { 177 | node := _bintree 178 | if len(name) != 0 { 179 | cannonicalName := strings.Replace(name, "\\", "/", -1) 180 | pathList := strings.Split(cannonicalName, "/") 181 | for _, p := range pathList { 182 | node = node.Children[p] 183 | if node == nil { 184 | return nil, fmt.Errorf("Asset %s not found", name) 185 | } 186 | } 187 | } 188 | if node.Func != nil { 189 | return nil, fmt.Errorf("Asset %s not found", name) 190 | } 191 | rv := make([]string, 0, len(node.Children)) 192 | for childName := range node.Children { 193 | rv = append(rv, childName) 194 | } 195 | return rv, nil 196 | } 197 | 198 | type bintree struct { 199 | Func func() (*asset, error) 200 | Children map[string]*bintree 201 | } 202 | var _bintree = &bintree{nil, map[string]*bintree{ 203 | "in": &bintree{nil, map[string]*bintree{ 204 | "a": &bintree{nil, map[string]*bintree{ 205 | "test.asset": &bintree{inATestAsset, map[string]*bintree{}}, 206 | }}, 207 | "b": &bintree{nil, map[string]*bintree{ 208 | "test.asset": &bintree{inBTestAsset, map[string]*bintree{}}, 209 | }}, 210 | "c": &bintree{nil, map[string]*bintree{ 211 | "test.asset": &bintree{inCTestAsset, map[string]*bintree{}}, 212 | }}, 213 | "test.asset": &bintree{inTestAsset, map[string]*bintree{}}, 214 | }}, 215 | }} 216 | 217 | // RestoreAsset restores an asset under the given directory 218 | func RestoreAsset(dir, name string) error { 219 | data, err := Asset(name) 220 | if err != nil { 221 | return err 222 | } 223 | info, err := AssetInfo(name) 224 | if err != nil { 225 | return err 226 | } 227 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 228 | if err != nil { 229 | return err 230 | } 231 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 232 | if err != nil { 233 | return err 234 | } 235 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 236 | if err != nil { 237 | return err 238 | } 239 | return nil 240 | } 241 | 242 | // RestoreAssets restores an asset under the given directory recursively 243 | func RestoreAssets(dir, name string) error { 244 | children, err := AssetDir(name) 245 | // File 246 | if err != nil { 247 | return RestoreAsset(dir, name) 248 | } 249 | // Dir 250 | for _, child := range children { 251 | err = RestoreAssets(dir, filepath.Join(name, child)) 252 | if err != nil { 253 | return err 254 | } 255 | } 256 | return nil 257 | } 258 | 259 | func _filePath(dir, name string) string { 260 | cannonicalName := strings.Replace(name, "\\", "/", -1) 261 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 262 | } 263 | 264 | -------------------------------------------------------------------------------- /testdata/out/debug.go-bindata: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "strings" 7 | "os" 8 | "path" 9 | "path/filepath" 10 | ) 11 | 12 | // bindata_read reads the given file from disk. It returns an error on failure. 13 | func bindata_read(path, name string) ([]byte, error) { 14 | buf, err := ioutil.ReadFile(path) 15 | if err != nil { 16 | err = fmt.Errorf("Error reading asset %s at %s: %v", name, path, err) 17 | } 18 | return buf, err 19 | } 20 | 21 | type asset struct { 22 | bytes []byte 23 | info os.FileInfo 24 | } 25 | 26 | // in_a_test_asset reads file data from disk. It returns an error on failure. 27 | func in_a_test_asset() (*asset, error) { 28 | path := "/Users/tamird/src/go/src/github.com/jteeuwen/go-bindata/testdata/in/a/test.asset" 29 | name := "in/a/test.asset" 30 | bytes, err := bindata_read(path, name) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | fi, err := os.Stat(path) 36 | if err != nil { 37 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 38 | } 39 | 40 | a := &asset{bytes: bytes, info: fi} 41 | return a, err 42 | } 43 | 44 | // in_b_test_asset reads file data from disk. It returns an error on failure. 45 | func in_b_test_asset() (*asset, error) { 46 | path := "/Users/tamird/src/go/src/github.com/jteeuwen/go-bindata/testdata/in/b/test.asset" 47 | name := "in/b/test.asset" 48 | bytes, err := bindata_read(path, name) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | fi, err := os.Stat(path) 54 | if err != nil { 55 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 56 | } 57 | 58 | a := &asset{bytes: bytes, info: fi} 59 | return a, err 60 | } 61 | 62 | // in_c_test_asset reads file data from disk. It returns an error on failure. 63 | func in_c_test_asset() (*asset, error) { 64 | path := "/Users/tamird/src/go/src/github.com/jteeuwen/go-bindata/testdata/in/c/test.asset" 65 | name := "in/c/test.asset" 66 | bytes, err := bindata_read(path, name) 67 | if err != nil { 68 | return nil, err 69 | } 70 | 71 | fi, err := os.Stat(path) 72 | if err != nil { 73 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 74 | } 75 | 76 | a := &asset{bytes: bytes, info: fi} 77 | return a, err 78 | } 79 | 80 | // in_test_asset reads file data from disk. It returns an error on failure. 81 | func in_test_asset() (*asset, error) { 82 | path := "/Users/tamird/src/go/src/github.com/jteeuwen/go-bindata/testdata/in/test.asset" 83 | name := "in/test.asset" 84 | bytes, err := bindata_read(path, name) 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | fi, err := os.Stat(path) 90 | if err != nil { 91 | err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) 92 | } 93 | 94 | a := &asset{bytes: bytes, info: fi} 95 | return a, err 96 | } 97 | 98 | // Asset loads and returns the asset for the given name. 99 | // It returns an error if the asset could not be found or 100 | // could not be loaded. 101 | func Asset(name string) ([]byte, error) { 102 | cannonicalName := strings.Replace(name, "\\", "/", -1) 103 | if f, ok := _bindata[cannonicalName]; ok { 104 | a, err := f() 105 | if err != nil { 106 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 107 | } 108 | return a.bytes, nil 109 | } 110 | return nil, fmt.Errorf("Asset %s not found", name) 111 | } 112 | 113 | // MustAsset is like Asset but panics when Asset would return an error. 114 | // It simplifies safe initialization of global variables. 115 | func MustAsset(name string) []byte { 116 | a, err := Asset(name) 117 | if (err != nil) { 118 | panic("asset: Asset(" + name + "): " + err.Error()) 119 | } 120 | 121 | return a 122 | } 123 | 124 | // AssetInfo loads and returns the asset info for the given name. 125 | // It returns an error if the asset could not be found or 126 | // could not be loaded. 127 | func AssetInfo(name string) (os.FileInfo, error) { 128 | cannonicalName := strings.Replace(name, "\\", "/", -1) 129 | if f, ok := _bindata[cannonicalName]; ok { 130 | a, err := f() 131 | if err != nil { 132 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 133 | } 134 | return a.info, nil 135 | } 136 | return nil, fmt.Errorf("AssetInfo %s not found", name) 137 | } 138 | 139 | // AssetNames returns the names of the assets. 140 | func AssetNames() []string { 141 | names := make([]string, 0, len(_bindata)) 142 | for name := range _bindata { 143 | names = append(names, name) 144 | } 145 | return names 146 | } 147 | 148 | // _bindata is a table, holding each asset generator, mapped to its name. 149 | var _bindata = map[string]func() (*asset, error){ 150 | "in/a/test.asset": in_a_test_asset, 151 | "in/b/test.asset": in_b_test_asset, 152 | "in/c/test.asset": in_c_test_asset, 153 | "in/test.asset": in_test_asset, 154 | } 155 | 156 | // AssetDir returns the file names below a certain 157 | // directory embedded in the file by go-bindata. 158 | // For example if you run go-bindata on data/... and data contains the 159 | // following hierarchy: 160 | // data/ 161 | // foo.txt 162 | // img/ 163 | // a.png 164 | // b.png 165 | // then AssetDir("data") would return []string{"foo.txt", "img"} 166 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 167 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 168 | // AssetDir("") will return []string{"data"}. 169 | func AssetDir(name string) ([]string, error) { 170 | node := _bintree 171 | if len(name) != 0 { 172 | cannonicalName := strings.Replace(name, "\\", "/", -1) 173 | pathList := strings.Split(cannonicalName, "/") 174 | for _, p := range pathList { 175 | node = node.Children[p] 176 | if node == nil { 177 | return nil, fmt.Errorf("Asset %s not found", name) 178 | } 179 | } 180 | } 181 | if node.Func != nil { 182 | return nil, fmt.Errorf("Asset %s not found", name) 183 | } 184 | rv := make([]string, 0, len(node.Children)) 185 | for name := range node.Children { 186 | rv = append(rv, name) 187 | } 188 | return rv, nil 189 | } 190 | 191 | type _bintree_t struct { 192 | Func func() (*asset, error) 193 | Children map[string]*_bintree_t 194 | } 195 | var _bintree = &_bintree_t{nil, map[string]*_bintree_t{ 196 | "in": &_bintree_t{nil, map[string]*_bintree_t{ 197 | "a": &_bintree_t{nil, map[string]*_bintree_t{ 198 | "test.asset": &_bintree_t{in_a_test_asset, map[string]*_bintree_t{ 199 | }}, 200 | }}, 201 | "b": &_bintree_t{nil, map[string]*_bintree_t{ 202 | "test.asset": &_bintree_t{in_b_test_asset, map[string]*_bintree_t{ 203 | }}, 204 | }}, 205 | "c": &_bintree_t{nil, map[string]*_bintree_t{ 206 | "test.asset": &_bintree_t{in_c_test_asset, map[string]*_bintree_t{ 207 | }}, 208 | }}, 209 | "test.asset": &_bintree_t{in_test_asset, map[string]*_bintree_t{ 210 | }}, 211 | }}, 212 | }} 213 | 214 | // Restore an asset under the given directory 215 | func RestoreAsset(dir, name string) error { 216 | data, err := Asset(name) 217 | if err != nil { 218 | return err 219 | } 220 | info, err := AssetInfo(name) 221 | if err != nil { 222 | return err 223 | } 224 | err = os.MkdirAll(_filePath(dir, path.Dir(name)), os.FileMode(0755)) 225 | if err != nil { 226 | return err 227 | } 228 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 229 | if err != nil { 230 | return err 231 | } 232 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 233 | if err != nil { 234 | return err 235 | } 236 | return nil 237 | } 238 | 239 | // Restore assets under the given directory recursively 240 | func RestoreAssets(dir, name string) error { 241 | children, err := AssetDir(name) 242 | if err != nil { // File 243 | return RestoreAsset(dir, name) 244 | } else { // Dir 245 | for _, child := range children { 246 | err = RestoreAssets(dir, path.Join(name, child)) 247 | if err != nil { 248 | return err 249 | } 250 | } 251 | } 252 | return nil 253 | } 254 | 255 | func _filePath(dir, name string) string { 256 | cannonicalName := strings.Replace(name, "\\", "/", -1) 257 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 258 | } 259 | 260 | -------------------------------------------------------------------------------- /testdata/out/nocompress-memcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // in/a/test.asset 4 | // in/b/test.asset 5 | // in/c/test.asset 6 | // in/test.asset 7 | // DO NOT EDIT! 8 | 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | "io/ioutil" 14 | "os" 15 | "path/filepath" 16 | "strings" 17 | "time" 18 | ) 19 | type asset struct { 20 | bytes []byte 21 | info os.FileInfo 22 | } 23 | 24 | type bindataFileInfo struct { 25 | name string 26 | size int64 27 | mode os.FileMode 28 | modTime time.Time 29 | } 30 | 31 | func (fi bindataFileInfo) Name() string { 32 | return fi.name 33 | } 34 | func (fi bindataFileInfo) Size() int64 { 35 | return fi.size 36 | } 37 | func (fi bindataFileInfo) Mode() os.FileMode { 38 | return fi.mode 39 | } 40 | func (fi bindataFileInfo) ModTime() time.Time { 41 | return fi.modTime 42 | } 43 | func (fi bindataFileInfo) IsDir() bool { 44 | return false 45 | } 46 | func (fi bindataFileInfo) Sys() interface{} { 47 | return nil 48 | } 49 | 50 | var _inATestAsset = []byte(`// sample file 51 | `) 52 | 53 | func inATestAssetBytes() ([]byte, error) { 54 | return _inATestAsset, nil 55 | } 56 | 57 | func inATestAsset() (*asset, error) { 58 | bytes, err := inATestAssetBytes() 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | info := bindataFileInfo{name: "in/a/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 64 | a := &asset{bytes: bytes, info: info} 65 | return a, nil 66 | } 67 | 68 | var _inBTestAsset = []byte(`// sample file 69 | `) 70 | 71 | func inBTestAssetBytes() ([]byte, error) { 72 | return _inBTestAsset, nil 73 | } 74 | 75 | func inBTestAsset() (*asset, error) { 76 | bytes, err := inBTestAssetBytes() 77 | if err != nil { 78 | return nil, err 79 | } 80 | 81 | info := bindataFileInfo{name: "in/b/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 82 | a := &asset{bytes: bytes, info: info} 83 | return a, nil 84 | } 85 | 86 | var _inCTestAsset = []byte(`// sample file 87 | `) 88 | 89 | func inCTestAssetBytes() ([]byte, error) { 90 | return _inCTestAsset, nil 91 | } 92 | 93 | func inCTestAsset() (*asset, error) { 94 | bytes, err := inCTestAssetBytes() 95 | if err != nil { 96 | return nil, err 97 | } 98 | 99 | info := bindataFileInfo{name: "in/c/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 100 | a := &asset{bytes: bytes, info: info} 101 | return a, nil 102 | } 103 | 104 | var _inTestAsset = []byte(`// sample file 105 | `) 106 | 107 | func inTestAssetBytes() ([]byte, error) { 108 | return _inTestAsset, nil 109 | } 110 | 111 | func inTestAsset() (*asset, error) { 112 | bytes, err := inTestAssetBytes() 113 | if err != nil { 114 | return nil, err 115 | } 116 | 117 | info := bindataFileInfo{name: "in/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 118 | a := &asset{bytes: bytes, info: info} 119 | return a, nil 120 | } 121 | 122 | // Asset loads and returns the asset for the given name. 123 | // It returns an error if the asset could not be found or 124 | // could not be loaded. 125 | func Asset(name string) ([]byte, error) { 126 | cannonicalName := strings.Replace(name, "\\", "/", -1) 127 | if f, ok := _bindata[cannonicalName]; ok { 128 | a, err := f() 129 | if err != nil { 130 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 131 | } 132 | return a.bytes, nil 133 | } 134 | return nil, fmt.Errorf("Asset %s not found", name) 135 | } 136 | 137 | // MustAsset is like Asset but panics when Asset would return an error. 138 | // It simplifies safe initialization of global variables. 139 | func MustAsset(name string) []byte { 140 | a, err := Asset(name) 141 | if err != nil { 142 | panic("asset: Asset(" + name + "): " + err.Error()) 143 | } 144 | 145 | return a 146 | } 147 | 148 | // AssetInfo loads and returns the asset info for the given name. 149 | // It returns an error if the asset could not be found or 150 | // could not be loaded. 151 | func AssetInfo(name string) (os.FileInfo, error) { 152 | cannonicalName := strings.Replace(name, "\\", "/", -1) 153 | if f, ok := _bindata[cannonicalName]; ok { 154 | a, err := f() 155 | if err != nil { 156 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 157 | } 158 | return a.info, nil 159 | } 160 | return nil, fmt.Errorf("AssetInfo %s not found", name) 161 | } 162 | 163 | // AssetNames returns the names of the assets. 164 | func AssetNames() []string { 165 | names := make([]string, 0, len(_bindata)) 166 | for name := range _bindata { 167 | names = append(names, name) 168 | } 169 | return names 170 | } 171 | 172 | // _bindata is a table, holding each asset generator, mapped to its name. 173 | var _bindata = map[string]func() (*asset, error){ 174 | "in/a/test.asset": inATestAsset, 175 | "in/b/test.asset": inBTestAsset, 176 | "in/c/test.asset": inCTestAsset, 177 | "in/test.asset": inTestAsset, 178 | } 179 | 180 | // AssetDir returns the file names below a certain 181 | // directory embedded in the file by go-bindata. 182 | // For example if you run go-bindata on data/... and data contains the 183 | // following hierarchy: 184 | // data/ 185 | // foo.txt 186 | // img/ 187 | // a.png 188 | // b.png 189 | // then AssetDir("data") would return []string{"foo.txt", "img"} 190 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 191 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 192 | // AssetDir("") will return []string{"data"}. 193 | func AssetDir(name string) ([]string, error) { 194 | node := _bintree 195 | if len(name) != 0 { 196 | cannonicalName := strings.Replace(name, "\\", "/", -1) 197 | pathList := strings.Split(cannonicalName, "/") 198 | for _, p := range pathList { 199 | node = node.Children[p] 200 | if node == nil { 201 | return nil, fmt.Errorf("Asset %s not found", name) 202 | } 203 | } 204 | } 205 | if node.Func != nil { 206 | return nil, fmt.Errorf("Asset %s not found", name) 207 | } 208 | rv := make([]string, 0, len(node.Children)) 209 | for childName := range node.Children { 210 | rv = append(rv, childName) 211 | } 212 | return rv, nil 213 | } 214 | 215 | type bintree struct { 216 | Func func() (*asset, error) 217 | Children map[string]*bintree 218 | } 219 | var _bintree = &bintree{nil, map[string]*bintree{ 220 | "in": &bintree{nil, map[string]*bintree{ 221 | "a": &bintree{nil, map[string]*bintree{ 222 | "test.asset": &bintree{inATestAsset, map[string]*bintree{}}, 223 | }}, 224 | "b": &bintree{nil, map[string]*bintree{ 225 | "test.asset": &bintree{inBTestAsset, map[string]*bintree{}}, 226 | }}, 227 | "c": &bintree{nil, map[string]*bintree{ 228 | "test.asset": &bintree{inCTestAsset, map[string]*bintree{}}, 229 | }}, 230 | "test.asset": &bintree{inTestAsset, map[string]*bintree{}}, 231 | }}, 232 | }} 233 | 234 | // RestoreAsset restores an asset under the given directory 235 | func RestoreAsset(dir, name string) error { 236 | data, err := Asset(name) 237 | if err != nil { 238 | return err 239 | } 240 | info, err := AssetInfo(name) 241 | if err != nil { 242 | return err 243 | } 244 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 245 | if err != nil { 246 | return err 247 | } 248 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 249 | if err != nil { 250 | return err 251 | } 252 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 253 | if err != nil { 254 | return err 255 | } 256 | return nil 257 | } 258 | 259 | // RestoreAssets restores an asset under the given directory recursively 260 | func RestoreAssets(dir, name string) error { 261 | children, err := AssetDir(name) 262 | // File 263 | if err != nil { 264 | return RestoreAsset(dir, name) 265 | } 266 | // Dir 267 | for _, child := range children { 268 | err = RestoreAssets(dir, filepath.Join(name, child)) 269 | if err != nil { 270 | return err 271 | } 272 | } 273 | return nil 274 | } 275 | 276 | func _filePath(dir, name string) string { 277 | cannonicalName := strings.Replace(name, "\\", "/", -1) 278 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 279 | } 280 | 281 | -------------------------------------------------------------------------------- /testdata/out/nocompress-nomemcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // in/a/test.asset 4 | // in/b/test.asset 5 | // in/c/test.asset 6 | // in/test.asset 7 | // DO NOT EDIT! 8 | 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | "io/ioutil" 14 | "os" 15 | "path/filepath" 16 | "reflect" 17 | "strings" 18 | "time" 19 | "unsafe" 20 | ) 21 | 22 | func bindataRead(data, name string) ([]byte, error) { 23 | var empty [0]byte 24 | sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) 25 | b := empty[:] 26 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 27 | bx.Data = sx.Data 28 | bx.Len = len(data) 29 | bx.Cap = bx.Len 30 | return b, nil 31 | } 32 | 33 | type asset struct { 34 | bytes []byte 35 | info os.FileInfo 36 | } 37 | 38 | type bindataFileInfo struct { 39 | name string 40 | size int64 41 | mode os.FileMode 42 | modTime time.Time 43 | } 44 | 45 | func (fi bindataFileInfo) Name() string { 46 | return fi.name 47 | } 48 | func (fi bindataFileInfo) Size() int64 { 49 | return fi.size 50 | } 51 | func (fi bindataFileInfo) Mode() os.FileMode { 52 | return fi.mode 53 | } 54 | func (fi bindataFileInfo) ModTime() time.Time { 55 | return fi.modTime 56 | } 57 | func (fi bindataFileInfo) IsDir() bool { 58 | return false 59 | } 60 | func (fi bindataFileInfo) Sys() interface{} { 61 | return nil 62 | } 63 | 64 | var _inATestAsset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" 65 | 66 | func inATestAssetBytes() ([]byte, error) { 67 | return bindataRead( 68 | _inATestAsset, 69 | "in/a/test.asset", 70 | ) 71 | } 72 | 73 | func inATestAsset() (*asset, error) { 74 | bytes, err := inATestAssetBytes() 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | info := bindataFileInfo{name: "in/a/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 80 | a := &asset{bytes: bytes, info: info} 81 | return a, nil 82 | } 83 | 84 | var _inBTestAsset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" 85 | 86 | func inBTestAssetBytes() ([]byte, error) { 87 | return bindataRead( 88 | _inBTestAsset, 89 | "in/b/test.asset", 90 | ) 91 | } 92 | 93 | func inBTestAsset() (*asset, error) { 94 | bytes, err := inBTestAssetBytes() 95 | if err != nil { 96 | return nil, err 97 | } 98 | 99 | info := bindataFileInfo{name: "in/b/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 100 | a := &asset{bytes: bytes, info: info} 101 | return a, nil 102 | } 103 | 104 | var _inCTestAsset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" 105 | 106 | func inCTestAssetBytes() ([]byte, error) { 107 | return bindataRead( 108 | _inCTestAsset, 109 | "in/c/test.asset", 110 | ) 111 | } 112 | 113 | func inCTestAsset() (*asset, error) { 114 | bytes, err := inCTestAssetBytes() 115 | if err != nil { 116 | return nil, err 117 | } 118 | 119 | info := bindataFileInfo{name: "in/c/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 120 | a := &asset{bytes: bytes, info: info} 121 | return a, nil 122 | } 123 | 124 | var _inTestAsset = "\x2f\x2f\x20\x73\x61\x6d\x70\x6c\x65\x20\x66\x69\x6c\x65\x0a" 125 | 126 | func inTestAssetBytes() ([]byte, error) { 127 | return bindataRead( 128 | _inTestAsset, 129 | "in/test.asset", 130 | ) 131 | } 132 | 133 | func inTestAsset() (*asset, error) { 134 | bytes, err := inTestAssetBytes() 135 | if err != nil { 136 | return nil, err 137 | } 138 | 139 | info := bindataFileInfo{name: "in/test.asset", size: 15, mode: os.FileMode(436), modTime: time.Unix(1445582844, 0)} 140 | a := &asset{bytes: bytes, info: info} 141 | return a, nil 142 | } 143 | 144 | // Asset loads and returns the asset for the given name. 145 | // It returns an error if the asset could not be found or 146 | // could not be loaded. 147 | func Asset(name string) ([]byte, error) { 148 | cannonicalName := strings.Replace(name, "\\", "/", -1) 149 | if f, ok := _bindata[cannonicalName]; ok { 150 | a, err := f() 151 | if err != nil { 152 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 153 | } 154 | return a.bytes, nil 155 | } 156 | return nil, fmt.Errorf("Asset %s not found", name) 157 | } 158 | 159 | // MustAsset is like Asset but panics when Asset would return an error. 160 | // It simplifies safe initialization of global variables. 161 | func MustAsset(name string) []byte { 162 | a, err := Asset(name) 163 | if err != nil { 164 | panic("asset: Asset(" + name + "): " + err.Error()) 165 | } 166 | 167 | return a 168 | } 169 | 170 | // AssetInfo loads and returns the asset info for the given name. 171 | // It returns an error if the asset could not be found or 172 | // could not be loaded. 173 | func AssetInfo(name string) (os.FileInfo, error) { 174 | cannonicalName := strings.Replace(name, "\\", "/", -1) 175 | if f, ok := _bindata[cannonicalName]; ok { 176 | a, err := f() 177 | if err != nil { 178 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 179 | } 180 | return a.info, nil 181 | } 182 | return nil, fmt.Errorf("AssetInfo %s not found", name) 183 | } 184 | 185 | // AssetNames returns the names of the assets. 186 | func AssetNames() []string { 187 | names := make([]string, 0, len(_bindata)) 188 | for name := range _bindata { 189 | names = append(names, name) 190 | } 191 | return names 192 | } 193 | 194 | // _bindata is a table, holding each asset generator, mapped to its name. 195 | var _bindata = map[string]func() (*asset, error){ 196 | "in/a/test.asset": inATestAsset, 197 | "in/b/test.asset": inBTestAsset, 198 | "in/c/test.asset": inCTestAsset, 199 | "in/test.asset": inTestAsset, 200 | } 201 | 202 | // AssetDir returns the file names below a certain 203 | // directory embedded in the file by go-bindata. 204 | // For example if you run go-bindata on data/... and data contains the 205 | // following hierarchy: 206 | // data/ 207 | // foo.txt 208 | // img/ 209 | // a.png 210 | // b.png 211 | // then AssetDir("data") would return []string{"foo.txt", "img"} 212 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 213 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 214 | // AssetDir("") will return []string{"data"}. 215 | func AssetDir(name string) ([]string, error) { 216 | node := _bintree 217 | if len(name) != 0 { 218 | cannonicalName := strings.Replace(name, "\\", "/", -1) 219 | pathList := strings.Split(cannonicalName, "/") 220 | for _, p := range pathList { 221 | node = node.Children[p] 222 | if node == nil { 223 | return nil, fmt.Errorf("Asset %s not found", name) 224 | } 225 | } 226 | } 227 | if node.Func != nil { 228 | return nil, fmt.Errorf("Asset %s not found", name) 229 | } 230 | rv := make([]string, 0, len(node.Children)) 231 | for childName := range node.Children { 232 | rv = append(rv, childName) 233 | } 234 | return rv, nil 235 | } 236 | 237 | type bintree struct { 238 | Func func() (*asset, error) 239 | Children map[string]*bintree 240 | } 241 | var _bintree = &bintree{nil, map[string]*bintree{ 242 | "in": &bintree{nil, map[string]*bintree{ 243 | "a": &bintree{nil, map[string]*bintree{ 244 | "test.asset": &bintree{inATestAsset, map[string]*bintree{}}, 245 | }}, 246 | "b": &bintree{nil, map[string]*bintree{ 247 | "test.asset": &bintree{inBTestAsset, map[string]*bintree{}}, 248 | }}, 249 | "c": &bintree{nil, map[string]*bintree{ 250 | "test.asset": &bintree{inCTestAsset, map[string]*bintree{}}, 251 | }}, 252 | "test.asset": &bintree{inTestAsset, map[string]*bintree{}}, 253 | }}, 254 | }} 255 | 256 | // RestoreAsset restores an asset under the given directory 257 | func RestoreAsset(dir, name string) error { 258 | data, err := Asset(name) 259 | if err != nil { 260 | return err 261 | } 262 | info, err := AssetInfo(name) 263 | if err != nil { 264 | return err 265 | } 266 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 267 | if err != nil { 268 | return err 269 | } 270 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 271 | if err != nil { 272 | return err 273 | } 274 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 275 | if err != nil { 276 | return err 277 | } 278 | return nil 279 | } 280 | 281 | // RestoreAssets restores an asset under the given directory recursively 282 | func RestoreAssets(dir, name string) error { 283 | children, err := AssetDir(name) 284 | // File 285 | if err != nil { 286 | return RestoreAsset(dir, name) 287 | } 288 | // Dir 289 | for _, child := range children { 290 | err = RestoreAssets(dir, filepath.Join(name, child)) 291 | if err != nil { 292 | return err 293 | } 294 | } 295 | return nil 296 | } 297 | 298 | func _filePath(dir, name string) string { 299 | cannonicalName := strings.Replace(name, "\\", "/", -1) 300 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 301 | } 302 | 303 | -------------------------------------------------------------------------------- /testdata/symlinkFile/file1: -------------------------------------------------------------------------------- 1 | ../symlinkSrc/file1 -------------------------------------------------------------------------------- /testdata/symlinkParent/symlinkTarget: -------------------------------------------------------------------------------- 1 | ../symlinkSrc/ -------------------------------------------------------------------------------- /testdata/symlinkRecursiveParent/file1: -------------------------------------------------------------------------------- 1 | // test file 1 2 | -------------------------------------------------------------------------------- /testdata/symlinkRecursiveParent/symlinkTarget: -------------------------------------------------------------------------------- 1 | ../symlinkRecursiveParent/ -------------------------------------------------------------------------------- /testdata/symlinkSrc/file1: -------------------------------------------------------------------------------- 1 | // symlink file 1 2 | -------------------------------------------------------------------------------- /testdata/symlinkSrc/file2: -------------------------------------------------------------------------------- 1 | // symlink file 2 2 | -------------------------------------------------------------------------------- /testdata/symlinkSrc/file3: -------------------------------------------------------------------------------- 1 | // symlink file 3 2 | -------------------------------------------------------------------------------- /testdata/symlinkSrc/file4: -------------------------------------------------------------------------------- 1 | // symlink file 4 2 | -------------------------------------------------------------------------------- /toc.go: -------------------------------------------------------------------------------- 1 | // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication 2 | // license. Its contents can be found at: 3 | // http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "sort" 11 | "strings" 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{%s, map[string]*bintree{", root.funcOrNil()) 57 | 58 | if len(root.Children) > 0 { 59 | io.WriteString(w, "\n") 60 | 61 | // Sort to make output stable between invocations 62 | filenames := make([]string, len(root.Children)) 63 | i := 0 64 | for filename, _ := range root.Children { 65 | filenames[i] = filename 66 | i++ 67 | } 68 | sort.Strings(filenames) 69 | 70 | for _, p := range filenames { 71 | ident(w, nident+1) 72 | fmt.Fprintf(w, `"%s": `, p) 73 | root.Children[p].writeGoMap(w, nident+1) 74 | } 75 | ident(w, nident) 76 | } 77 | 78 | io.WriteString(w, "}}") 79 | if nident > 0 { 80 | io.WriteString(w, ",") 81 | } 82 | io.WriteString(w, "\n") 83 | } 84 | 85 | func (root *assetTree) WriteAsGoMap(w io.Writer) error { 86 | _, err := fmt.Fprint(w, `type bintree struct { 87 | Func func() (*asset, error) 88 | Children map[string]*bintree 89 | } 90 | var _bintree = `) 91 | root.writeGoMap(w, 0) 92 | return err 93 | } 94 | 95 | func writeTOCTree(w io.Writer, toc []Asset) error { 96 | _, err := fmt.Fprintf(w, `// AssetDir returns the file names below a certain 97 | // directory embedded in the file by go-bindata. 98 | // For example if you run go-bindata on data/... and data contains the 99 | // following hierarchy: 100 | // data/ 101 | // foo.txt 102 | // img/ 103 | // a.png 104 | // b.png 105 | // then AssetDir("data") would return []string{"foo.txt", "img"} 106 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 107 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 108 | // AssetDir("") will return []string{"data"}. 109 | func AssetDir(name string) ([]string, error) { 110 | node := _bintree 111 | if len(name) != 0 { 112 | cannonicalName := strings.Replace(name, "\\", "/", -1) 113 | pathList := strings.Split(cannonicalName, "/") 114 | for _, p := range pathList { 115 | node = node.Children[p] 116 | if node == nil { 117 | return nil, fmt.Errorf("Asset %%s not found", name) 118 | } 119 | } 120 | } 121 | if node.Func != nil { 122 | return nil, fmt.Errorf("Asset %%s not found", name) 123 | } 124 | rv := make([]string, 0, len(node.Children)) 125 | for childName := range node.Children { 126 | rv = append(rv, childName) 127 | } 128 | return rv, nil 129 | } 130 | 131 | `) 132 | if err != nil { 133 | return err 134 | } 135 | tree := newAssetTree() 136 | for i := range toc { 137 | pathList := strings.Split(toc[i].Name, "/") 138 | tree.Add(pathList, toc[i]) 139 | } 140 | return tree.WriteAsGoMap(w) 141 | } 142 | 143 | // writeTOC writes the table of contents file. 144 | func writeTOC(w io.Writer, toc []Asset) error { 145 | err := writeTOCHeader(w) 146 | if err != nil { 147 | return err 148 | } 149 | 150 | for i := range toc { 151 | err = writeTOCAsset(w, &toc[i]) 152 | if err != nil { 153 | return err 154 | } 155 | } 156 | 157 | return writeTOCFooter(w) 158 | } 159 | 160 | // writeTOCHeader writes the table of contents file header. 161 | func writeTOCHeader(w io.Writer) error { 162 | _, err := fmt.Fprintf(w, `// Asset loads and returns the asset for the given name. 163 | // It returns an error if the asset could not be found or 164 | // could not be loaded. 165 | func Asset(name string) ([]byte, error) { 166 | cannonicalName := strings.Replace(name, "\\", "/", -1) 167 | if f, ok := _bindata[cannonicalName]; ok { 168 | a, err := f() 169 | if err != nil { 170 | return nil, fmt.Errorf("Asset %%s can't read by error: %%v", name, err) 171 | } 172 | return a.bytes, nil 173 | } 174 | return nil, fmt.Errorf("Asset %%s not found", name) 175 | } 176 | 177 | // MustAsset is like Asset but panics when Asset would return an error. 178 | // It simplifies safe initialization of global variables. 179 | func MustAsset(name string) []byte { 180 | a, err := Asset(name) 181 | if err != nil { 182 | panic("asset: Asset(" + name + "): " + err.Error()) 183 | } 184 | 185 | return a 186 | } 187 | 188 | // AssetInfo loads and returns the asset info for the given name. 189 | // It returns an error if the asset could not be found or 190 | // could not be loaded. 191 | func AssetInfo(name string) (os.FileInfo, error) { 192 | cannonicalName := strings.Replace(name, "\\", "/", -1) 193 | if f, ok := _bindata[cannonicalName]; ok { 194 | a, err := f() 195 | if err != nil { 196 | return nil, fmt.Errorf("AssetInfo %%s can't read by error: %%v", name, err) 197 | } 198 | return a.info, nil 199 | } 200 | return nil, fmt.Errorf("AssetInfo %%s not found", name) 201 | } 202 | 203 | // AssetNames returns the names of the assets. 204 | func AssetNames() []string { 205 | names := make([]string, 0, len(_bindata)) 206 | for name := range _bindata { 207 | names = append(names, name) 208 | } 209 | return names 210 | } 211 | 212 | // _bindata is a table, holding each asset generator, mapped to its name. 213 | var _bindata = map[string]func() (*asset, error){ 214 | `) 215 | return err 216 | } 217 | 218 | // writeTOCAsset write a TOC entry for the given asset. 219 | func writeTOCAsset(w io.Writer, asset *Asset) error { 220 | _, err := fmt.Fprintf(w, "\t%q: %s,\n", asset.Name, asset.Func) 221 | return err 222 | } 223 | 224 | // writeTOCFooter writes the table of contents file footer. 225 | func writeTOCFooter(w io.Writer) error { 226 | _, err := fmt.Fprintf(w, `} 227 | 228 | `) 229 | return err 230 | } 231 | --------------------------------------------------------------------------------