├── 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 |
--------------------------------------------------------------------------------