├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .mailmap ├── AUTHORS.txt ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── asset.go ├── benchmark_test.go ├── bits.go ├── bytewriter.go ├── config.go ├── convert.go ├── convert_test.go ├── debug.go ├── doc.go ├── filewriter.go ├── go-bindata ├── AppendSliceValue.go ├── main.go └── version.go ├── go.mod ├── release.go ├── release_go112.go ├── release_go113.go ├── release_test.go ├── restore.go ├── safefile.go ├── safefile_test.go ├── stringwriter.go ├── testdata ├── Makefile ├── assets │ └── bindata.go ├── benchmark │ ├── 0.jpg │ ├── 1.jpg │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 13.jpg │ ├── 14.jpg │ ├── 15.jpg │ ├── 16.jpg │ ├── 17.jpg │ ├── 18.jpg │ ├── 19.jpg │ ├── 2.jpg │ ├── 20.jpg │ ├── 21.jpg │ ├── 22.jpg │ ├── 23.jpg │ ├── 24.jpg │ ├── 25.jpg │ ├── 26.jpg │ ├── 27.jpg │ ├── 28.jpg │ ├── 29.jpg │ ├── 3.jpg │ ├── 30.jpg │ ├── 31.jpg │ ├── 32.jpg │ ├── 33.jpg │ ├── 34.jpg │ ├── 35.jpg │ ├── 36.jpg │ ├── 37.jpg │ ├── 38.jpg │ ├── 39.jpg │ ├── 4.jpg │ ├── 40.jpg │ ├── 41.jpg │ ├── 42.jpg │ ├── 43.jpg │ ├── 44.jpg │ ├── 45.jpg │ ├── 46.jpg │ ├── 47.jpg │ ├── 48.jpg │ ├── 49.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ └── 9.jpg ├── download-photos.sh ├── dupname │ ├── foo │ │ └── bar │ └── foo_bar ├── empty │ └── empty_file ├── fa.js ├── in │ ├── a │ │ └── test.asset │ ├── b │ │ └── test.asset │ ├── c │ │ └── test.asset │ └── test.asset ├── out │ ├── compress-memcopy.go │ ├── compress-nomemcopy.go │ ├── debug.go │ ├── nocompress-memcopy.go │ ├── nocompress-nomemcopy.go │ └── prefix.go ├── symlinkFile │ └── file1 ├── symlinkParent │ └── symlinkTarget ├── symlinkRecursiveParent │ ├── file1 │ └── symlinkTarget └── symlinkSrc │ ├── file1 │ ├── file2 │ ├── file3 │ └── file4 └── toc.go /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Test 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | go-version: [1.19.x, 1.20.x] 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Install Go 11 | uses: actions/setup-go@v3 12 | with: 13 | go-version: ${{ matrix.go-version }} 14 | - uses: actions/checkout@v3 15 | with: 16 | path: './src/github.com/kevinburke/go-bindata' 17 | - uses: actions/cache@v3 18 | with: 19 | path: /home/runner/.cache 20 | key: ${{ runner.os }}-go-v3-${{ hashFiles('**/*.go') }} 21 | restore-keys: | 22 | ${{ runner.os }}-go-v3- 23 | # staticcheck needs this for GOPATH 24 | - run: | 25 | echo "GO111MODULE=off" >> $GITHUB_ENV 26 | echo "GOPATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV 27 | echo "PATH=$GITHUB_WORKSPACE/bin:$PATH" >> $GITHUB_ENV 28 | echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV 29 | - name: Download dependencies 30 | run: go get -t -v ./... 31 | working-directory: './src/github.com/kevinburke/go-bindata' 32 | - name: Run tests 33 | run: rm -f ${GOPATH}/bin/go-bindata && make ci 34 | working-directory: './src/github.com/kevinburke/go-bindata' 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /releases 2 | 3 | # unformatted.out is any large Go source file generated by go-bindata. 4 | /testdata/unformatted.out 5 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Pierre Baillet Pierre Baillet 2 | Jordan Liggitt Jordan Liggitt 3 | Keiji Yoshida 4 | Jim Teeuwen 5 | Craig Landry 6 | Kenta Oda 7 | Kevin Burke Kevin Burke 8 | -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | Aaron Schlesinger 2 | Alan Shreve 3 | Anand Gaitonde and Michael Maximilien 4 | Andrew Bates 5 | Beyang Liu 6 | Brandon Mulcahy 7 | Chris McBride 8 | Craig Landry 9 | Damien Nozay 10 | David Chase 11 | Dimitri Sokolyuk 12 | Dmitri Shuralyov 13 | Elazar Leibovich 14 | Elias Naur 15 | Emad Elsaid 16 | Ian Kent 17 | Jens Breitbart 18 | Jessica Forrester 19 | Jim Teeuwen 20 | Johan Brandhorst 21 | Jordan Liggitt 22 | Joseph Hager 23 | Keegan Carruthers-Smith 24 | Keiji Yoshida 25 | Kenta Oda 26 | Kevin Burke 27 | Liam Bowen 28 | Matt Dee 29 | Maxim Ignatenko 30 | MinJae Kwon 31 | Paweł Błaszczyk 32 | Pierre Baillet 33 | Ruben Vermeersch 34 | Russ Cox 35 | Ryosuke IWANAGA 36 | SATO taichi 37 | Sebastian Thiel 38 | Serhan Şen 39 | Stephen Searles 40 | Tamir Duberstein 41 | Tobias Schmidt 42 | Tobias Schottdorf 43 | Yasuhiro Matsumoto 44 | chenrui 45 | ikawaha 46 | opennota 47 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v4 2 | 3 | This is meant to satisfy go module versioning behavior; see 4 | https://stackoverflow.com/a/52058348/329700 for more. 5 | 6 | ## 3.24.0 7 | 8 | Remove uses of io/ioutil; you must use Go 1.18 or higher with this version of 9 | go-bindata and its generated asset files. 10 | 11 | Update generated doc comments for compatibility with Go's updated doc comment 12 | guidelines. 13 | 14 | ## 3.21.0 15 | 16 | Replace "Debug" with "AssetDebug" to reduce the likelihood of conflicts. 17 | 18 | ## 3.20.0 19 | 20 | Add the "Debug" constant if assets have been generated using the `--debug` flag 21 | at the command line. 22 | -------------------------------------------------------------------------------- /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 | ## Bug reports 8 | 9 | When supplying a bug report, please consider the following guidelines. 10 | These serve to make it easier for us to address the issue and find a solution. 11 | Most of these are pretty self-evident, but sometimes it is still necessary 12 | to reiterate them. 13 | 14 | * Be clear in the way you express the problem. Use simple language and 15 | just enough of it to clearly define the issue. Not everyone is a native 16 | English speaker. And while most can handle themselves pretty well, 17 | it helps to stay away from more esoteric vocabulary. 18 | 19 | Be patient with non-native English speakers. If their bug reports 20 | or comments are hard to understand, just ask for clarification. 21 | Do not start guessing at their meaning, as this may just lead to 22 | more confusion and misunderstandings. 23 | * Clearly define any information which is relevant to the problem. 24 | This includes library versions, operating system and any other 25 | external dependencies which may be needed. 26 | * Where applicable, provide a step-by-step listing of the way to 27 | reproduce the problem. Make sure this is the simplest possible 28 | way to do so. Omit any and all unneccesary steps, because they may 29 | just complicate our understanding of the real problem. 30 | If need be, create a whole new code project on your local machine, 31 | which specifically tries to create the problem you are running into; 32 | nothing more, nothing less. 33 | 34 | Include this program in the bug report. It often suffices to paste 35 | the code in a [Gist](https://gist.github.com) or on the 36 | [Go playground](http://play.golang.org). 37 | * If possible, provide us with a listing of the steps you have already 38 | undertaken to solve the problem. This can save us a great deal of 39 | wasted time, trying out solutions you have already covered. 40 | 41 | ## Pull requests 42 | 43 | Bug reports are great. Supplying fixes to bugs is even better. 44 | When submitting a pull request, the following guidelines are 45 | good to keep in mind: 46 | 47 | * `go fmt`: **Always** run your code through `go fmt`, before 48 | committing it. Code has to be readable by many different 49 | people. And the only way this will be as painless as possible, 50 | is if we all stick to the same code style. 51 | 52 | Some of our projects may have automated build-servers hooked up 53 | to commit hooks. These will vet any submitted code and determine 54 | if it meets a set of properties. One of which is code formatting. 55 | These servers will outright deny a submission which has not been 56 | run through `go fmt`, even if the code itself is correct. 57 | 58 | We try to maintain a zero-tolerance policy on this matter, 59 | because consistently formatted code makes life a great deal 60 | easier for everyone involved. 61 | 62 | * Commit log messages: When committing changes, do so often and 63 | clearly -- Even if you have changed only 1 character in a code 64 | comment. This means that commit log messages should clearly state 65 | exactly what the change does and why. If it fixes a known issue, 66 | then mention the issue number in the commit log. E.g.: 67 | 68 | > Fixes return value for `foo/boo.Baz()` to be consistent with 69 | > the rest of the API. This addresses issue #32 70 | 71 | Do not pile a lot of unrelated changes into a single commit. 72 | Pick and choose only those changes for a single commit, which are 73 | directly related. We would much rather see a hundred commits 74 | saying nothing but `"Runs go fmt"` in between any real fixes 75 | than have these style changes embedded in those real fixes. 76 | It creates a lot of noise when trying to review code. 77 | 78 | ## New releases 79 | 80 | 1) Manually update version.go with the new version number. ("git commit -m v3.25.0") 81 | 82 | 2) Commit the change. The commit message should be the version number. 83 | 84 | 3) Add a git tag and push to Github. You MUST push the tag to Github before 85 | creating a Github release. 86 | 87 | 4a) download github-release; go get github.com/github-release/github-release 88 | 4b) download differ; go get github.com/kevinburke/differ 89 | 90 | 4) Run GITHUB_TOKEN=mytoken make release version=my-git-tag 91 | -------------------------------------------------------------------------------- /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 | 4 | https://creativecommons.org/publicdomain/zero/1.0 5 | 6 | safefile.go and safefile_test.go are imported from github.com/dchest/safefile 7 | and contain local modifications. The license from that project is included here: 8 | 9 | Copyright (c) 2013 Dmitry Chestnykh 10 | All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions 14 | are met: 15 | 16 | * Redistributions of source code must retain the above copyright 17 | notice, this list of conditions and the following disclaimer. 18 | 19 | * Redistributions in binary form must reproduce the above 20 | copyright notice, this list of conditions and the following 21 | disclaimer in the documentation and/or other materials 22 | provided with the distribution. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/bash -o pipefail 2 | 3 | export PATH := $(PATH):/usr/local/meter/bin 4 | 5 | BENCHSTAT := $(GOPATH)/bin/benchstat 6 | RELEASE := $(GOPATH)/bin/github-release 7 | WRITE_MAILMAP := $(GOPATH)/bin/write_mailmap 8 | 9 | all: 10 | $(MAKE) -C testdata 11 | 12 | diff-testdata: 13 | differ $(MAKE) -C testdata 14 | differ go fmt ./testdata/out/... 15 | 16 | lint: 17 | go vet ./... 18 | staticcheck ./... 19 | 20 | go-test: 21 | go test ./... 22 | 23 | go-race-test: 24 | go test -race ./... 25 | 26 | test: go-test 27 | $(MAKE) -C testdata 28 | 29 | race-test: lint go-race-test 30 | $(MAKE) -C testdata 31 | 32 | $(GOPATH)/bin/go-bindata: 33 | go install -v ./... 34 | 35 | testdata/assets/bindata.go: 36 | go-bindata -o testdata/assets/bindata.go -pkg assets ./testdata/benchmark 37 | 38 | $(BENCHSTAT): 39 | go get golang.org/x/perf/cmd/benchstat 40 | 41 | bench: $(GOPATH)/bin/go-bindata | $(BENCHSTAT) 42 | go list ./... | grep -v vendor | xargs go test -benchtime=5s -bench=. -run='^$$' 2>&1 | $(BENCHSTAT) /dev/stdin 43 | 44 | $(WRITE_MAILMAP): 45 | go get -u github.com/kevinburke/write_mailmap 46 | 47 | force: ; 48 | 49 | AUTHORS.txt: force | $(WRITE_MAILMAP) 50 | $(WRITE_MAILMAP) > AUTHORS.txt 51 | 52 | authors: AUTHORS.txt 53 | 54 | ci-install: 55 | go get github.com/kevinburke/differ 56 | go get honnef.co/go/tools/cmd/staticcheck 57 | 58 | ci: ci-install lint go-race-test diff-testdata 59 | 60 | # Ensure you have updated go-bindata/version.go manually. 61 | release: | $(RELEASE) race-test diff-testdata 62 | ifndef version 63 | @echo "Please provide a version" 64 | exit 1 65 | endif 66 | ifndef GITHUB_TOKEN 67 | @echo "Please set GITHUB_TOKEN in the environment" 68 | exit 1 69 | endif 70 | # If you don't push these, Github creates a tagged release for you from the 71 | # wrong commit. 72 | git push origin master 73 | git push origin --tags 74 | mkdir -p releases/$(version) 75 | GOOS=linux GOARCH=amd64 go build -o releases/$(version)/go-bindata-linux-amd64 ./go-bindata 76 | GOOS=linux GOARCH=arm64 go build -o releases/$(version)/go-bindata-linux-arm64 ./go-bindata 77 | GOOS=darwin GOARCH=amd64 go build -o releases/$(version)/go-bindata-darwin-amd64 ./go-bindata 78 | GOOS=darwin GOARCH=arm64 go build -o releases/$(version)/go-bindata-darwin-arm64 ./go-bindata 79 | GOOS=windows GOARCH=amd64 go build -o releases/$(version)/go-bindata-windows-amd64 ./go-bindata 80 | # these commands are not idempotent so ignore failures if an upload repeats 81 | $(RELEASE) release --user kevinburke --repo go-bindata --tag $(version) || true 82 | $(RELEASE) upload --user kevinburke --repo go-bindata --tag $(version) --name go-bindata-linux-amd64 --file releases/$(version)/go-bindata-linux-amd64 || true 83 | $(RELEASE) upload --user kevinburke --repo go-bindata --tag $(version) --name go-bindata-linux-arm64 --file releases/$(version)/go-bindata-linux-arm64 || true 84 | $(RELEASE) upload --user kevinburke --repo go-bindata --tag $(version) --name go-bindata-darwin-amd64 --file releases/$(version)/go-bindata-darwin-amd64 || true 85 | $(RELEASE) upload --user kevinburke --repo go-bindata --tag $(version) --name go-bindata-darwin-arm64 --file releases/$(version)/go-bindata-darwin-arm64 || true 86 | $(RELEASE) upload --user kevinburke --repo go-bindata --tag $(version) --name go-bindata-windows-amd64 --file releases/$(version)/go-bindata-windows-amd64 || true 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## bindata 2 | 3 | *This fork is maintained by Kevin Burke, and is the version trusted by Homebrew. 4 | Changes made include:* 5 | 6 | - Atomic writes; generated file cannot be read while partially complete. 7 | 8 | - Better encoding of files that contain characters in the Unicode format range. 9 | 10 | - Generated file reports file sizes. 11 | 12 | - Generated code is run through go fmt. 13 | 14 | - SHA256 hashes are computed for all files and stored in the binary. You can 15 | use this to detect in-memory corruption and to provide easy cache-busting 16 | mechanisms. 17 | 18 | - Added AssetString and MustAssetString functions. 19 | 20 | - ByName is not public. 21 | 22 | - Some errors in file writes were unchecked, but are now checked. 23 | 24 | - File modes are stored in octal (0644) instead of nonsensical decimal (420) 25 | 26 | This package converts any file into manageable Go source code. Useful for 27 | embedding binary data into a go program. The file data is optionally gzip 28 | compressed before being converted to a raw byte slice. 29 | 30 | It comes with a command line tool in the `go-bindata` subdirectory. This tool 31 | offers a set of command line options, used to customize the output being 32 | generated. 33 | 34 | 35 | ### Installation 36 | 37 | On Macs, you can install the binary using [Homebrew](https://brew.sh): 38 | 39 | ``` 40 | brew install go-bindata 41 | ``` 42 | 43 | You can also download a binary from the [releases page][releases]. Switch in 44 | your GOOS for the word "linux" below, and the latest version for the version 45 | listed below: 46 | 47 | ``` 48 | curl --silent --location --output /usr/local/bin/go-bindata https://github.com/kevinburke/go-bindata/releases/download/v4.0.0/go-bindata-linux-amd64 49 | chmod 755 /usr/local/bin/go-bindata 50 | ``` 51 | 52 | Alternatively, if you have a working Go installation, you can build the source and install the executable into `$GOPATH/bin` or `$GOBIN`: 53 | 54 | ```shell 55 | go install github.com/kevinburke/go-bindata/v4/...@latest 56 | # for versions of Go < 1.11, or without module support, use: 57 | go install github.com/kevinburke/go-bindata/... 58 | ``` 59 | 60 | [releases]: https://github.com/kevinburke/go-bindata/releases 61 | 62 | ### Usage 63 | 64 | Conversion is done on one or more sets of files. They are all embedded in a new 65 | Go source file, along with a table of contents and an `Asset` function, 66 | which allows quick access to the asset, based on its name. 67 | 68 | The simplest invocation generates a `bindata.go` file in the current 69 | working directory. It includes all assets from the `data` directory. 70 | 71 | $ go-bindata data/ 72 | 73 | To include all input sub-directories recursively, use the ellipsis postfix 74 | as defined for Go import paths. Otherwise it will only consider assets in the 75 | input directory itself. 76 | 77 | $ go-bindata data/... 78 | 79 | To specify the name of the output file being generated, use the `-o` option: 80 | 81 | $ go-bindata -o myfile.go data/ 82 | 83 | Multiple input directories can be specified if necessary. 84 | 85 | $ go-bindata dir1/... /path/to/dir2/... dir3 86 | 87 | 88 | The following paragraphs detail some of the command line options which can be 89 | supplied to `go-bindata`. Refer to the `testdata/out` directory for various 90 | output examples from the assets in `testdata/in`. Each example uses different 91 | command line options. 92 | 93 | To ignore files, pass in regexes using -ignore, for example: 94 | 95 | $ go-bindata -ignore=\\.gitignore data/... 96 | 97 | ### Accessing an asset 98 | 99 | To access asset data, we use the `Asset(string) ([]byte, error)` function which 100 | is included in the generated output. 101 | 102 | data, err := Asset("pub/style/foo.css") 103 | if err != nil { 104 | // Asset was not found. 105 | } 106 | 107 | // use asset data 108 | 109 | 110 | ### Debug vs Release builds 111 | 112 | When invoking the program with the `-debug` flag, the generated code does 113 | not actually include the asset data. Instead, it generates function stubs 114 | which load the data from the original file on disk. The asset API remains 115 | identical between debug and release builds, so your code will not have to 116 | change. 117 | 118 | This is useful during development when you expect the assets to change often. 119 | The host application using these assets uses the same API in both cases and 120 | will not have to care where the actual data comes from. 121 | 122 | An example is a Go webserver with some embedded, static web content like 123 | HTML, JS and CSS files. While developing it, you do not want to rebuild the 124 | whole server and restart it every time you make a change to a bit of 125 | javascript. You just want to build and launch the server once. Then just press 126 | refresh in the browser to see those changes. Embedding the assets with the 127 | `debug` flag allows you to do just that. When you are finished developing and 128 | ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. 129 | It will now embed the latest version of the assets. 130 | 131 | 132 | ### Lower memory footprint 133 | 134 | Using the `-nomemcopy` flag, will alter the way the output file is generated. 135 | It will employ a hack that allows us to read the file data directly from 136 | the compiled program's `.rodata` section. This ensures that when we 137 | call our generated function, we omit unnecessary memcopies. 138 | 139 | The downside of this, is that it requires dependencies on the `reflect` and 140 | `unsafe` packages. These may be restricted on platforms like AppEngine and 141 | thus prevent you from using this mode. 142 | 143 | Another disadvantage is that the byte slice we create, is strictly read-only. 144 | For most use-cases this is not a problem, but if you ever try to alter the 145 | returned byte slice, a runtime panic is thrown. Use this mode only on target 146 | platforms where memory constraints are an issue. 147 | 148 | The default behavior is to use the old code generation method. This prevents the 149 | two previously mentioned issues, but will employ at least one extra memcopy and 150 | thus increase memory requirements. 151 | 152 | For instance, consider the following two examples: 153 | 154 | This would be the default mode, using an extra memcopy but gives a safe 155 | implementation without dependencies on `reflect` and `unsafe`: 156 | 157 | ```go 158 | func myfile() []byte { 159 | return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a} 160 | } 161 | ``` 162 | 163 | Here is the same functionality, but uses the `.rodata` hack. 164 | The byte slice returned from this example can not be written to without 165 | generating a runtime error. 166 | 167 | ```go 168 | var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" 169 | 170 | func myfile() []byte { 171 | var empty [0]byte 172 | sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) 173 | b := empty[:] 174 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 175 | bx.Data = sx.Data 176 | bx.Len = len(_myfile) 177 | bx.Cap = bx.Len 178 | return b 179 | } 180 | ``` 181 | 182 | 183 | ### Optional compression 184 | 185 | When the `-nocompress` flag is given, the supplied resource is *not* GZIP 186 | compressed before being turned into Go code. The data should still be accessed 187 | through a function call, so nothing changes in the usage of the generated file. 188 | 189 | This feature is useful if you do not care for compression, or the supplied 190 | resource is already compressed. Doing it again would not add any value and may 191 | even increase the size of the data. 192 | 193 | The default behavior of the program is to use compression. 194 | 195 | 196 | ### Path prefix stripping 197 | 198 | The keys used in the `_bindata` map, are the same as the input file name 199 | passed to `go-bindata`. This includes the path. In most cases, this is not 200 | desireable, as it puts potentially sensitive information in your code base. 201 | For this purpose, the tool supplies another command line flag `-prefix`. 202 | This accepts a portion of a path name, which should be stripped off from 203 | the map keys and function names. 204 | 205 | For example, running without the `-prefix` flag, we get: 206 | 207 | $ go-bindata /path/to/templates/ 208 | 209 | _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html 210 | 211 | Running with the `-prefix` flag, we get: 212 | 213 | $ go-bindata -prefix "/path/to/" /path/to/templates/ 214 | 215 | _bindata["templates/foo.html"] = templates_foo_html 216 | 217 | ### Build tags 218 | 219 | With the optional `-tags` flag, you can specify any go build tags that 220 | must be fulfilled for the output file to be included in a build. This 221 | is useful when including binary data in multiple formats, where the desired 222 | format is specified at build time with the appropriate tags. 223 | 224 | The tags are appended to a `// +build` line in the beginning of the output file 225 | and must follow the build tags syntax specified by the go tool. 226 | 227 | ### Related projects 228 | 229 | [go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) - 230 | implements `http.FileSystem` interface. Allows you to serve assets with `net/http`. 231 | -------------------------------------------------------------------------------- /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 | Size int64 13 | } 14 | -------------------------------------------------------------------------------- /benchmark_test.go: -------------------------------------------------------------------------------- 1 | package bindata_test 2 | 3 | import ( 4 | "go/format" 5 | "os" 6 | "path/filepath" 7 | "testing" 8 | 9 | bindata "github.com/kevinburke/go-bindata/v4" 10 | ) 11 | 12 | func dirSize(path string) (int64, error) { 13 | var size int64 14 | err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { 15 | if !info.IsDir() { 16 | size += info.Size() 17 | } 18 | return err 19 | }) 20 | return size, err 21 | } 22 | 23 | func BenchmarkBindata(b *testing.B) { 24 | size, err := dirSize("testdata/benchmark") 25 | if err != nil { 26 | b.Fatal(err) 27 | } 28 | b.SetBytes(size) 29 | outDir, err := os.MkdirTemp("", "bench_bindata") 30 | if err != nil { 31 | b.Fatal(err) 32 | } 33 | defer os.RemoveAll(outDir) // clean up 34 | cfg := &bindata.Config{ 35 | Package: "assets", 36 | Input: []bindata.InputConfig{ 37 | {Path: "testdata/benchmark", Recursive: true}, 38 | }, 39 | Output: filepath.Join(outDir, "bindata.go"), 40 | NoMemCopy: false, 41 | NoCompress: true, 42 | Debug: false, 43 | NoMetadata: true, 44 | Mode: 0x0, ModTime: 0, 45 | Ignore: nil, 46 | } 47 | b.ReportAllocs() 48 | b.ResetTimer() 49 | for i := 0; i < b.N; i++ { 50 | if err := bindata.Translate(cfg); err != nil { 51 | b.Fatal(err) 52 | } 53 | } 54 | } 55 | 56 | var formatSink []byte 57 | 58 | func BenchmarkFormatSource(b *testing.B) { 59 | // https://github.com/golang/go/issues/26528 60 | // unformatted.out is any large go-bindata source file. 61 | data, err := os.ReadFile("testdata/unformatted.out") 62 | if os.IsNotExist(err) { 63 | b.Skip("source file does not exist") 64 | return 65 | } 66 | if err != nil { 67 | b.Fatal(err) 68 | } 69 | b.SetBytes(int64(len(data))) 70 | b.ReportAllocs() 71 | b.ResetTimer() 72 | for i := 0; i < b.N; i++ { 73 | formatSink, err = format.Source(data) 74 | if err != nil { 75 | b.Fatal(err) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /bits.go: -------------------------------------------------------------------------------- 1 | package bindata 2 | 3 | // fmtInt formats v into the tail of buf. 4 | // It returns the index where the output begins. 5 | func fmtInt(buf []byte, v uint64) int { 6 | w := len(buf) 7 | if v == 0 { 8 | w-- 9 | buf[w] = '0' 10 | } else { 11 | for v > 0 { 12 | w-- 13 | buf[w] = byte(v%10) + '0' 14 | v /= 10 15 | } 16 | } 17 | return w 18 | } 19 | 20 | // fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the 21 | // tail of buf, omitting trailing zeros. it omits the decimal 22 | // point too when the fraction is 0. It returns the index where the 23 | // output bytes begin and the value v/10**prec. 24 | func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) { 25 | // Omit trailing zeros up to and including decimal point. 26 | w := len(buf) 27 | print := false 28 | for i := 0; i < prec; i++ { 29 | digit := v % 10 30 | print = print || digit != 0 31 | if print { 32 | w-- 33 | buf[w] = byte(digit) + '0' 34 | } 35 | v /= 10 36 | } 37 | if print { 38 | w-- 39 | buf[w] = '.' 40 | } 41 | return w, v 42 | } 43 | 44 | const ( 45 | bit bits = 1 46 | byte_ = 8 * bit 47 | // https://en.wikipedia.org/wiki/Orders_of_magnitude_(data) 48 | kilobyte = 1000 * byte_ 49 | megabyte = 1000 * kilobyte 50 | gigabyte = 1000 * megabyte 51 | terabyte = 1000 * gigabyte 52 | petabyte = 1000 * terabyte 53 | exabyte = 1000 * petabyte 54 | ) 55 | 56 | // Bits represents a quantity of bits, bytes, kilobytes or megabytes. Bits are 57 | // parsed and formatted using the IEEE / SI standards, which use multiples of 58 | // 1000 to represent kilobytes and megabytes (instead of multiples of 1024). For 59 | // more information see https://en.wikipedia.org/wiki/Megabyte#Definitions. 60 | type bits int64 61 | 62 | // Bytes returns the size as a floating point number of bytes. 63 | func (b bits) Bytes() float64 { 64 | bytes := b / byte_ 65 | bits := b % byte_ 66 | return float64(bytes) + float64(bits)/8 67 | } 68 | 69 | // Kilobytes returns the size as a floating point number of kilobytes. 70 | func (b bits) Kilobytes() float64 { 71 | bytes := b / kilobyte 72 | bits := b % kilobyte 73 | return float64(bytes) + float64(bits)/(8*1000) 74 | } 75 | 76 | // Megabytes returns the size as a floating point number of megabytes. 77 | func (b bits) Megabytes() float64 { 78 | bytes := b / megabyte 79 | bits := b % megabyte 80 | return float64(bytes) + float64(bits)/(8*1000*1000) 81 | } 82 | 83 | // Gigabytes returns the size as a floating point number of gigabytes. 84 | func (b bits) Gigabytes() float64 { 85 | bytes := b / gigabyte 86 | bits := b % gigabyte 87 | return float64(bytes) + float64(bits)/(8*1000*1000*1000) 88 | } 89 | 90 | // String returns a string representation of b using the largest unit that has a 91 | // positive number before the decimal. At most three decimal places of precision 92 | // are printed. 93 | func (b bits) String() string { 94 | if b == 0 { 95 | return "0" 96 | } 97 | // Largest value is "-123.150EB" 98 | var buf [10]byte 99 | w := len(buf) - 1 100 | u := uint64(b) 101 | neg := b < 0 102 | if neg { 103 | u = -u 104 | } 105 | if u < uint64(byte_) { 106 | w -= 2 107 | copy(buf[w:], "bit") 108 | w = fmtInt(buf[:w], u) 109 | } else { 110 | switch { 111 | case u < uint64(kilobyte): 112 | w -= 0 113 | buf[w] = 'B' 114 | u = (u * 1e3 / 8) 115 | case u < uint64(megabyte): 116 | w -= 1 117 | copy(buf[w:], "kB") 118 | u /= 8 119 | case u < uint64(gigabyte): 120 | w -= 1 121 | copy(buf[w:], "MB") 122 | u /= 8 * 1e3 123 | case u < uint64(terabyte): 124 | w -= 1 125 | copy(buf[w:], "GB") 126 | u /= 8 * 1e6 127 | case u < uint64(petabyte): 128 | w -= 1 129 | copy(buf[w:], "TB") 130 | u /= 8 * 1e9 131 | case u < uint64(exabyte): 132 | w -= 1 133 | copy(buf[w:], "PB") 134 | u /= 8 * 1e12 135 | case u >= uint64(exabyte): 136 | w -= 1 137 | copy(buf[w:], "EB") 138 | u /= 8 * 1e15 139 | } 140 | w, u = fmtFrac(buf[:w], u, 3) 141 | w = fmtInt(buf[:w], u) 142 | } 143 | if neg { 144 | w-- 145 | buf[w] = '-' 146 | } 147 | return string(buf[w:]) 148 | } 149 | -------------------------------------------------------------------------------- /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 | // ByteWriter writes the hex-encoded version of input bytes to its Writer. 19 | type ByteWriter struct { 20 | io.Writer 21 | c int 22 | } 23 | 24 | func (w *ByteWriter) Write(p []byte) (n int, err error) { 25 | if len(p) == 0 { 26 | return 27 | } 28 | 29 | for n = range p { 30 | if w.c%12 == 0 { 31 | w.Writer.Write(newline) 32 | w.Writer.Write(dataindent) 33 | w.c = 0 34 | } else { 35 | w.Writer.Write(space) 36 | } 37 | 38 | fmt.Fprintf(w.Writer, "0x%02x,", p[n]) 39 | w.c++ 40 | } 41 | 42 | n++ 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` 65 | // and `unsafe` packages. These may be restricted on platforms like 66 | // AppEngine and thus prevent you from using this mode. 67 | // 68 | // Another disadvantage is that the byte slice we create is strictly 69 | // read-only. For most use-cases this is not a problem, but if you ever try 70 | // to alter the returned byte slice, a runtime panic is thrown. Use this 71 | // mode only on target platforms where memory constraints are an issue. 72 | // 73 | // The default behavior is to use the old code generation method. This 74 | // prevents the two previously mentioned issues, but will employ at least 75 | // one 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 loads the 110 | // asset contents directly from disk at their original location, instead of 111 | // embedding the contents in the code. 112 | // 113 | // This is mostly useful if you anticipate that the assets are going to 114 | // change during your development cycle. You will always want your code to 115 | // access the latest version of the asset. Only in release mode, will the 116 | // assets actually be embedded in the code. The default behavior is Release 117 | // 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 %q is a directory", c.Output) 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 | "bytes" 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 to Go code and 19 | // writes new files to the output specified in the given configuration. 20 | func Translate(c *Config) error { 21 | var toc []Asset 22 | 23 | // Ensure our configuration has sane values. 24 | if err := c.validate(); err != nil { 25 | return err 26 | } 27 | 28 | knownFuncs := make(map[string]int) 29 | visitedPaths := make(map[string]bool) 30 | // Locate all the assets. 31 | for _, input := range c.Input { 32 | if err := findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore, knownFuncs, visitedPaths); err != nil { 33 | return err 34 | } 35 | } 36 | 37 | // Create output file. 38 | buf := new(bytes.Buffer) 39 | // Write the header. This makes e.g. Github ignore diffs in generated files. 40 | if _, err := fmt.Fprint(buf, "// Code generated by go-bindata. DO NOT EDIT.\n"); err != nil { 41 | return err 42 | } 43 | if _, err := fmt.Fprint(buf, "// sources:\n"); err != nil { 44 | return err 45 | } 46 | 47 | wd, err := os.Getwd() 48 | if err != nil { 49 | return err 50 | } 51 | 52 | for _, asset := range toc { 53 | relative, err := filepath.Rel(wd, asset.Path) 54 | if err != nil { 55 | return err 56 | } 57 | relative = strings.TrimPrefix(relative, c.Prefix) 58 | relative = strings.TrimPrefix(relative, "/") 59 | if _, err = fmt.Fprintf(buf, "// %s (%s)\n", filepath.ToSlash(relative), bits(asset.Size)*byte_); err != nil { 60 | return err 61 | } 62 | } 63 | if _, err := fmt.Fprint(buf, "\n"); err != nil { 64 | return err 65 | } 66 | 67 | // Write build tags, if applicable. 68 | if len(c.Tags) > 0 { 69 | if _, err := fmt.Fprintf(buf, "// +build %s\n\n", c.Tags); err != nil { 70 | return err 71 | } 72 | } 73 | 74 | // Write package declaration. 75 | _, err = fmt.Fprintf(buf, "package %s\n\n", c.Package) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | // Write assets. 81 | if c.Debug || c.Dev { 82 | if os.Getenv("GO_BINDATA_TEST") == "true" { 83 | // If we don't do this, people running the tests on different 84 | // machines get different git diffs. 85 | for i := range toc { 86 | toc[i].Path = strings.Replace(toc[i].Path, wd, "/test", 1) 87 | } 88 | } 89 | err = writeDebugFunctions(buf, c, toc) 90 | } else { 91 | err = writeReleaseFunctions(buf, c, toc) 92 | } 93 | if err != nil { 94 | return err 95 | } 96 | 97 | // Write table of contents 98 | if err := writeTOC(buf, toc); err != nil { 99 | return err 100 | } 101 | _, err = fmt.Fprintf(buf, `// AssetDebug is true if the assets were built with the debug flag enabled. 102 | const AssetDebug = %t 103 | 104 | `, c.Debug) 105 | if err != nil { 106 | return err 107 | } 108 | // Write hierarchical tree of assets 109 | if err := writeTOCTree(buf, toc); err != nil { 110 | return err 111 | } 112 | 113 | // Write restore procedure 114 | if err := writeRestore(buf); err != nil { 115 | return err 116 | } 117 | 118 | return diffAndWrite(c.Output, buf.Bytes(), 0666) 119 | } 120 | 121 | // findFiles recursively finds all the file paths in the given directory tree. 122 | // They are added to the given map as keys. Values will be safe function names 123 | // for each file, which will be used when generating the output code. 124 | func findFiles(dirOrFile, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp, knownFuncs map[string]int, visitedPaths map[string]bool) error { 125 | dirOrFile = filepath.Clean(dirOrFile) 126 | // confusingly, if a prefix exists this is the absolute path; if a prefix 127 | // doesn't exist it may be an absolute path, or it may be a relative path. 128 | var dirOrFilePath string 129 | if len(prefix) > 0 { 130 | var err error 131 | dirOrFilePath, err = filepath.Abs(dirOrFile) 132 | if err != nil { 133 | return err 134 | } 135 | prefix, err = filepath.Abs(prefix) 136 | if err != nil { 137 | return err 138 | } 139 | prefix = filepath.ToSlash(prefix) 140 | } else { 141 | dirOrFilePath = dirOrFile 142 | } 143 | 144 | dirOrFileFI, err := os.Stat(dirOrFilePath) 145 | if err != nil { 146 | return err 147 | } 148 | 149 | var list []os.FileInfo 150 | // if prefix is non-empty this is the absolute path, otherwise it may be 151 | // a relative path. 152 | var dirpath string 153 | if dirOrFileFI.IsDir() { 154 | dirpath = dirOrFilePath 155 | visitedPaths[dirpath] = true 156 | fd, err := os.Open(dirpath) 157 | if err != nil { 158 | return err 159 | } 160 | 161 | list, err = fd.Readdir(0) 162 | if err != nil { 163 | return err 164 | } 165 | 166 | // Sort to make output stable between invocations 167 | sort.Slice(list, func(i, j int) bool { 168 | return list[i].Name() < list[j].Name() 169 | }) 170 | fd.Close() 171 | } else { 172 | dirpath = filepath.Dir(dirOrFilePath) 173 | list = []os.FileInfo{dirOrFileFI} 174 | } 175 | 176 | for _, entry := range list { 177 | var asset Asset 178 | asset.Path = filepath.Join(dirpath, entry.Name()) 179 | pathWithSlashes := filepath.ToSlash(asset.Path) 180 | 181 | shouldIgnore := false 182 | for _, re := range ignore { 183 | if re.MatchString(asset.Path) { 184 | shouldIgnore = true 185 | break 186 | } 187 | } 188 | if shouldIgnore { 189 | continue 190 | } 191 | 192 | if entry.IsDir() { 193 | if recursive { 194 | recursivePath := filepath.Join(dirOrFile, entry.Name()) 195 | visitedPaths[asset.Path] = true 196 | findFiles(recursivePath, prefix, recursive, toc, ignore, knownFuncs, visitedPaths) 197 | } 198 | continue 199 | } else if entry.Mode()&os.ModeSymlink == os.ModeSymlink { 200 | var linkPath string 201 | if linkPath, err = os.Readlink(asset.Path); err != nil { 202 | return err 203 | } 204 | if !filepath.IsAbs(linkPath) { 205 | if linkPath, err = filepath.Abs(dirpath + "/" + linkPath); err != nil { 206 | return err 207 | } 208 | } 209 | if _, ok := visitedPaths[linkPath]; !ok { 210 | visitedPaths[linkPath] = true 211 | findFiles(asset.Path, prefix, recursive, toc, ignore, knownFuncs, visitedPaths) 212 | } 213 | continue 214 | } 215 | 216 | if strings.HasPrefix(pathWithSlashes, prefix) { 217 | asset.Name = strings.TrimPrefix(pathWithSlashes, prefix) 218 | } else { 219 | // File or directory isn't inside of the prefix list 220 | if dirOrFileFI.IsDir() { 221 | asset.Name = filepath.Join(dirOrFile, entry.Name()) 222 | } else { 223 | asset.Name = dirOrFile 224 | } 225 | } 226 | 227 | // If we have a leading slash, get rid of it. 228 | asset.Name = strings.TrimPrefix(asset.Name, "/") 229 | 230 | // This shouldn't happen. 231 | if len(asset.Name) == 0 { 232 | return fmt.Errorf("invalid file: %v", asset.Path) 233 | } 234 | 235 | asset.Func = safeFunctionName(asset.Name, knownFuncs) 236 | asset.Path, err = filepath.Abs(asset.Path) 237 | if err != nil { 238 | return err 239 | } 240 | asset.Size = entry.Size() 241 | *toc = append(*toc, asset) 242 | } 243 | 244 | return nil 245 | } 246 | 247 | var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`) 248 | 249 | // safeFunctionName converts the given name into a name which qualifies as a 250 | // valid function identifier. It also compares against a known list of functions 251 | // (if one is provided) to prevent conflict based on name translation. 252 | func safeFunctionName(name string, knownFuncs map[string]int) string { 253 | var inBytes, outBytes []byte 254 | var toUpper bool 255 | 256 | name = strings.ToLower(name) 257 | inBytes = []byte(name) 258 | 259 | for i := 0; i < len(inBytes); i++ { 260 | if regFuncName.Match([]byte{inBytes[i]}) { 261 | toUpper = true 262 | } else if toUpper { 263 | outBytes = append(outBytes, []byte(strings.ToUpper(string(inBytes[i])))...) 264 | toUpper = false 265 | } else { 266 | outBytes = append(outBytes, inBytes[i]) 267 | } 268 | } 269 | 270 | name = string(outBytes) 271 | 272 | // Identifier can't start with a digit. 273 | if unicode.IsDigit(rune(name[0])) { 274 | name = "_" + name 275 | } 276 | 277 | if num, ok := knownFuncs[name]; ok { 278 | knownFuncs[name] = num + 1 279 | name = fmt.Sprintf("%s%d", name, num) 280 | } else if knownFuncs != nil { 281 | knownFuncs[name] = 2 282 | } 283 | 284 | return name 285 | } 286 | -------------------------------------------------------------------------------- /convert_test.go: -------------------------------------------------------------------------------- 1 | package bindata 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/kevinburke/go-bindata/v4/testdata/assets" 9 | ) 10 | 11 | func TestSafeFunctionName(t *testing.T) { 12 | var knownFuncs = make(map[string]int) 13 | name1 := safeFunctionName("foo/bar", knownFuncs) 14 | name2 := safeFunctionName("foo_bar", knownFuncs) 15 | if name1 == name2 { 16 | t.Errorf("name collision") 17 | } 18 | } 19 | 20 | func TestFindFiles(t *testing.T) { 21 | var toc []Asset 22 | var visitedPaths = make(map[string]bool) 23 | err := findFiles("testdata/dupname", "testdata/dupname", true, &toc, []*regexp.Regexp{}, nil, visitedPaths) 24 | if err != nil { 25 | t.Errorf("expected to be no error: %+v", err) 26 | } 27 | if toc[0].Func == toc[1].Func { 28 | t.Errorf("name collision") 29 | } 30 | } 31 | 32 | func TestFindFilesOutsidePrefixDirectory(t *testing.T) { 33 | var toc []Asset 34 | var visitedPaths = make(map[string]bool) 35 | err := findFiles("testdata/in/a", "testdata/assets", true, &toc, nil, nil, visitedPaths) 36 | if err != nil { 37 | t.Errorf("expected to be no error: %+v", err) 38 | } 39 | if len(toc) != 1 { 40 | t.Errorf("expected to find one item, got %d", len(toc)) 41 | } 42 | item := toc[0] 43 | want := "testdata/in/a/test.asset" 44 | if item.Name != want { 45 | t.Errorf("expected Name to be %q, got %q", want, item.Name) 46 | } 47 | } 48 | 49 | func TestFindFilesOutsidePrefix(t *testing.T) { 50 | var toc []Asset 51 | var visitedPaths = make(map[string]bool) 52 | err := findFiles("testdata/in/test.asset", "testdata/assets", true, &toc, nil, nil, visitedPaths) 53 | if err != nil { 54 | t.Errorf("expected to be no error: %+v", err) 55 | } 56 | if len(toc) != 1 { 57 | t.Errorf("expected to find one item, got %d", len(toc)) 58 | } 59 | item := toc[0] 60 | want := "testdata/in/test.asset" 61 | if item.Name != want { 62 | t.Errorf("expected Name to be %q, got %q", want, item.Name) 63 | } 64 | } 65 | 66 | func TestFindFilesWithSymlinks(t *testing.T) { 67 | var tocSrc []Asset 68 | var tocTarget []Asset 69 | 70 | var knownFuncs = make(map[string]int) 71 | var visitedPaths = make(map[string]bool) 72 | err := findFiles("testdata/symlinkSrc", "testdata/symlinkSrc", true, &tocSrc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 73 | if err != nil { 74 | t.Errorf("expected to be no error: %+v", err) 75 | } 76 | 77 | knownFuncs = make(map[string]int) 78 | visitedPaths = make(map[string]bool) 79 | err = findFiles("testdata/symlinkParent", "testdata/symlinkParent", true, &tocTarget, []*regexp.Regexp{}, knownFuncs, visitedPaths) 80 | if err != nil { 81 | t.Errorf("expected to be no error: %+v", err) 82 | } 83 | 84 | if len(tocSrc) != len(tocTarget) { 85 | t.Errorf("Symlink source and target should have the same number of assets. Expected %d got %d", len(tocTarget), len(tocSrc)) 86 | } else { 87 | for i := range tocSrc { 88 | targetFunc := strings.TrimPrefix(tocTarget[i].Func, "symlinktarget") 89 | targetFunc = strings.ToLower(targetFunc[:1]) + targetFunc[1:] 90 | if tocSrc[i].Func != targetFunc { 91 | t.Errorf("Symlink source and target produced different function lists. Expected %s to be %s", targetFunc, tocSrc[i].Func) 92 | } 93 | } 94 | } 95 | } 96 | 97 | func TestFindFilesWithRecursiveSymlinks(t *testing.T) { 98 | var toc []Asset 99 | 100 | var knownFuncs = make(map[string]int) 101 | var visitedPaths = make(map[string]bool) 102 | err := findFiles("testdata/symlinkRecursiveParent", "testdata/symlinkRecursiveParent", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 103 | if err != nil { 104 | t.Errorf("expected to be no error: %+v", err) 105 | } 106 | 107 | if len(toc) != 1 { 108 | t.Errorf("Only one asset should have been found. Got %d: %v", len(toc), toc) 109 | } 110 | } 111 | 112 | func TestFindFilesWithSymlinkedFile(t *testing.T) { 113 | var toc []Asset 114 | 115 | var knownFuncs = make(map[string]int) 116 | var visitedPaths = make(map[string]bool) 117 | err := findFiles("testdata/symlinkFile", "testdata/symlinkFile", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) 118 | if err != nil { 119 | t.Errorf("expected to be no error: %+v", err) 120 | } 121 | 122 | if len(toc) != 1 { 123 | t.Errorf("Only one asset should have been found. Got %d: %v", len(toc), toc) 124 | } 125 | } 126 | 127 | func TestNoPrefixExtensionMatch(t *testing.T) { 128 | _, err := assets.Asset("testdata/benchmark/44.jpg") 129 | if err != nil { 130 | t.Fatal(err) 131 | } 132 | _, err = assets.Asset("testdata/benchmark/44.jpgextraextension") 133 | if err == nil { 134 | t.Fatal("should have returned err retrieving nonexistent file, got nil") 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /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 | // https://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | ) 11 | 12 | // writeDebugFunctions writes the debug code file. 13 | func writeDebugFunctions(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 | "crypto/sha256" 34 | "fmt" 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 := os.ReadFile(path) 43 | if err != nil { 44 | err = fmt.Errorf("Error reading asset %%s at %%s: %`+wrappedError+`", name, path, err) 45 | } 46 | return buf, err 47 | } 48 | 49 | type asset struct { 50 | bytes []byte 51 | info os.FileInfo 52 | digest [sha256.Size]byte 53 | } 54 | 55 | `) 56 | return err 57 | } 58 | 59 | // writeDebugAsset write a debug entry for the given asset. 60 | // A debug entry is simply a function which reads the asset from 61 | // the original file (e.g.: from disk). 62 | func writeDebugAsset(w io.Writer, c *Config, asset *Asset) error { 63 | pathExpr := fmt.Sprintf("%q", asset.Path) 64 | if c.Dev { 65 | pathExpr = fmt.Sprintf("filepath.Join(rootDir, %q)", asset.Name) 66 | } 67 | 68 | _, err := fmt.Fprintf(w, `// %s reads file data from disk. It returns an error on failure. 69 | func %s() (*asset, error) { 70 | path := %s 71 | name := %q 72 | bytes, err := bindataRead(path, name) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | fi, err := os.Stat(path) 78 | if err != nil { 79 | err = fmt.Errorf("Error reading asset info %%s at %%s: %`+wrappedError+`", name, path, err) 80 | } 81 | 82 | a := &asset{bytes: bytes, info: fi} 83 | return a, err 84 | } 85 | 86 | `, asset.Func, asset.Func, pathExpr, asset.Name) 87 | return err 88 | } 89 | -------------------------------------------------------------------------------- /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 behavior is to use the old code generation method. This prevents the 53 | two previously mentioned issues, but will employ at least one extra memcopy and 54 | 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 behavior 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 | -------------------------------------------------------------------------------- /filewriter.go: -------------------------------------------------------------------------------- 1 | package bindata 2 | 3 | import ( 4 | "bytes" 5 | "crypto/sha256" 6 | "io" 7 | "os" 8 | ) 9 | 10 | func diffAndWrite(filename string, data []byte, mode os.FileMode) error { 11 | // If the file has the same contents as data, try to avoid a write. 12 | f, err := os.Open(filename) 13 | if err != nil { 14 | return safefileWriteFile(filename, data, mode) 15 | } 16 | h := sha256.New() 17 | if _, err := io.Copy(h, f); err != nil { 18 | return safefileWriteFile(filename, data, mode) 19 | } 20 | if err := f.Close(); err != nil { 21 | return safefileWriteFile(filename, data, mode) 22 | } 23 | h2 := sha256.New() 24 | if _, err := h2.Write(data); err != nil { 25 | return safefileWriteFile(filename, data, mode) 26 | } 27 | if bytes.Equal(h.Sum(nil), h2.Sum(nil)) { 28 | return nil 29 | } 30 | return safefileWriteFile(filename, data, mode) 31 | } 32 | -------------------------------------------------------------------------------- /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/kevinburke/go-bindata/v4" 16 | ) 17 | 18 | func main() { 19 | cfg := parseArgs() 20 | if err := bindata.Translate(cfg); err != nil { 21 | fmt.Fprintf(os.Stderr, "bindata: %v\n", err) 22 | os.Exit(1) 23 | } 24 | } 25 | 26 | // parseArgs creates a new, filled configuration instance 27 | // by reading and parsing command line options. 28 | // 29 | // This function exits the program with an error, if 30 | // any of the command line options are incorrect. 31 | func parseArgs() *bindata.Config { 32 | var longVersion bool 33 | var version bool 34 | 35 | c := bindata.NewConfig() 36 | 37 | flag.Usage = func() { 38 | fmt.Printf("Usage: %s [options] \n\n", os.Args[0]) 39 | flag.PrintDefaults() 40 | } 41 | 42 | flag.BoolVar(&c.Debug, "debug", c.Debug, "Do not embed the assets, but provide the embedding API. Contents will still be loaded from disk.") 43 | 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.") 44 | flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of build tags to include.") 45 | flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off asset names.") 46 | flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.") 47 | 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.") 48 | flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.") 49 | flag.BoolVar(&c.NoMetadata, "nometadata", c.NoMetadata, "Assets will not preserve size, mode, and modtime info.") 50 | flag.UintVar(&c.Mode, "mode", c.Mode, "Optional file mode override for all files.") 51 | flag.Int64Var(&c.ModTime, "modtime", c.ModTime, "Optional modification unix timestamp override for all files.") 52 | flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.") 53 | flag.BoolVar(&longVersion, "version", false, "Displays verbose version information.") 54 | flag.BoolVar(&version, "v", 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 | rx, err := regexp.Compile(pattern) 64 | if err != nil { 65 | fmt.Fprintf(os.Stderr, "could not parse --ignore flag %q as regex: %v\n", pattern, err) 66 | os.Exit(1) 67 | } 68 | patterns = append(patterns, rx) 69 | } 70 | c.Ignore = patterns 71 | 72 | if version { 73 | fmt.Printf("%s\n", Version()) 74 | os.Exit(0) 75 | } 76 | if longVersion { 77 | fmt.Printf("%s\n", LongVersion()) 78 | os.Exit(0) 79 | } 80 | 81 | // Make sure we have input paths. 82 | if flag.NArg() == 0 { 83 | fmt.Fprintf(os.Stderr, "Missing \n\n") 84 | flag.Usage() 85 | os.Exit(1) 86 | } 87 | 88 | // Create input configurations. 89 | c.Input = make([]bindata.InputConfig, flag.NArg()) 90 | for i := range c.Input { 91 | c.Input[i] = parseInput(flag.Arg(i)) 92 | } 93 | 94 | return c 95 | } 96 | 97 | // parseRecursive determines whether the given path has a recursive indicator and 98 | // returns a new path with the recursive indicator chopped off if it does. 99 | // 100 | // ex: 101 | // /path/to/foo/... -> (/path/to/foo, true) 102 | // /path/to/bar -> (/path/to/bar, false) 103 | func parseInput(path string) bindata.InputConfig { 104 | if strings.HasSuffix(path, "/...") { 105 | return bindata.InputConfig{ 106 | Path: filepath.Clean(path[:len(path)-4]), 107 | Recursive: true, 108 | } 109 | } else { 110 | return bindata.InputConfig{ 111 | Path: filepath.Clean(path), 112 | Recursive: false, 113 | } 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /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 | "sync" 11 | "time" 12 | ) 13 | 14 | const ( 15 | AppName = "go-bindata" 16 | AppVersionMajor = 4 17 | AppVersionMinor = 0 18 | AppVersionRev = 2 19 | ) 20 | 21 | var vsn, longVsn string 22 | var vsnOnce, longVsnOnce sync.Once 23 | 24 | func Version() string { 25 | vsnOnce.Do(func() { 26 | vsn = fmt.Sprintf(`go-bindata version %d.%d.%d`, AppVersionMajor, AppVersionMinor, AppVersionRev) 27 | }) 28 | return vsn 29 | } 30 | 31 | func LongVersion() string { 32 | longVsnOnce.Do(func() { 33 | longVsn = fmt.Sprintf(`%s %d.%d.%d (Go runtime %s). 34 | Copyright (c) 2010-2015, Jim Teeuwen. 35 | Copyright (c) 2017-%d, Kevin Burke.`, AppName, 36 | AppVersionMajor, AppVersionMinor, AppVersionRev, 37 | runtime.Version(), time.Now().Year()) 38 | }) 39 | return longVsn 40 | } 41 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/kevinburke/go-bindata/v4 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /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 | "crypto/sha256" 11 | "fmt" 12 | "io" 13 | "os" 14 | "unicode" 15 | "unicode/utf8" 16 | ) 17 | 18 | // writeReleaseFunctions writes the release code file. 19 | func writeReleaseFunctions(w io.Writer, c *Config, toc []Asset) error { 20 | err := writeReleaseHeader(w, c) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | for i := range toc { 26 | if err := writeReleaseAsset(w, c, &toc[i]); 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 | h := sha256.New() 69 | tr := io.TeeReader(fd, h) 70 | if c.NoCompress { 71 | if c.NoMemCopy { 72 | err = uncompressed_nomemcopy(w, asset, tr) 73 | } else { 74 | err = uncompressed_memcopy(w, asset, tr) 75 | } 76 | } else { 77 | if c.NoMemCopy { 78 | err = compressed_nomemcopy(w, asset, tr) 79 | } else { 80 | err = compressedMemcopy(w, asset, tr) 81 | } 82 | } 83 | if err != nil { 84 | return err 85 | } 86 | var digest [sha256.Size]byte 87 | copy(digest[:], h.Sum(nil)) 88 | return assetReleaseCommon(w, c, asset, digest) 89 | } 90 | 91 | var ( 92 | backquote = []byte("`") 93 | bom = []byte("\xEF\xBB\xBF") 94 | ) 95 | 96 | // sanitize prepares a valid UTF-8 string as a raw string constant. 97 | // Based on https://code.google.com/p/go/source/browse/godoc/static/makestatic.go?repo=tools 98 | func sanitize(b []byte) []byte { 99 | var chunks [][]byte 100 | for i, b := range bytes.Split(b, backquote) { 101 | if i > 0 { 102 | chunks = append(chunks, backquote) 103 | } 104 | for j, c := range bytes.Split(b, bom) { 105 | if j > 0 { 106 | chunks = append(chunks, bom) 107 | } 108 | if len(c) > 0 { 109 | chunks = append(chunks, c) 110 | } 111 | } 112 | } 113 | 114 | var buf bytes.Buffer 115 | sanitizeChunks(&buf, chunks) 116 | return buf.Bytes() 117 | } 118 | 119 | func sanitizeChunks(buf *bytes.Buffer, chunks [][]byte) { 120 | n := len(chunks) 121 | if n >= 2 { 122 | buf.WriteString("(") 123 | sanitizeChunks(buf, chunks[:n/2]) 124 | buf.WriteString(" + ") 125 | sanitizeChunks(buf, chunks[n/2:]) 126 | buf.WriteString(")") 127 | return 128 | } 129 | b := chunks[0] 130 | if bytes.Equal(b, backquote) { 131 | buf.WriteString("\"`\"") 132 | return 133 | } 134 | if bytes.Equal(b, bom) { 135 | buf.WriteString(`"\xEF\xBB\xBF"`) 136 | return 137 | } 138 | buf.WriteString("`") 139 | buf.Write(b) 140 | buf.WriteString("`") 141 | } 142 | 143 | func header_compressed_nomemcopy(w io.Writer) error { 144 | _, err := fmt.Fprintf(w, `import ( 145 | "bytes" 146 | "compress/gzip" 147 | "crypto/sha256" 148 | "fmt" 149 | "io" 150 | "os" 151 | "path/filepath" 152 | "strings" 153 | "time" 154 | ) 155 | 156 | func bindataRead(data, name string) ([]byte, error) { 157 | gz, err := gzip.NewReader(strings.NewReader(data)) 158 | if err != nil { 159 | return nil, fmt.Errorf("read %%q: %`+wrappedError+`", name, err) 160 | } 161 | 162 | var buf bytes.Buffer 163 | _, err = io.Copy(&buf, gz) 164 | 165 | if err != nil { 166 | return nil, fmt.Errorf("read %%q: %`+wrappedError+`", name, err) 167 | } 168 | 169 | clErr := gz.Close() 170 | if clErr != nil { 171 | return nil, clErr 172 | } 173 | 174 | return buf.Bytes(), nil 175 | } 176 | 177 | `) 178 | return err 179 | } 180 | 181 | func header_compressed_memcopy(w io.Writer) error { 182 | _, err := fmt.Fprintf(w, `import ( 183 | "bytes" 184 | "compress/gzip" 185 | "crypto/sha256" 186 | "fmt" 187 | "io" 188 | "os" 189 | "path/filepath" 190 | "strings" 191 | "time" 192 | ) 193 | 194 | func bindataRead(data []byte, name string) ([]byte, error) { 195 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 196 | if err != nil { 197 | return nil, fmt.Errorf("read %%q: %`+wrappedError+`", name, err) 198 | } 199 | 200 | var buf bytes.Buffer 201 | _, err = io.Copy(&buf, gz) 202 | clErr := gz.Close() 203 | 204 | if err != nil { 205 | return nil, fmt.Errorf("read %%q: %`+wrappedError+`", name, err) 206 | } 207 | if clErr != nil { 208 | return nil, err 209 | } 210 | 211 | return buf.Bytes(), nil 212 | } 213 | 214 | `) 215 | return err 216 | } 217 | 218 | func header_uncompressed_nomemcopy(w io.Writer) error { 219 | _, err := fmt.Fprintf(w, `import ( 220 | "crypto/sha256" 221 | "fmt" 222 | "os" 223 | "path/filepath" 224 | "reflect" 225 | "strings" 226 | "time" 227 | "unsafe" 228 | ) 229 | 230 | func bindataRead(data, name string) ([]byte, error) { 231 | var empty [0]byte 232 | sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) 233 | b := empty[:] 234 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 235 | bx.Data = sx.Data 236 | bx.Len = len(data) 237 | bx.Cap = bx.Len 238 | return b, nil 239 | } 240 | 241 | `) 242 | return err 243 | } 244 | 245 | func header_uncompressed_memcopy(w io.Writer) error { 246 | _, err := fmt.Fprintf(w, `import ( 247 | "crypto/sha256" 248 | "fmt" 249 | "os" 250 | "path/filepath" 251 | "strings" 252 | "time" 253 | ) 254 | 255 | `) 256 | return err 257 | } 258 | 259 | func header_release_common(w io.Writer) error { 260 | _, err := fmt.Fprintf(w, `type asset struct { 261 | bytes []byte 262 | info os.FileInfo 263 | digest [sha256.Size]byte 264 | } 265 | 266 | type bindataFileInfo struct { 267 | name string 268 | size int64 269 | mode os.FileMode 270 | modTime time.Time 271 | } 272 | 273 | func (fi bindataFileInfo) Name() string { 274 | return fi.name 275 | } 276 | func (fi bindataFileInfo) Size() int64 { 277 | return fi.size 278 | } 279 | func (fi bindataFileInfo) Mode() os.FileMode { 280 | return fi.mode 281 | } 282 | func (fi bindataFileInfo) ModTime() time.Time { 283 | return fi.modTime 284 | } 285 | func (fi bindataFileInfo) IsDir() bool { 286 | return false 287 | } 288 | func (fi bindataFileInfo) Sys() interface{} { 289 | return nil 290 | } 291 | 292 | `) 293 | return err 294 | } 295 | 296 | func compressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error { 297 | _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) 298 | if err != nil { 299 | return err 300 | } 301 | 302 | gz := gzip.NewWriter(&StringWriter{Writer: w}) 303 | _, err = io.Copy(gz, r) 304 | gz.Close() 305 | 306 | if err != nil { 307 | return err 308 | } 309 | 310 | _, err = fmt.Fprintf(w, `" 311 | 312 | func %sBytes() ([]byte, error) { 313 | return bindataRead( 314 | _%s, 315 | %q, 316 | ) 317 | } 318 | 319 | `, asset.Func, asset.Func, asset.Name) 320 | return err 321 | } 322 | 323 | func compressedMemcopy(w io.Writer, asset *Asset, r io.Reader) error { 324 | _, err := fmt.Fprintf(w, `var _%s = []byte("`, asset.Func) 325 | if err != nil { 326 | return err 327 | } 328 | 329 | gz := gzip.NewWriter(&StringWriter{Writer: w}) 330 | _, err = io.Copy(gz, r) 331 | gz.Close() 332 | 333 | if err != nil { 334 | return err 335 | } 336 | 337 | _, err = fmt.Fprintf(w, `") 338 | 339 | func %sBytes() ([]byte, error) { 340 | return bindataRead( 341 | _%s, 342 | %q, 343 | ) 344 | } 345 | 346 | `, asset.Func, asset.Func, asset.Name) 347 | return err 348 | } 349 | 350 | func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error { 351 | _, err := fmt.Fprintf(w, `var _%s = "`, asset.Func) 352 | if err != nil { 353 | return err 354 | } 355 | 356 | _, err = io.Copy(&StringWriter{Writer: w}, r) 357 | if err != nil { 358 | return err 359 | } 360 | 361 | _, err = fmt.Fprintf(w, `" 362 | 363 | func %sBytes() ([]byte, error) { 364 | return bindataRead( 365 | _%s, 366 | %q, 367 | ) 368 | } 369 | 370 | `, asset.Func, asset.Func, asset.Name) 371 | return err 372 | } 373 | 374 | func validSanitizedUtf8(b []byte) bool { 375 | if !utf8.Valid(b) { 376 | return false 377 | } 378 | for len(b) > 0 { 379 | r, size := utf8.DecodeRune(b) 380 | if r == 0 { 381 | return false 382 | } 383 | if unicode.In(r, unicode.Cf) { 384 | // staticcheck doesn't like these; fallback to slow decoder 385 | return false 386 | } 387 | b = b[size:] 388 | } 389 | return true 390 | } 391 | 392 | func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error { 393 | _, err := fmt.Fprintf(w, `var _%s = []byte(`, asset.Func) 394 | if err != nil { 395 | return err 396 | } 397 | 398 | b, err := io.ReadAll(r) 399 | if err != nil { 400 | return err 401 | } 402 | if len(b) > 0 && validSanitizedUtf8(b) { 403 | w.Write(sanitize(b)) 404 | } else { 405 | fmt.Fprintf(w, "%+q", b) 406 | } 407 | 408 | _, err = fmt.Fprintf(w, `) 409 | 410 | func %sBytes() ([]byte, error) { 411 | return _%s, nil 412 | } 413 | 414 | `, asset.Func, asset.Func) 415 | return err 416 | } 417 | 418 | func assetReleaseCommon(w io.Writer, c *Config, asset *Asset, digest [sha256.Size]byte) error { 419 | fi, err := os.Stat(asset.Path) 420 | if err != nil { 421 | return err 422 | } 423 | 424 | mode := uint(fi.Mode()) 425 | modTime := fi.ModTime().Unix() 426 | size := fi.Size() 427 | if c.NoMetadata { 428 | mode = 0 429 | modTime = 0 430 | size = 0 431 | } 432 | if c.Mode > 0 { 433 | mode = uint(os.ModePerm) & c.Mode 434 | } 435 | if c.ModTime > 0 { 436 | modTime = c.ModTime 437 | } 438 | _, err = fmt.Fprintf(w, `func %s() (*asset, error) { 439 | bytes, err := %sBytes() 440 | if err != nil { 441 | return nil, err 442 | } 443 | 444 | info := bindataFileInfo{name: %q, size: %d, mode: os.FileMode(%#o), modTime: time.Unix(%d, 0)} 445 | a := &asset{bytes: bytes, info: info, digest: %#v} 446 | return a, nil 447 | } 448 | 449 | `, asset.Func, asset.Func, asset.Name, size, mode, modTime, digest) 450 | return err 451 | } 452 | -------------------------------------------------------------------------------- /release_go112.go: -------------------------------------------------------------------------------- 1 | // +build !go1.13 2 | 3 | package bindata 4 | 5 | const wrappedError = "%v" 6 | -------------------------------------------------------------------------------- /release_go113.go: -------------------------------------------------------------------------------- 1 | // +build go1.13 2 | 3 | package bindata 4 | 5 | const wrappedError = "%w" 6 | -------------------------------------------------------------------------------- /release_test.go: -------------------------------------------------------------------------------- 1 | package bindata 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "strings" 8 | "testing" 9 | ) 10 | 11 | var sanitizeTests = []struct { 12 | in string 13 | out string 14 | }{ 15 | {`hello`, "`hello`"}, 16 | {"hello\nworld", "`hello\nworld`"}, 17 | {"`ello", "(\"`\" + `ello`)"}, 18 | {"`a`e`i`o`u`", "(((\"`\" + `a`) + (\"`\" + (`e` + \"`\"))) + ((`i` + (\"`\" + `o`)) + (\"`\" + (`u` + \"`\"))))"}, 19 | {"\xEF\xBB\xBF`s away!", "(\"\\xEF\\xBB\\xBF\" + (\"`\" + `s away!`))"}, 20 | } 21 | 22 | func TestSanitize(t *testing.T) { 23 | for _, tt := range sanitizeTests { 24 | out := []byte(sanitize([]byte(tt.in))) 25 | if string(out) != tt.out { 26 | t.Errorf("sanitize(%q):\nhave %q\nwant %q", tt.in, out, tt.out) 27 | } 28 | } 29 | } 30 | 31 | func TestEncode(t *testing.T) { 32 | t.Skip("used to test unicode ranges") 33 | data, err := os.ReadFile("testdata/fa.js") 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | w := new(bytes.Buffer) 38 | uncompressed_memcopy(w, &Asset{}, bytes.NewReader(data)) 39 | fmt.Println(w.String()) 40 | t.Fail() 41 | } 42 | 43 | func TestEmptyFile(t *testing.T) { 44 | buf := new(bytes.Buffer) 45 | c := &Config{NoCompress: true, NoMemCopy: false} 46 | err := writeReleaseAsset(buf, c, &Asset{Func: "hello", Path: "testdata/empty/empty_file"}) 47 | if err != nil { 48 | t.Fatal(err) 49 | } 50 | if !strings.Contains(buf.String(), `[]byte("")`) { 51 | t.Errorf("should have got an empty string, got %s", buf.String()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /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 = os.WriteFile(_filePath(dir, name), data, info.Mode()) 29 | if err != nil { 30 | return err 31 | } 32 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 33 | } 34 | 35 | // RestoreAssets restores an asset under the given directory recursively. 36 | func RestoreAssets(dir, name string) error { 37 | children, err := AssetDir(name) 38 | // File 39 | if err != nil { 40 | return RestoreAsset(dir, name) 41 | } 42 | // Dir 43 | for _, child := range children { 44 | err = RestoreAssets(dir, filepath.Join(name, child)) 45 | if err != nil { 46 | return err 47 | } 48 | } 49 | return nil 50 | } 51 | 52 | func _filePath(dir, name string) string { 53 | canonicalName := strings.Replace(name, "\\", "/", -1) 54 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 55 | } 56 | `) 57 | return err 58 | } 59 | -------------------------------------------------------------------------------- /safefile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Dmitry Chestnykh. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // 5 | // Some modifications made: API's were made internal to the package. os.Rename 6 | // hack for old Windows/Plan 9 builds removed; if you are using those systems, 7 | // you won't get atomic rewrites, sorry. 8 | 9 | package bindata 10 | 11 | import ( 12 | "crypto/rand" 13 | "encoding/base32" 14 | "errors" 15 | "io" 16 | "os" 17 | "path/filepath" 18 | "strings" 19 | ) 20 | 21 | // ErrAlreadyCommitted error is returned when calling Commit on a file that 22 | // has been already successfully committed. 23 | var errAlreadyCommitted = errors.New("file already committed") 24 | 25 | type safefileFile struct { 26 | *os.File 27 | origName string 28 | closeFunc func(*safefileFile) error 29 | isClosed bool // if true, temporary file has been closed, but not renamed 30 | isCommitted bool // if true, the file has been successfully committed 31 | } 32 | 33 | func makeTempName(origname, prefix string) (tempname string, err error) { 34 | origname = filepath.Clean(origname) 35 | if len(origname) == 0 || origname[len(origname)-1] == filepath.Separator { 36 | return "", os.ErrInvalid 37 | } 38 | // Generate 10 random bytes. 39 | // This gives 80 bits of entropy, good enough 40 | // for making temporary file name unpredictable. 41 | var rnd [10]byte 42 | if _, err := rand.Read(rnd[:]); err != nil { 43 | return "", err 44 | } 45 | name := prefix + "-" + strings.ToLower(base32.StdEncoding.EncodeToString(rnd[:])) + ".tmp" 46 | return filepath.Join(filepath.Dir(origname), name), nil 47 | } 48 | 49 | // safefileCreate creates a temporary file in the same directory as filename, 50 | // which will be renamed to the given filename when calling Commit. 51 | func safefileCreate(filename string, perm os.FileMode) (*safefileFile, error) { 52 | for { 53 | tempname, err := makeTempName(filename, "sf") 54 | if err != nil { 55 | return nil, err 56 | } 57 | f, err := os.OpenFile(tempname, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) 58 | if err != nil { 59 | if os.IsExist(err) { 60 | continue 61 | } 62 | return nil, err 63 | } 64 | return &safefileFile{ 65 | File: f, 66 | origName: filename, 67 | closeFunc: closeUncommitted, 68 | }, nil 69 | } 70 | } 71 | 72 | // OrigName returns the original filename given to Create. 73 | func (f *safefileFile) OrigName() string { 74 | return f.origName 75 | } 76 | 77 | // Close closes temporary file and removes it. 78 | // If the file has been committed, Close is no-op. 79 | func (f *safefileFile) Close() error { 80 | return f.closeFunc(f) 81 | } 82 | 83 | func closeUncommitted(f *safefileFile) error { 84 | err0 := f.File.Close() 85 | err1 := os.Remove(f.Name()) 86 | f.closeFunc = closeAgainError 87 | if err0 != nil { 88 | return err0 89 | } 90 | return err1 91 | } 92 | 93 | func closeAfterFailedRename(f *safefileFile) error { 94 | // Remove temporary file. 95 | // 96 | // The note from Commit function applies here too, as we may be 97 | // removing a different file. However, since we rely on our temporary 98 | // names being unpredictable, this should not be a concern. 99 | f.closeFunc = closeAgainError 100 | return os.Remove(f.Name()) 101 | } 102 | 103 | func closeCommitted(f *safefileFile) error { 104 | // noop 105 | return nil 106 | } 107 | 108 | func closeAgainError(f *safefileFile) error { 109 | return os.ErrInvalid 110 | } 111 | 112 | // Commit safely commits data into the original file by syncing temporary 113 | // file to disk, closing it and renaming to the original file name. 114 | // 115 | // In case of success, the temporary file is closed and no longer exists 116 | // on disk. It is safe to call Close after Commit: the operation will do 117 | // nothing. 118 | // 119 | // In case of error, the temporary file is still opened and exists on disk; 120 | // it must be closed by callers by calling Close or by trying to commit again. 121 | 122 | // Note that when trying to Commit again after a failed Commit when the file 123 | // has been closed, but not renamed to its original name (the new commit will 124 | // try again to rename it), safefile cannot guarantee that the temporary file 125 | // has not been changed, or that it is the same temporary file we were dealing 126 | // with. However, since the temporary name is unpredictable, it is unlikely 127 | // that this happened accidentally. If complete atomicity is needed, do not 128 | // Commit again after error, write the file again. 129 | func (f *safefileFile) Commit() error { 130 | if f.isCommitted { 131 | return errAlreadyCommitted 132 | } 133 | if !f.isClosed { 134 | // Sync to disk. 135 | err := f.Sync() 136 | if err != nil { 137 | return err 138 | } 139 | // Close underlying os.File. 140 | err = f.File.Close() 141 | if err != nil { 142 | return err 143 | } 144 | f.isClosed = true 145 | } 146 | err := os.Rename(f.Name(), f.origName) 147 | if err != nil { 148 | f.closeFunc = closeAfterFailedRename 149 | return err 150 | } 151 | f.closeFunc = closeCommitted 152 | f.isCommitted = true 153 | return nil 154 | } 155 | 156 | // WriteFile is a safe analog of ioutil.WriteFile. 157 | func safefileWriteFile(filename string, data []byte, perm os.FileMode) error { 158 | f, err := safefileCreate(filename, perm) 159 | if err != nil { 160 | return err 161 | } 162 | defer f.Close() 163 | n, err := f.Write(data) 164 | if err != nil { 165 | return err 166 | } 167 | if err == nil && n < len(data) { 168 | err = io.ErrShortWrite 169 | return err 170 | } 171 | return f.Commit() 172 | } 173 | -------------------------------------------------------------------------------- /safefile_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Dmitry Chestnykh. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bindata 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "os" 11 | "path/filepath" 12 | "testing" 13 | "time" 14 | ) 15 | 16 | func ensureFileContains(name, data string) error { 17 | b, err := os.ReadFile(name) 18 | if err != nil { 19 | return err 20 | } 21 | if string(b) != data { 22 | return fmt.Errorf("wrong data in file: expected %s, got %s", data, string(b)) 23 | } 24 | return nil 25 | } 26 | 27 | func tempFileName(count int) string { 28 | return filepath.Join(os.TempDir(), fmt.Sprintf("safefile-test-%d-%x", count, time.Now().UnixNano())) 29 | } 30 | 31 | var testData = "Hello, this is a test data" 32 | 33 | func testInTempDir() error { 34 | name := tempFileName(0) 35 | defer os.Remove(name) 36 | f, err := safefileCreate(name, 0666) 37 | if err != nil { 38 | return err 39 | } 40 | if name != f.OrigName() { 41 | f.Close() 42 | return fmt.Errorf("name %q differs from OrigName: %q", name, f.OrigName()) 43 | } 44 | _, err = io.WriteString(f, testData) 45 | if err != nil { 46 | f.Close() 47 | return err 48 | } 49 | err = f.Commit() 50 | if err != nil { 51 | f.Close() 52 | return err 53 | } 54 | err = f.Close() 55 | if err != nil { 56 | return err 57 | } 58 | return ensureFileContains(name, testData) 59 | } 60 | 61 | func TestMakeTempName(t *testing.T) { 62 | // Make sure temp name is random. 63 | m := make(map[string]bool) 64 | for i := 0; i < 100; i++ { 65 | name, err := makeTempName("/tmp", "sf") 66 | if err != nil { 67 | t.Fatal(err) 68 | } 69 | if m[name] { 70 | t.Fatal("repeated file name") 71 | } 72 | m[name] = true 73 | } 74 | } 75 | 76 | func TestFile(t *testing.T) { 77 | err := testInTempDir() 78 | if err != nil { 79 | t.Fatal(err) 80 | } 81 | } 82 | 83 | func TestWriteFile(t *testing.T) { 84 | name := tempFileName(1) 85 | err := safefileWriteFile(name, []byte(testData), 0666) 86 | if err != nil { 87 | t.Fatal(err) 88 | } 89 | err = ensureFileContains(name, testData) 90 | if err != nil { 91 | os.Remove(name) 92 | t.Fatal(err) 93 | } 94 | os.Remove(name) 95 | } 96 | 97 | func TestAbandon(t *testing.T) { 98 | name := tempFileName(2) 99 | f, err := safefileCreate(name, 0666) 100 | if err != nil { 101 | t.Fatal(err) 102 | } 103 | err = f.Close() 104 | if err != nil { 105 | t.Fatalf("Abandon failed: %s", err) 106 | } 107 | // Make sure temporary file doesn't exist. 108 | _, err = os.Stat(f.Name()) 109 | if err != nil && !os.IsNotExist(err) { 110 | t.Fatal(err) 111 | } 112 | } 113 | 114 | func TestDoubleCommit(t *testing.T) { 115 | name := tempFileName(3) 116 | f, err := safefileCreate(name, 0666) 117 | if err != nil { 118 | t.Fatal(err) 119 | } 120 | err = f.Commit() 121 | if err != nil { 122 | os.Remove(name) 123 | t.Fatalf("First commit failed: %s", err) 124 | } 125 | err = f.Commit() 126 | if err != errAlreadyCommitted { 127 | os.Remove(name) 128 | t.Fatalf("Second commit didn't fail: %s", err) 129 | } 130 | err = f.Close() 131 | if err != nil { 132 | os.Remove(name) 133 | t.Fatalf("Close failed: %s", err) 134 | } 135 | os.Remove(name) 136 | } 137 | 138 | func TestOverwriting(t *testing.T) { 139 | name := tempFileName(4) 140 | defer os.Remove(name) 141 | 142 | olddata := "This is old data" 143 | err := os.WriteFile(name, []byte(olddata), 0600) 144 | if err != nil { 145 | t.Fatal(err) 146 | } 147 | 148 | newdata := "This is new data" 149 | err = safefileWriteFile(name, []byte(newdata), 0600) 150 | if err != nil { 151 | t.Fatal(err) 152 | } 153 | 154 | err = ensureFileContains(name, newdata) 155 | if err != nil { 156 | t.Fatal(err) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /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 golint $(FILES:.go=.checked) 5 | 6 | out/%.checked: out/%.go 7 | errcheck $< 8 | go vet --all $< 9 | golint $< 10 | 11 | $(GOPATH)/bin/go-bindata: $(wildcard ../*.go) $(wildcard ../**/*.go) 12 | go install -race ../... 13 | $(GOPATH)/bin/go-bindata --version 14 | 15 | out/compress-memcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 16 | GO_BINDATA_TEST=true $(GOPATH)/bin/go-bindata --modtime=1136214245 -o $@ in/... 17 | 18 | out/compress-nomemcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 19 | GO_BINDATA_TEST=true $(GOPATH)/bin/go-bindata --modtime=1136214245 --nomemcopy -o $@ in/... 20 | 21 | out/debug.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 22 | GO_BINDATA_TEST=true $(GOPATH)/bin/go-bindata --modtime=1136214245 --debug -o $@ in/... 23 | 24 | out/nocompress-memcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 25 | GO_BINDATA_TEST=true $(GOPATH)/bin/go-bindata --modtime=1136214245 --nocompress -o $@ in/... 26 | 27 | out/nocompress-nomemcopy.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 28 | GO_BINDATA_TEST=true $(GOPATH)/bin/go-bindata --modtime=1136214245 --nocompress -nomemcopy -o $@ in/... 29 | 30 | out/prefix.go: $(wildcard in/**/*) $(GOPATH)/bin/go-bindata 31 | GO_BINDATA_TEST=true $(GOPATH)/bin/go-bindata --modtime=1136214245 --prefix in -o $@ in/... 32 | 33 | errcheck: 34 | go get github.com/kisielk/errcheck 35 | 36 | golint: 37 | go get golang.org/x/lint/golint 38 | -------------------------------------------------------------------------------- /testdata/benchmark/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/0.jpg -------------------------------------------------------------------------------- /testdata/benchmark/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/1.jpg -------------------------------------------------------------------------------- /testdata/benchmark/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/10.jpg -------------------------------------------------------------------------------- /testdata/benchmark/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/11.jpg -------------------------------------------------------------------------------- /testdata/benchmark/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/12.jpg -------------------------------------------------------------------------------- /testdata/benchmark/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/13.jpg -------------------------------------------------------------------------------- /testdata/benchmark/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/14.jpg -------------------------------------------------------------------------------- /testdata/benchmark/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/15.jpg -------------------------------------------------------------------------------- /testdata/benchmark/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/16.jpg -------------------------------------------------------------------------------- /testdata/benchmark/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/17.jpg -------------------------------------------------------------------------------- /testdata/benchmark/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/18.jpg -------------------------------------------------------------------------------- /testdata/benchmark/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/19.jpg -------------------------------------------------------------------------------- /testdata/benchmark/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/2.jpg -------------------------------------------------------------------------------- /testdata/benchmark/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/20.jpg -------------------------------------------------------------------------------- /testdata/benchmark/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/21.jpg -------------------------------------------------------------------------------- /testdata/benchmark/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/22.jpg -------------------------------------------------------------------------------- /testdata/benchmark/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/23.jpg -------------------------------------------------------------------------------- /testdata/benchmark/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/24.jpg -------------------------------------------------------------------------------- /testdata/benchmark/25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/25.jpg -------------------------------------------------------------------------------- /testdata/benchmark/26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/26.jpg -------------------------------------------------------------------------------- /testdata/benchmark/27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/27.jpg -------------------------------------------------------------------------------- /testdata/benchmark/28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/28.jpg -------------------------------------------------------------------------------- /testdata/benchmark/29.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/29.jpg -------------------------------------------------------------------------------- /testdata/benchmark/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/3.jpg -------------------------------------------------------------------------------- /testdata/benchmark/30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/30.jpg -------------------------------------------------------------------------------- /testdata/benchmark/31.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/31.jpg -------------------------------------------------------------------------------- /testdata/benchmark/32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/32.jpg -------------------------------------------------------------------------------- /testdata/benchmark/33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/33.jpg -------------------------------------------------------------------------------- /testdata/benchmark/34.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/34.jpg -------------------------------------------------------------------------------- /testdata/benchmark/35.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/35.jpg -------------------------------------------------------------------------------- /testdata/benchmark/36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/36.jpg -------------------------------------------------------------------------------- /testdata/benchmark/37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/37.jpg -------------------------------------------------------------------------------- /testdata/benchmark/38.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/38.jpg -------------------------------------------------------------------------------- /testdata/benchmark/39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/39.jpg -------------------------------------------------------------------------------- /testdata/benchmark/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/4.jpg -------------------------------------------------------------------------------- /testdata/benchmark/40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/40.jpg -------------------------------------------------------------------------------- /testdata/benchmark/41.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/41.jpg -------------------------------------------------------------------------------- /testdata/benchmark/42.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/42.jpg -------------------------------------------------------------------------------- /testdata/benchmark/43.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/43.jpg -------------------------------------------------------------------------------- /testdata/benchmark/44.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/44.jpg -------------------------------------------------------------------------------- /testdata/benchmark/45.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/45.jpg -------------------------------------------------------------------------------- /testdata/benchmark/46.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/46.jpg -------------------------------------------------------------------------------- /testdata/benchmark/47.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/47.jpg -------------------------------------------------------------------------------- /testdata/benchmark/48.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/48.jpg -------------------------------------------------------------------------------- /testdata/benchmark/49.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/49.jpg -------------------------------------------------------------------------------- /testdata/benchmark/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/5.jpg -------------------------------------------------------------------------------- /testdata/benchmark/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/6.jpg -------------------------------------------------------------------------------- /testdata/benchmark/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/7.jpg -------------------------------------------------------------------------------- /testdata/benchmark/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/8.jpg -------------------------------------------------------------------------------- /testdata/benchmark/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/benchmark/9.jpg -------------------------------------------------------------------------------- /testdata/download-photos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | main() { 7 | local width=1600 8 | local height=1200 9 | local count=0 10 | while [[ "${count}" -lt 50 ]]; do 11 | curl "http://placekitten.com/${width}/${height}" > "testdata/benchmark/${count}.jpg" 12 | count=$(expr $count + 1) 13 | width=$(expr $width + 1) 14 | height=$(expr $height + 1) 15 | done 16 | } 17 | 18 | main "$@" 19 | -------------------------------------------------------------------------------- /testdata/dupname/foo/bar: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/dupname/foo_bar: -------------------------------------------------------------------------------- 1 | // sample file 2 | -------------------------------------------------------------------------------- /testdata/empty/empty_file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinburke/go-bindata/2394b8291982849e5d021d3e2cee870ce63fe8a2/testdata/empty/empty_file -------------------------------------------------------------------------------- /testdata/fa.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.7 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="لطفاً "+t+" کاراکتر را حذف نمایید";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لطفاً تعداد "+t+" کاراکتر یا بیشتر وارد نمایید";return n},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(e){var t="شما تنها می‌توانید "+e.maximum+" آیتم را انتخاب نمایید";return t},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),{define:e.define,require:e.require}})(); -------------------------------------------------------------------------------- /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. DO NOT EDIT. 2 | // sources: 3 | // in/a/test.asset (15B) 4 | // in/b/test.asset (15B) 5 | // in/c/test.asset (15B) 6 | // in/test.asset (15B) 7 | 8 | package main 9 | 10 | import ( 11 | "bytes" 12 | "compress/gzip" 13 | "crypto/sha256" 14 | "fmt" 15 | "io" 16 | "os" 17 | "path/filepath" 18 | "strings" 19 | "time" 20 | ) 21 | 22 | func bindataRead(data []byte, name string) ([]byte, error) { 23 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 24 | if err != nil { 25 | return nil, fmt.Errorf("read %q: %w", name, err) 26 | } 27 | 28 | var buf bytes.Buffer 29 | _, err = io.Copy(&buf, gz) 30 | clErr := gz.Close() 31 | 32 | if err != nil { 33 | return nil, fmt.Errorf("read %q: %w", name, err) 34 | } 35 | if clErr != nil { 36 | return nil, err 37 | } 38 | 39 | return buf.Bytes(), nil 40 | } 41 | 42 | type asset struct { 43 | bytes []byte 44 | info os.FileInfo 45 | digest [sha256.Size]byte 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\x00\x00\x00\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(0644), modTime: time.Unix(1136214245, 0)} 90 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 91 | return a, nil 92 | } 93 | 94 | var _inBTestAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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(0644), modTime: time.Unix(1136214245, 0)} 110 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 111 | return a, nil 112 | } 113 | 114 | var _inCTestAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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(0644), modTime: time.Unix(1136214245, 0)} 130 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 131 | return a, nil 132 | } 133 | 134 | var _inTestAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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(0644), modTime: time.Unix(1136214245, 0)} 150 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 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 | canonicalName := strings.Replace(name, "\\", "/", -1) 159 | if f, ok := _bindata[canonicalName]; 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 | // AssetString returns the asset contents as a string (instead of a []byte). 170 | func AssetString(name string) (string, error) { 171 | data, err := Asset(name) 172 | return string(data), err 173 | } 174 | 175 | // MustAsset is like Asset but panics when Asset would return an error. 176 | // It simplifies safe initialization of global variables. 177 | func MustAsset(name string) []byte { 178 | a, err := Asset(name) 179 | if err != nil { 180 | panic("asset: Asset(" + name + "): " + err.Error()) 181 | } 182 | 183 | return a 184 | } 185 | 186 | // MustAssetString is like AssetString but panics when Asset would return an 187 | // error. It simplifies safe initialization of global variables. 188 | func MustAssetString(name string) string { 189 | return string(MustAsset(name)) 190 | } 191 | 192 | // AssetInfo loads and returns the asset info for the given name. 193 | // It returns an error if the asset could not be found or 194 | // could not be loaded. 195 | func AssetInfo(name string) (os.FileInfo, error) { 196 | canonicalName := strings.Replace(name, "\\", "/", -1) 197 | if f, ok := _bindata[canonicalName]; ok { 198 | a, err := f() 199 | if err != nil { 200 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 201 | } 202 | return a.info, nil 203 | } 204 | return nil, fmt.Errorf("AssetInfo %s not found", name) 205 | } 206 | 207 | // AssetDigest returns the digest of the file with the given name. It returns an 208 | // error if the asset could not be found or the digest could not be loaded. 209 | func AssetDigest(name string) ([sha256.Size]byte, error) { 210 | canonicalName := strings.Replace(name, "\\", "/", -1) 211 | if f, ok := _bindata[canonicalName]; ok { 212 | a, err := f() 213 | if err != nil { 214 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 215 | } 216 | return a.digest, nil 217 | } 218 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 219 | } 220 | 221 | // Digests returns a map of all known files and their checksums. 222 | func Digests() (map[string][sha256.Size]byte, error) { 223 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 224 | for name := range _bindata { 225 | a, err := _bindata[name]() 226 | if err != nil { 227 | return nil, err 228 | } 229 | mp[name] = a.digest 230 | } 231 | return mp, nil 232 | } 233 | 234 | // AssetNames returns the names of the assets. 235 | func AssetNames() []string { 236 | names := make([]string, 0, len(_bindata)) 237 | for name := range _bindata { 238 | names = append(names, name) 239 | } 240 | return names 241 | } 242 | 243 | // _bindata is a table, holding each asset generator, mapped to its name. 244 | var _bindata = map[string]func() (*asset, error){ 245 | "in/a/test.asset": inATestAsset, 246 | "in/b/test.asset": inBTestAsset, 247 | "in/c/test.asset": inCTestAsset, 248 | "in/test.asset": inTestAsset, 249 | } 250 | 251 | // AssetDebug is true if the assets were built with the debug flag enabled. 252 | const AssetDebug = false 253 | 254 | // AssetDir returns the file names below a certain 255 | // directory embedded in the file by go-bindata. 256 | // For example if you run go-bindata on data/... and data contains the 257 | // following hierarchy: 258 | // 259 | // data/ 260 | // foo.txt 261 | // img/ 262 | // a.png 263 | // b.png 264 | // 265 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 266 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 267 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 268 | // AssetDir("") will return []string{"data"}. 269 | func AssetDir(name string) ([]string, error) { 270 | node := _bintree 271 | if len(name) != 0 { 272 | canonicalName := strings.Replace(name, "\\", "/", -1) 273 | pathList := strings.Split(canonicalName, "/") 274 | for _, p := range pathList { 275 | node = node.Children[p] 276 | if node == nil { 277 | return nil, fmt.Errorf("Asset %s not found", name) 278 | } 279 | } 280 | } 281 | if node.Func != nil { 282 | return nil, fmt.Errorf("Asset %s not found", name) 283 | } 284 | rv := make([]string, 0, len(node.Children)) 285 | for childName := range node.Children { 286 | rv = append(rv, childName) 287 | } 288 | return rv, nil 289 | } 290 | 291 | type bintree struct { 292 | Func func() (*asset, error) 293 | Children map[string]*bintree 294 | } 295 | 296 | var _bintree = &bintree{nil, map[string]*bintree{ 297 | "in": {nil, map[string]*bintree{ 298 | "a": {nil, map[string]*bintree{ 299 | "test.asset": {inATestAsset, map[string]*bintree{}}, 300 | }}, 301 | "b": {nil, map[string]*bintree{ 302 | "test.asset": {inBTestAsset, map[string]*bintree{}}, 303 | }}, 304 | "c": {nil, map[string]*bintree{ 305 | "test.asset": {inCTestAsset, map[string]*bintree{}}, 306 | }}, 307 | "test.asset": {inTestAsset, map[string]*bintree{}}, 308 | }}, 309 | }} 310 | 311 | // RestoreAsset restores an asset under the given directory. 312 | func RestoreAsset(dir, name string) error { 313 | data, err := Asset(name) 314 | if err != nil { 315 | return err 316 | } 317 | info, err := AssetInfo(name) 318 | if err != nil { 319 | return err 320 | } 321 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 322 | if err != nil { 323 | return err 324 | } 325 | err = os.WriteFile(_filePath(dir, name), data, info.Mode()) 326 | if err != nil { 327 | return err 328 | } 329 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 330 | } 331 | 332 | // RestoreAssets restores an asset under the given directory recursively. 333 | func RestoreAssets(dir, name string) error { 334 | children, err := AssetDir(name) 335 | // File 336 | if err != nil { 337 | return RestoreAsset(dir, name) 338 | } 339 | // Dir 340 | for _, child := range children { 341 | err = RestoreAssets(dir, filepath.Join(name, child)) 342 | if err != nil { 343 | return err 344 | } 345 | } 346 | return nil 347 | } 348 | 349 | func _filePath(dir, name string) string { 350 | canonicalName := strings.Replace(name, "\\", "/", -1) 351 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 352 | } 353 | -------------------------------------------------------------------------------- /testdata/out/compress-nomemcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. DO NOT EDIT. 2 | // sources: 3 | // in/a/test.asset (15B) 4 | // in/b/test.asset (15B) 5 | // in/c/test.asset (15B) 6 | // in/test.asset (15B) 7 | 8 | package main 9 | 10 | import ( 11 | "bytes" 12 | "compress/gzip" 13 | "crypto/sha256" 14 | "fmt" 15 | "io" 16 | "os" 17 | "path/filepath" 18 | "strings" 19 | "time" 20 | ) 21 | 22 | func bindataRead(data, name string) ([]byte, error) { 23 | gz, err := gzip.NewReader(strings.NewReader(data)) 24 | if err != nil { 25 | return nil, fmt.Errorf("read %q: %w", name, err) 26 | } 27 | 28 | var buf bytes.Buffer 29 | _, err = io.Copy(&buf, gz) 30 | 31 | if err != nil { 32 | return nil, fmt.Errorf("read %q: %w", name, err) 33 | } 34 | 35 | clErr := gz.Close() 36 | if clErr != nil { 37 | return nil, clErr 38 | } 39 | 40 | return buf.Bytes(), nil 41 | } 42 | 43 | type asset struct { 44 | bytes []byte 45 | info os.FileInfo 46 | digest [sha256.Size]byte 47 | } 48 | 49 | type bindataFileInfo struct { 50 | name string 51 | size int64 52 | mode os.FileMode 53 | modTime time.Time 54 | } 55 | 56 | func (fi bindataFileInfo) Name() string { 57 | return fi.name 58 | } 59 | func (fi bindataFileInfo) Size() int64 { 60 | return fi.size 61 | } 62 | func (fi bindataFileInfo) Mode() os.FileMode { 63 | return fi.mode 64 | } 65 | func (fi bindataFileInfo) ModTime() time.Time { 66 | return fi.modTime 67 | } 68 | func (fi bindataFileInfo) IsDir() bool { 69 | return false 70 | } 71 | func (fi bindataFileInfo) Sys() interface{} { 72 | return nil 73 | } 74 | 75 | var _inATestAsset = "\x1f\x8b\x08\x00\x00\x00\x00\x00\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" 76 | 77 | func inATestAssetBytes() ([]byte, error) { 78 | return bindataRead( 79 | _inATestAsset, 80 | "in/a/test.asset", 81 | ) 82 | } 83 | 84 | func inATestAsset() (*asset, error) { 85 | bytes, err := inATestAssetBytes() 86 | if err != nil { 87 | return nil, err 88 | } 89 | 90 | info := bindataFileInfo{name: "in/a/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 91 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 92 | return a, nil 93 | } 94 | 95 | var _inBTestAsset = "\x1f\x8b\x08\x00\x00\x00\x00\x00\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" 96 | 97 | func inBTestAssetBytes() ([]byte, error) { 98 | return bindataRead( 99 | _inBTestAsset, 100 | "in/b/test.asset", 101 | ) 102 | } 103 | 104 | func inBTestAsset() (*asset, error) { 105 | bytes, err := inBTestAssetBytes() 106 | if err != nil { 107 | return nil, err 108 | } 109 | 110 | info := bindataFileInfo{name: "in/b/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 111 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 112 | return a, nil 113 | } 114 | 115 | var _inCTestAsset = "\x1f\x8b\x08\x00\x00\x00\x00\x00\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" 116 | 117 | func inCTestAssetBytes() ([]byte, error) { 118 | return bindataRead( 119 | _inCTestAsset, 120 | "in/c/test.asset", 121 | ) 122 | } 123 | 124 | func inCTestAsset() (*asset, error) { 125 | bytes, err := inCTestAssetBytes() 126 | if err != nil { 127 | return nil, err 128 | } 129 | 130 | info := bindataFileInfo{name: "in/c/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 131 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 132 | return a, nil 133 | } 134 | 135 | var _inTestAsset = "\x1f\x8b\x08\x00\x00\x00\x00\x00\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" 136 | 137 | func inTestAssetBytes() ([]byte, error) { 138 | return bindataRead( 139 | _inTestAsset, 140 | "in/test.asset", 141 | ) 142 | } 143 | 144 | func inTestAsset() (*asset, error) { 145 | bytes, err := inTestAssetBytes() 146 | if err != nil { 147 | return nil, err 148 | } 149 | 150 | info := bindataFileInfo{name: "in/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 151 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 152 | return a, nil 153 | } 154 | 155 | // Asset loads and returns the asset for the given name. 156 | // It returns an error if the asset could not be found or 157 | // could not be loaded. 158 | func Asset(name string) ([]byte, error) { 159 | canonicalName := strings.Replace(name, "\\", "/", -1) 160 | if f, ok := _bindata[canonicalName]; ok { 161 | a, err := f() 162 | if err != nil { 163 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 164 | } 165 | return a.bytes, nil 166 | } 167 | return nil, fmt.Errorf("Asset %s not found", name) 168 | } 169 | 170 | // AssetString returns the asset contents as a string (instead of a []byte). 171 | func AssetString(name string) (string, error) { 172 | data, err := Asset(name) 173 | return string(data), err 174 | } 175 | 176 | // MustAsset is like Asset but panics when Asset would return an error. 177 | // It simplifies safe initialization of global variables. 178 | func MustAsset(name string) []byte { 179 | a, err := Asset(name) 180 | if err != nil { 181 | panic("asset: Asset(" + name + "): " + err.Error()) 182 | } 183 | 184 | return a 185 | } 186 | 187 | // MustAssetString is like AssetString but panics when Asset would return an 188 | // error. It simplifies safe initialization of global variables. 189 | func MustAssetString(name string) string { 190 | return string(MustAsset(name)) 191 | } 192 | 193 | // AssetInfo loads and returns the asset info for the given name. 194 | // It returns an error if the asset could not be found or 195 | // could not be loaded. 196 | func AssetInfo(name string) (os.FileInfo, error) { 197 | canonicalName := strings.Replace(name, "\\", "/", -1) 198 | if f, ok := _bindata[canonicalName]; ok { 199 | a, err := f() 200 | if err != nil { 201 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 202 | } 203 | return a.info, nil 204 | } 205 | return nil, fmt.Errorf("AssetInfo %s not found", name) 206 | } 207 | 208 | // AssetDigest returns the digest of the file with the given name. It returns an 209 | // error if the asset could not be found or the digest could not be loaded. 210 | func AssetDigest(name string) ([sha256.Size]byte, error) { 211 | canonicalName := strings.Replace(name, "\\", "/", -1) 212 | if f, ok := _bindata[canonicalName]; ok { 213 | a, err := f() 214 | if err != nil { 215 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 216 | } 217 | return a.digest, nil 218 | } 219 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 220 | } 221 | 222 | // Digests returns a map of all known files and their checksums. 223 | func Digests() (map[string][sha256.Size]byte, error) { 224 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 225 | for name := range _bindata { 226 | a, err := _bindata[name]() 227 | if err != nil { 228 | return nil, err 229 | } 230 | mp[name] = a.digest 231 | } 232 | return mp, nil 233 | } 234 | 235 | // AssetNames returns the names of the assets. 236 | func AssetNames() []string { 237 | names := make([]string, 0, len(_bindata)) 238 | for name := range _bindata { 239 | names = append(names, name) 240 | } 241 | return names 242 | } 243 | 244 | // _bindata is a table, holding each asset generator, mapped to its name. 245 | var _bindata = map[string]func() (*asset, error){ 246 | "in/a/test.asset": inATestAsset, 247 | "in/b/test.asset": inBTestAsset, 248 | "in/c/test.asset": inCTestAsset, 249 | "in/test.asset": inTestAsset, 250 | } 251 | 252 | // AssetDebug is true if the assets were built with the debug flag enabled. 253 | const AssetDebug = false 254 | 255 | // AssetDir returns the file names below a certain 256 | // directory embedded in the file by go-bindata. 257 | // For example if you run go-bindata on data/... and data contains the 258 | // following hierarchy: 259 | // 260 | // data/ 261 | // foo.txt 262 | // img/ 263 | // a.png 264 | // b.png 265 | // 266 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 267 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 268 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 269 | // AssetDir("") will return []string{"data"}. 270 | func AssetDir(name string) ([]string, error) { 271 | node := _bintree 272 | if len(name) != 0 { 273 | canonicalName := strings.Replace(name, "\\", "/", -1) 274 | pathList := strings.Split(canonicalName, "/") 275 | for _, p := range pathList { 276 | node = node.Children[p] 277 | if node == nil { 278 | return nil, fmt.Errorf("Asset %s not found", name) 279 | } 280 | } 281 | } 282 | if node.Func != nil { 283 | return nil, fmt.Errorf("Asset %s not found", name) 284 | } 285 | rv := make([]string, 0, len(node.Children)) 286 | for childName := range node.Children { 287 | rv = append(rv, childName) 288 | } 289 | return rv, nil 290 | } 291 | 292 | type bintree struct { 293 | Func func() (*asset, error) 294 | Children map[string]*bintree 295 | } 296 | 297 | var _bintree = &bintree{nil, map[string]*bintree{ 298 | "in": {nil, map[string]*bintree{ 299 | "a": {nil, map[string]*bintree{ 300 | "test.asset": {inATestAsset, map[string]*bintree{}}, 301 | }}, 302 | "b": {nil, map[string]*bintree{ 303 | "test.asset": {inBTestAsset, map[string]*bintree{}}, 304 | }}, 305 | "c": {nil, map[string]*bintree{ 306 | "test.asset": {inCTestAsset, map[string]*bintree{}}, 307 | }}, 308 | "test.asset": {inTestAsset, map[string]*bintree{}}, 309 | }}, 310 | }} 311 | 312 | // RestoreAsset restores an asset under the given directory. 313 | func RestoreAsset(dir, name string) error { 314 | data, err := Asset(name) 315 | if err != nil { 316 | return err 317 | } 318 | info, err := AssetInfo(name) 319 | if err != nil { 320 | return err 321 | } 322 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 323 | if err != nil { 324 | return err 325 | } 326 | err = os.WriteFile(_filePath(dir, name), data, info.Mode()) 327 | if err != nil { 328 | return err 329 | } 330 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 331 | } 332 | 333 | // RestoreAssets restores an asset under the given directory recursively. 334 | func RestoreAssets(dir, name string) error { 335 | children, err := AssetDir(name) 336 | // File 337 | if err != nil { 338 | return RestoreAsset(dir, name) 339 | } 340 | // Dir 341 | for _, child := range children { 342 | err = RestoreAssets(dir, filepath.Join(name, child)) 343 | if err != nil { 344 | return err 345 | } 346 | } 347 | return nil 348 | } 349 | 350 | func _filePath(dir, name string) string { 351 | canonicalName := strings.Replace(name, "\\", "/", -1) 352 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 353 | } 354 | -------------------------------------------------------------------------------- /testdata/out/debug.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. DO NOT EDIT. 2 | // sources: 3 | // in/a/test.asset (15B) 4 | // in/b/test.asset (15B) 5 | // in/c/test.asset (15B) 6 | // in/test.asset (15B) 7 | 8 | package main 9 | 10 | import ( 11 | "crypto/sha256" 12 | "fmt" 13 | "os" 14 | "path/filepath" 15 | "strings" 16 | ) 17 | 18 | // bindataRead reads the given file from disk. It returns an error on failure. 19 | func bindataRead(path, name string) ([]byte, error) { 20 | buf, err := os.ReadFile(path) 21 | if err != nil { 22 | err = fmt.Errorf("Error reading asset %s at %s: %w", name, path, err) 23 | } 24 | return buf, err 25 | } 26 | 27 | type asset struct { 28 | bytes []byte 29 | info os.FileInfo 30 | digest [sha256.Size]byte 31 | } 32 | 33 | // inATestAsset reads file data from disk. It returns an error on failure. 34 | func inATestAsset() (*asset, error) { 35 | path := "/test/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: %w", 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 := "/test/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: %w", 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 := "/test/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: %w", 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 := "/test/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: %w", 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 | canonicalName := strings.Replace(name, "\\", "/", -1) 110 | if f, ok := _bindata[canonicalName]; 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 | // AssetString returns the asset contents as a string (instead of a []byte). 121 | func AssetString(name string) (string, error) { 122 | data, err := Asset(name) 123 | return string(data), err 124 | } 125 | 126 | // MustAsset is like Asset but panics when Asset would return an error. 127 | // It simplifies safe initialization of global variables. 128 | func MustAsset(name string) []byte { 129 | a, err := Asset(name) 130 | if err != nil { 131 | panic("asset: Asset(" + name + "): " + err.Error()) 132 | } 133 | 134 | return a 135 | } 136 | 137 | // MustAssetString is like AssetString but panics when Asset would return an 138 | // error. It simplifies safe initialization of global variables. 139 | func MustAssetString(name string) string { 140 | return string(MustAsset(name)) 141 | } 142 | 143 | // AssetInfo loads and returns the asset info for the given name. 144 | // It returns an error if the asset could not be found or 145 | // could not be loaded. 146 | func AssetInfo(name string) (os.FileInfo, error) { 147 | canonicalName := strings.Replace(name, "\\", "/", -1) 148 | if f, ok := _bindata[canonicalName]; ok { 149 | a, err := f() 150 | if err != nil { 151 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 152 | } 153 | return a.info, nil 154 | } 155 | return nil, fmt.Errorf("AssetInfo %s not found", name) 156 | } 157 | 158 | // AssetDigest returns the digest of the file with the given name. It returns an 159 | // error if the asset could not be found or the digest could not be loaded. 160 | func AssetDigest(name string) ([sha256.Size]byte, error) { 161 | canonicalName := strings.Replace(name, "\\", "/", -1) 162 | if f, ok := _bindata[canonicalName]; ok { 163 | a, err := f() 164 | if err != nil { 165 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 166 | } 167 | return a.digest, nil 168 | } 169 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 170 | } 171 | 172 | // Digests returns a map of all known files and their checksums. 173 | func Digests() (map[string][sha256.Size]byte, error) { 174 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 175 | for name := range _bindata { 176 | a, err := _bindata[name]() 177 | if err != nil { 178 | return nil, err 179 | } 180 | mp[name] = a.digest 181 | } 182 | return mp, nil 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 | // AssetDebug is true if the assets were built with the debug flag enabled. 203 | const AssetDebug = true 204 | 205 | // AssetDir returns the file names below a certain 206 | // directory embedded in the file by go-bindata. 207 | // For example if you run go-bindata on data/... and data contains the 208 | // following hierarchy: 209 | // 210 | // data/ 211 | // foo.txt 212 | // img/ 213 | // a.png 214 | // b.png 215 | // 216 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 217 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 218 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 219 | // AssetDir("") will return []string{"data"}. 220 | func AssetDir(name string) ([]string, error) { 221 | node := _bintree 222 | if len(name) != 0 { 223 | canonicalName := strings.Replace(name, "\\", "/", -1) 224 | pathList := strings.Split(canonicalName, "/") 225 | for _, p := range pathList { 226 | node = node.Children[p] 227 | if node == nil { 228 | return nil, fmt.Errorf("Asset %s not found", name) 229 | } 230 | } 231 | } 232 | if node.Func != nil { 233 | return nil, fmt.Errorf("Asset %s not found", name) 234 | } 235 | rv := make([]string, 0, len(node.Children)) 236 | for childName := range node.Children { 237 | rv = append(rv, childName) 238 | } 239 | return rv, nil 240 | } 241 | 242 | type bintree struct { 243 | Func func() (*asset, error) 244 | Children map[string]*bintree 245 | } 246 | 247 | var _bintree = &bintree{nil, map[string]*bintree{ 248 | "in": {nil, map[string]*bintree{ 249 | "a": {nil, map[string]*bintree{ 250 | "test.asset": {inATestAsset, map[string]*bintree{}}, 251 | }}, 252 | "b": {nil, map[string]*bintree{ 253 | "test.asset": {inBTestAsset, map[string]*bintree{}}, 254 | }}, 255 | "c": {nil, map[string]*bintree{ 256 | "test.asset": {inCTestAsset, map[string]*bintree{}}, 257 | }}, 258 | "test.asset": {inTestAsset, map[string]*bintree{}}, 259 | }}, 260 | }} 261 | 262 | // RestoreAsset restores an asset under the given directory. 263 | func RestoreAsset(dir, name string) error { 264 | data, err := Asset(name) 265 | if err != nil { 266 | return err 267 | } 268 | info, err := AssetInfo(name) 269 | if err != nil { 270 | return err 271 | } 272 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 273 | if err != nil { 274 | return err 275 | } 276 | err = os.WriteFile(_filePath(dir, name), data, info.Mode()) 277 | if err != nil { 278 | return err 279 | } 280 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 281 | } 282 | 283 | // RestoreAssets restores an asset under the given directory recursively. 284 | func RestoreAssets(dir, name string) error { 285 | children, err := AssetDir(name) 286 | // File 287 | if err != nil { 288 | return RestoreAsset(dir, name) 289 | } 290 | // Dir 291 | for _, child := range children { 292 | err = RestoreAssets(dir, filepath.Join(name, child)) 293 | if err != nil { 294 | return err 295 | } 296 | } 297 | return nil 298 | } 299 | 300 | func _filePath(dir, name string) string { 301 | canonicalName := strings.Replace(name, "\\", "/", -1) 302 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 303 | } 304 | -------------------------------------------------------------------------------- /testdata/out/nocompress-memcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. DO NOT EDIT. 2 | // sources: 3 | // in/a/test.asset (15B) 4 | // in/b/test.asset (15B) 5 | // in/c/test.asset (15B) 6 | // in/test.asset (15B) 7 | 8 | package main 9 | 10 | import ( 11 | "crypto/sha256" 12 | "fmt" 13 | "os" 14 | "path/filepath" 15 | "strings" 16 | "time" 17 | ) 18 | 19 | type asset struct { 20 | bytes []byte 21 | info os.FileInfo 22 | digest [sha256.Size]byte 23 | } 24 | 25 | type bindataFileInfo struct { 26 | name string 27 | size int64 28 | mode os.FileMode 29 | modTime time.Time 30 | } 31 | 32 | func (fi bindataFileInfo) Name() string { 33 | return fi.name 34 | } 35 | func (fi bindataFileInfo) Size() int64 { 36 | return fi.size 37 | } 38 | func (fi bindataFileInfo) Mode() os.FileMode { 39 | return fi.mode 40 | } 41 | func (fi bindataFileInfo) ModTime() time.Time { 42 | return fi.modTime 43 | } 44 | func (fi bindataFileInfo) IsDir() bool { 45 | return false 46 | } 47 | func (fi bindataFileInfo) Sys() interface{} { 48 | return nil 49 | } 50 | 51 | var _inATestAsset = []byte(`// sample file 52 | `) 53 | 54 | func inATestAssetBytes() ([]byte, error) { 55 | return _inATestAsset, nil 56 | } 57 | 58 | func inATestAsset() (*asset, error) { 59 | bytes, err := inATestAssetBytes() 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | info := bindataFileInfo{name: "in/a/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 65 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 66 | return a, nil 67 | } 68 | 69 | var _inBTestAsset = []byte(`// sample file 70 | `) 71 | 72 | func inBTestAssetBytes() ([]byte, error) { 73 | return _inBTestAsset, nil 74 | } 75 | 76 | func inBTestAsset() (*asset, error) { 77 | bytes, err := inBTestAssetBytes() 78 | if err != nil { 79 | return nil, err 80 | } 81 | 82 | info := bindataFileInfo{name: "in/b/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 83 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 84 | return a, nil 85 | } 86 | 87 | var _inCTestAsset = []byte(`// sample file 88 | `) 89 | 90 | func inCTestAssetBytes() ([]byte, error) { 91 | return _inCTestAsset, nil 92 | } 93 | 94 | func inCTestAsset() (*asset, error) { 95 | bytes, err := inCTestAssetBytes() 96 | if err != nil { 97 | return nil, err 98 | } 99 | 100 | info := bindataFileInfo{name: "in/c/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 101 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 102 | return a, nil 103 | } 104 | 105 | var _inTestAsset = []byte(`// sample file 106 | `) 107 | 108 | func inTestAssetBytes() ([]byte, error) { 109 | return _inTestAsset, nil 110 | } 111 | 112 | func inTestAsset() (*asset, error) { 113 | bytes, err := inTestAssetBytes() 114 | if err != nil { 115 | return nil, err 116 | } 117 | 118 | info := bindataFileInfo{name: "in/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 119 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 120 | return a, nil 121 | } 122 | 123 | // Asset loads and returns the asset for the given name. 124 | // It returns an error if the asset could not be found or 125 | // could not be loaded. 126 | func Asset(name string) ([]byte, error) { 127 | canonicalName := strings.Replace(name, "\\", "/", -1) 128 | if f, ok := _bindata[canonicalName]; ok { 129 | a, err := f() 130 | if err != nil { 131 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 132 | } 133 | return a.bytes, nil 134 | } 135 | return nil, fmt.Errorf("Asset %s not found", name) 136 | } 137 | 138 | // AssetString returns the asset contents as a string (instead of a []byte). 139 | func AssetString(name string) (string, error) { 140 | data, err := Asset(name) 141 | return string(data), err 142 | } 143 | 144 | // MustAsset is like Asset but panics when Asset would return an error. 145 | // It simplifies safe initialization of global variables. 146 | func MustAsset(name string) []byte { 147 | a, err := Asset(name) 148 | if err != nil { 149 | panic("asset: Asset(" + name + "): " + err.Error()) 150 | } 151 | 152 | return a 153 | } 154 | 155 | // MustAssetString is like AssetString but panics when Asset would return an 156 | // error. It simplifies safe initialization of global variables. 157 | func MustAssetString(name string) string { 158 | return string(MustAsset(name)) 159 | } 160 | 161 | // AssetInfo loads and returns the asset info for the given name. 162 | // It returns an error if the asset could not be found or 163 | // could not be loaded. 164 | func AssetInfo(name string) (os.FileInfo, error) { 165 | canonicalName := strings.Replace(name, "\\", "/", -1) 166 | if f, ok := _bindata[canonicalName]; ok { 167 | a, err := f() 168 | if err != nil { 169 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 170 | } 171 | return a.info, nil 172 | } 173 | return nil, fmt.Errorf("AssetInfo %s not found", name) 174 | } 175 | 176 | // AssetDigest returns the digest of the file with the given name. It returns an 177 | // error if the asset could not be found or the digest could not be loaded. 178 | func AssetDigest(name string) ([sha256.Size]byte, error) { 179 | canonicalName := strings.Replace(name, "\\", "/", -1) 180 | if f, ok := _bindata[canonicalName]; ok { 181 | a, err := f() 182 | if err != nil { 183 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 184 | } 185 | return a.digest, nil 186 | } 187 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 188 | } 189 | 190 | // Digests returns a map of all known files and their checksums. 191 | func Digests() (map[string][sha256.Size]byte, error) { 192 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 193 | for name := range _bindata { 194 | a, err := _bindata[name]() 195 | if err != nil { 196 | return nil, err 197 | } 198 | mp[name] = a.digest 199 | } 200 | return mp, nil 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 | "in/a/test.asset": inATestAsset, 215 | "in/b/test.asset": inBTestAsset, 216 | "in/c/test.asset": inCTestAsset, 217 | "in/test.asset": inTestAsset, 218 | } 219 | 220 | // AssetDebug is true if the assets were built with the debug flag enabled. 221 | const AssetDebug = false 222 | 223 | // AssetDir returns the file names below a certain 224 | // directory embedded in the file by go-bindata. 225 | // For example if you run go-bindata on data/... and data contains the 226 | // following hierarchy: 227 | // 228 | // data/ 229 | // foo.txt 230 | // img/ 231 | // a.png 232 | // b.png 233 | // 234 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 235 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 236 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 237 | // AssetDir("") will return []string{"data"}. 238 | func AssetDir(name string) ([]string, error) { 239 | node := _bintree 240 | if len(name) != 0 { 241 | canonicalName := strings.Replace(name, "\\", "/", -1) 242 | pathList := strings.Split(canonicalName, "/") 243 | for _, p := range pathList { 244 | node = node.Children[p] 245 | if node == nil { 246 | return nil, fmt.Errorf("Asset %s not found", name) 247 | } 248 | } 249 | } 250 | if node.Func != nil { 251 | return nil, fmt.Errorf("Asset %s not found", name) 252 | } 253 | rv := make([]string, 0, len(node.Children)) 254 | for childName := range node.Children { 255 | rv = append(rv, childName) 256 | } 257 | return rv, nil 258 | } 259 | 260 | type bintree struct { 261 | Func func() (*asset, error) 262 | Children map[string]*bintree 263 | } 264 | 265 | var _bintree = &bintree{nil, map[string]*bintree{ 266 | "in": {nil, map[string]*bintree{ 267 | "a": {nil, map[string]*bintree{ 268 | "test.asset": {inATestAsset, map[string]*bintree{}}, 269 | }}, 270 | "b": {nil, map[string]*bintree{ 271 | "test.asset": {inBTestAsset, map[string]*bintree{}}, 272 | }}, 273 | "c": {nil, map[string]*bintree{ 274 | "test.asset": {inCTestAsset, map[string]*bintree{}}, 275 | }}, 276 | "test.asset": {inTestAsset, map[string]*bintree{}}, 277 | }}, 278 | }} 279 | 280 | // RestoreAsset restores an asset under the given directory. 281 | func RestoreAsset(dir, name string) error { 282 | data, err := Asset(name) 283 | if err != nil { 284 | return err 285 | } 286 | info, err := AssetInfo(name) 287 | if err != nil { 288 | return err 289 | } 290 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 291 | if err != nil { 292 | return err 293 | } 294 | err = os.WriteFile(_filePath(dir, name), data, info.Mode()) 295 | if err != nil { 296 | return err 297 | } 298 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 299 | } 300 | 301 | // RestoreAssets restores an asset under the given directory recursively. 302 | func RestoreAssets(dir, name string) error { 303 | children, err := AssetDir(name) 304 | // File 305 | if err != nil { 306 | return RestoreAsset(dir, name) 307 | } 308 | // Dir 309 | for _, child := range children { 310 | err = RestoreAssets(dir, filepath.Join(name, child)) 311 | if err != nil { 312 | return err 313 | } 314 | } 315 | return nil 316 | } 317 | 318 | func _filePath(dir, name string) string { 319 | canonicalName := strings.Replace(name, "\\", "/", -1) 320 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 321 | } 322 | -------------------------------------------------------------------------------- /testdata/out/nocompress-nomemcopy.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. DO NOT EDIT. 2 | // sources: 3 | // in/a/test.asset (15B) 4 | // in/b/test.asset (15B) 5 | // in/c/test.asset (15B) 6 | // in/test.asset (15B) 7 | 8 | package main 9 | 10 | import ( 11 | "crypto/sha256" 12 | "fmt" 13 | "os" 14 | "path/filepath" 15 | "reflect" 16 | "strings" 17 | "time" 18 | "unsafe" 19 | ) 20 | 21 | func bindataRead(data, name string) ([]byte, error) { 22 | var empty [0]byte 23 | sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) 24 | b := empty[:] 25 | bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 26 | bx.Data = sx.Data 27 | bx.Len = len(data) 28 | bx.Cap = bx.Len 29 | return b, nil 30 | } 31 | 32 | type asset struct { 33 | bytes []byte 34 | info os.FileInfo 35 | digest [sha256.Size]byte 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(0644), modTime: time.Unix(1136214245, 0)} 80 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 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(0644), modTime: time.Unix(1136214245, 0)} 100 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 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(0644), modTime: time.Unix(1136214245, 0)} 120 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 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(0644), modTime: time.Unix(1136214245, 0)} 140 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 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 | canonicalName := strings.Replace(name, "\\", "/", -1) 149 | if f, ok := _bindata[canonicalName]; 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 | // AssetString returns the asset contents as a string (instead of a []byte). 160 | func AssetString(name string) (string, error) { 161 | data, err := Asset(name) 162 | return string(data), err 163 | } 164 | 165 | // MustAsset is like Asset but panics when Asset would return an error. 166 | // It simplifies safe initialization of global variables. 167 | func MustAsset(name string) []byte { 168 | a, err := Asset(name) 169 | if err != nil { 170 | panic("asset: Asset(" + name + "): " + err.Error()) 171 | } 172 | 173 | return a 174 | } 175 | 176 | // MustAssetString is like AssetString but panics when Asset would return an 177 | // error. It simplifies safe initialization of global variables. 178 | func MustAssetString(name string) string { 179 | return string(MustAsset(name)) 180 | } 181 | 182 | // AssetInfo loads and returns the asset info for the given name. 183 | // It returns an error if the asset could not be found or 184 | // could not be loaded. 185 | func AssetInfo(name string) (os.FileInfo, error) { 186 | canonicalName := strings.Replace(name, "\\", "/", -1) 187 | if f, ok := _bindata[canonicalName]; ok { 188 | a, err := f() 189 | if err != nil { 190 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 191 | } 192 | return a.info, nil 193 | } 194 | return nil, fmt.Errorf("AssetInfo %s not found", name) 195 | } 196 | 197 | // AssetDigest returns the digest of the file with the given name. It returns an 198 | // error if the asset could not be found or the digest could not be loaded. 199 | func AssetDigest(name string) ([sha256.Size]byte, error) { 200 | canonicalName := strings.Replace(name, "\\", "/", -1) 201 | if f, ok := _bindata[canonicalName]; ok { 202 | a, err := f() 203 | if err != nil { 204 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 205 | } 206 | return a.digest, nil 207 | } 208 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 209 | } 210 | 211 | // Digests returns a map of all known files and their checksums. 212 | func Digests() (map[string][sha256.Size]byte, error) { 213 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 214 | for name := range _bindata { 215 | a, err := _bindata[name]() 216 | if err != nil { 217 | return nil, err 218 | } 219 | mp[name] = a.digest 220 | } 221 | return mp, nil 222 | } 223 | 224 | // AssetNames returns the names of the assets. 225 | func AssetNames() []string { 226 | names := make([]string, 0, len(_bindata)) 227 | for name := range _bindata { 228 | names = append(names, name) 229 | } 230 | return names 231 | } 232 | 233 | // _bindata is a table, holding each asset generator, mapped to its name. 234 | var _bindata = map[string]func() (*asset, error){ 235 | "in/a/test.asset": inATestAsset, 236 | "in/b/test.asset": inBTestAsset, 237 | "in/c/test.asset": inCTestAsset, 238 | "in/test.asset": inTestAsset, 239 | } 240 | 241 | // AssetDebug is true if the assets were built with the debug flag enabled. 242 | const AssetDebug = false 243 | 244 | // AssetDir returns the file names below a certain 245 | // directory embedded in the file by go-bindata. 246 | // For example if you run go-bindata on data/... and data contains the 247 | // following hierarchy: 248 | // 249 | // data/ 250 | // foo.txt 251 | // img/ 252 | // a.png 253 | // b.png 254 | // 255 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 256 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 257 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 258 | // AssetDir("") will return []string{"data"}. 259 | func AssetDir(name string) ([]string, error) { 260 | node := _bintree 261 | if len(name) != 0 { 262 | canonicalName := strings.Replace(name, "\\", "/", -1) 263 | pathList := strings.Split(canonicalName, "/") 264 | for _, p := range pathList { 265 | node = node.Children[p] 266 | if node == nil { 267 | return nil, fmt.Errorf("Asset %s not found", name) 268 | } 269 | } 270 | } 271 | if node.Func != nil { 272 | return nil, fmt.Errorf("Asset %s not found", name) 273 | } 274 | rv := make([]string, 0, len(node.Children)) 275 | for childName := range node.Children { 276 | rv = append(rv, childName) 277 | } 278 | return rv, nil 279 | } 280 | 281 | type bintree struct { 282 | Func func() (*asset, error) 283 | Children map[string]*bintree 284 | } 285 | 286 | var _bintree = &bintree{nil, map[string]*bintree{ 287 | "in": {nil, map[string]*bintree{ 288 | "a": {nil, map[string]*bintree{ 289 | "test.asset": {inATestAsset, map[string]*bintree{}}, 290 | }}, 291 | "b": {nil, map[string]*bintree{ 292 | "test.asset": {inBTestAsset, map[string]*bintree{}}, 293 | }}, 294 | "c": {nil, map[string]*bintree{ 295 | "test.asset": {inCTestAsset, map[string]*bintree{}}, 296 | }}, 297 | "test.asset": {inTestAsset, map[string]*bintree{}}, 298 | }}, 299 | }} 300 | 301 | // RestoreAsset restores an asset under the given directory. 302 | func RestoreAsset(dir, name string) error { 303 | data, err := Asset(name) 304 | if err != nil { 305 | return err 306 | } 307 | info, err := AssetInfo(name) 308 | if err != nil { 309 | return err 310 | } 311 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 312 | if err != nil { 313 | return err 314 | } 315 | err = os.WriteFile(_filePath(dir, name), data, info.Mode()) 316 | if err != nil { 317 | return err 318 | } 319 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 320 | } 321 | 322 | // RestoreAssets restores an asset under the given directory recursively. 323 | func RestoreAssets(dir, name string) error { 324 | children, err := AssetDir(name) 325 | // File 326 | if err != nil { 327 | return RestoreAsset(dir, name) 328 | } 329 | // Dir 330 | for _, child := range children { 331 | err = RestoreAssets(dir, filepath.Join(name, child)) 332 | if err != nil { 333 | return err 334 | } 335 | } 336 | return nil 337 | } 338 | 339 | func _filePath(dir, name string) string { 340 | canonicalName := strings.Replace(name, "\\", "/", -1) 341 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 342 | } 343 | -------------------------------------------------------------------------------- /testdata/out/prefix.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. DO NOT EDIT. 2 | // sources: 3 | // a/test.asset (15B) 4 | // b/test.asset (15B) 5 | // c/test.asset (15B) 6 | // test.asset (15B) 7 | 8 | package main 9 | 10 | import ( 11 | "bytes" 12 | "compress/gzip" 13 | "crypto/sha256" 14 | "fmt" 15 | "io" 16 | "os" 17 | "path/filepath" 18 | "strings" 19 | "time" 20 | ) 21 | 22 | func bindataRead(data []byte, name string) ([]byte, error) { 23 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 24 | if err != nil { 25 | return nil, fmt.Errorf("read %q: %w", name, err) 26 | } 27 | 28 | var buf bytes.Buffer 29 | _, err = io.Copy(&buf, gz) 30 | clErr := gz.Close() 31 | 32 | if err != nil { 33 | return nil, fmt.Errorf("read %q: %w", name, err) 34 | } 35 | if clErr != nil { 36 | return nil, err 37 | } 38 | 39 | return buf.Bytes(), nil 40 | } 41 | 42 | type asset struct { 43 | bytes []byte 44 | info os.FileInfo 45 | digest [sha256.Size]byte 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 _aTestAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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 aTestAssetBytes() ([]byte, error) { 77 | return bindataRead( 78 | _aTestAsset, 79 | "a/test.asset", 80 | ) 81 | } 82 | 83 | func aTestAsset() (*asset, error) { 84 | bytes, err := aTestAssetBytes() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | info := bindataFileInfo{name: "a/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 90 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 91 | return a, nil 92 | } 93 | 94 | var _bTestAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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 bTestAssetBytes() ([]byte, error) { 97 | return bindataRead( 98 | _bTestAsset, 99 | "b/test.asset", 100 | ) 101 | } 102 | 103 | func bTestAsset() (*asset, error) { 104 | bytes, err := bTestAssetBytes() 105 | if err != nil { 106 | return nil, err 107 | } 108 | 109 | info := bindataFileInfo{name: "b/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 110 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 111 | return a, nil 112 | } 113 | 114 | var _cTestAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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 cTestAssetBytes() ([]byte, error) { 117 | return bindataRead( 118 | _cTestAsset, 119 | "c/test.asset", 120 | ) 121 | } 122 | 123 | func cTestAsset() (*asset, error) { 124 | bytes, err := cTestAssetBytes() 125 | if err != nil { 126 | return nil, err 127 | } 128 | 129 | info := bindataFileInfo{name: "c/test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 130 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 131 | return a, nil 132 | } 133 | 134 | var _testAsset = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\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 testAssetBytes() ([]byte, error) { 137 | return bindataRead( 138 | _testAsset, 139 | "test.asset", 140 | ) 141 | } 142 | 143 | func testAsset() (*asset, error) { 144 | bytes, err := testAssetBytes() 145 | if err != nil { 146 | return nil, err 147 | } 148 | 149 | info := bindataFileInfo{name: "test.asset", size: 15, mode: os.FileMode(0644), modTime: time.Unix(1136214245, 0)} 150 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x67, 0xe5, 0x1a, 0x66, 0xe5, 0x1, 0x4e, 0x8, 0x46, 0xd8, 0xa6, 0x67, 0x32, 0xa8, 0xa4, 0xf2, 0x95, 0x5a, 0x81, 0xd4, 0xe7, 0x1d, 0x90, 0xfa, 0x78, 0x26, 0x53, 0x53, 0x62, 0xd0, 0x86, 0xd2}} 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 | canonicalName := strings.Replace(name, "\\", "/", -1) 159 | if f, ok := _bindata[canonicalName]; 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 | // AssetString returns the asset contents as a string (instead of a []byte). 170 | func AssetString(name string) (string, error) { 171 | data, err := Asset(name) 172 | return string(data), err 173 | } 174 | 175 | // MustAsset is like Asset but panics when Asset would return an error. 176 | // It simplifies safe initialization of global variables. 177 | func MustAsset(name string) []byte { 178 | a, err := Asset(name) 179 | if err != nil { 180 | panic("asset: Asset(" + name + "): " + err.Error()) 181 | } 182 | 183 | return a 184 | } 185 | 186 | // MustAssetString is like AssetString but panics when Asset would return an 187 | // error. It simplifies safe initialization of global variables. 188 | func MustAssetString(name string) string { 189 | return string(MustAsset(name)) 190 | } 191 | 192 | // AssetInfo loads and returns the asset info for the given name. 193 | // It returns an error if the asset could not be found or 194 | // could not be loaded. 195 | func AssetInfo(name string) (os.FileInfo, error) { 196 | canonicalName := strings.Replace(name, "\\", "/", -1) 197 | if f, ok := _bindata[canonicalName]; ok { 198 | a, err := f() 199 | if err != nil { 200 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 201 | } 202 | return a.info, nil 203 | } 204 | return nil, fmt.Errorf("AssetInfo %s not found", name) 205 | } 206 | 207 | // AssetDigest returns the digest of the file with the given name. It returns an 208 | // error if the asset could not be found or the digest could not be loaded. 209 | func AssetDigest(name string) ([sha256.Size]byte, error) { 210 | canonicalName := strings.Replace(name, "\\", "/", -1) 211 | if f, ok := _bindata[canonicalName]; ok { 212 | a, err := f() 213 | if err != nil { 214 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 215 | } 216 | return a.digest, nil 217 | } 218 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 219 | } 220 | 221 | // Digests returns a map of all known files and their checksums. 222 | func Digests() (map[string][sha256.Size]byte, error) { 223 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 224 | for name := range _bindata { 225 | a, err := _bindata[name]() 226 | if err != nil { 227 | return nil, err 228 | } 229 | mp[name] = a.digest 230 | } 231 | return mp, nil 232 | } 233 | 234 | // AssetNames returns the names of the assets. 235 | func AssetNames() []string { 236 | names := make([]string, 0, len(_bindata)) 237 | for name := range _bindata { 238 | names = append(names, name) 239 | } 240 | return names 241 | } 242 | 243 | // _bindata is a table, holding each asset generator, mapped to its name. 244 | var _bindata = map[string]func() (*asset, error){ 245 | "a/test.asset": aTestAsset, 246 | "b/test.asset": bTestAsset, 247 | "c/test.asset": cTestAsset, 248 | "test.asset": testAsset, 249 | } 250 | 251 | // AssetDebug is true if the assets were built with the debug flag enabled. 252 | const AssetDebug = false 253 | 254 | // AssetDir returns the file names below a certain 255 | // directory embedded in the file by go-bindata. 256 | // For example if you run go-bindata on data/... and data contains the 257 | // following hierarchy: 258 | // 259 | // data/ 260 | // foo.txt 261 | // img/ 262 | // a.png 263 | // b.png 264 | // 265 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 266 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 267 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 268 | // AssetDir("") will return []string{"data"}. 269 | func AssetDir(name string) ([]string, error) { 270 | node := _bintree 271 | if len(name) != 0 { 272 | canonicalName := strings.Replace(name, "\\", "/", -1) 273 | pathList := strings.Split(canonicalName, "/") 274 | for _, p := range pathList { 275 | node = node.Children[p] 276 | if node == nil { 277 | return nil, fmt.Errorf("Asset %s not found", name) 278 | } 279 | } 280 | } 281 | if node.Func != nil { 282 | return nil, fmt.Errorf("Asset %s not found", name) 283 | } 284 | rv := make([]string, 0, len(node.Children)) 285 | for childName := range node.Children { 286 | rv = append(rv, childName) 287 | } 288 | return rv, nil 289 | } 290 | 291 | type bintree struct { 292 | Func func() (*asset, error) 293 | Children map[string]*bintree 294 | } 295 | 296 | var _bintree = &bintree{nil, map[string]*bintree{ 297 | "a": {nil, map[string]*bintree{ 298 | "test.asset": {aTestAsset, map[string]*bintree{}}, 299 | }}, 300 | "b": {nil, map[string]*bintree{ 301 | "test.asset": {bTestAsset, map[string]*bintree{}}, 302 | }}, 303 | "c": {nil, map[string]*bintree{ 304 | "test.asset": {cTestAsset, map[string]*bintree{}}, 305 | }}, 306 | "test.asset": {testAsset, map[string]*bintree{}}, 307 | }} 308 | 309 | // RestoreAsset restores an asset under the given directory. 310 | func RestoreAsset(dir, name string) error { 311 | data, err := Asset(name) 312 | if err != nil { 313 | return err 314 | } 315 | info, err := AssetInfo(name) 316 | if err != nil { 317 | return err 318 | } 319 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 320 | if err != nil { 321 | return err 322 | } 323 | err = os.WriteFile(_filePath(dir, name), data, info.Mode()) 324 | if err != nil { 325 | return err 326 | } 327 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 328 | } 329 | 330 | // RestoreAssets restores an asset under the given directory recursively. 331 | func RestoreAssets(dir, name string) error { 332 | children, err := AssetDir(name) 333 | // File 334 | if err != nil { 335 | return RestoreAsset(dir, name) 336 | } 337 | // Dir 338 | for _, child := range children { 339 | err = RestoreAssets(dir, filepath.Join(name, child)) 340 | if err != nil { 341 | return err 342 | } 343 | } 344 | return nil 345 | } 346 | 347 | func _filePath(dir, name string) string { 348 | canonicalName := strings.Replace(name, "\\", "/", -1) 349 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) 350 | } 351 | -------------------------------------------------------------------------------- /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 | "bytes" 9 | "fmt" 10 | "go/format" 11 | "io" 12 | "sort" 13 | "strings" 14 | ) 15 | 16 | type assetTree struct { 17 | Asset Asset 18 | Children map[string]*assetTree 19 | } 20 | 21 | func newAssetTree() *assetTree { 22 | tree := &assetTree{} 23 | tree.Children = make(map[string]*assetTree) 24 | return tree 25 | } 26 | 27 | func (node *assetTree) child(name string) *assetTree { 28 | rv, ok := node.Children[name] 29 | if !ok { 30 | rv = newAssetTree() 31 | // TODO: maintain this in sorted order 32 | node.Children[name] = rv 33 | } 34 | return rv 35 | } 36 | 37 | func (root *assetTree) Add(route []string, asset Asset) { 38 | for _, name := range route { 39 | root = root.child(name) 40 | } 41 | root.Asset = asset 42 | } 43 | 44 | func ident(buf *bytes.Buffer, n int) { 45 | for i := 0; i < n; i++ { 46 | buf.WriteByte('\t') 47 | } 48 | } 49 | 50 | func (root *assetTree) funcOrNil() string { 51 | if root.Asset.Func == "" { 52 | return "nil" 53 | } else { 54 | return root.Asset.Func 55 | } 56 | } 57 | 58 | func (root *assetTree) writeGoMap(buf *bytes.Buffer, nident int) { 59 | buf.Grow(35) // at least this size 60 | if nident == 0 { 61 | // at the top level we need to declare the map type 62 | buf.WriteString("&bintree") 63 | } 64 | fmt.Fprintf(buf, "{%s, map[string]*bintree{", root.funcOrNil()) 65 | 66 | if len(root.Children) > 0 { 67 | buf.WriteByte('\n') 68 | 69 | // Sort to make output stable between invocations 70 | filenames := make([]string, len(root.Children)) 71 | i := 0 72 | for filename := range root.Children { 73 | filenames[i] = filename 74 | i++ 75 | } 76 | sort.Strings(filenames) 77 | 78 | for _, p := range filenames { 79 | ident(buf, nident+1) 80 | buf.WriteByte('"') 81 | buf.WriteString(p) 82 | buf.WriteString(`": `) 83 | root.Children[p].writeGoMap(buf, nident+1) 84 | } 85 | ident(buf, nident) 86 | } 87 | 88 | buf.WriteString("}}") 89 | if nident > 0 { 90 | buf.WriteByte(',') 91 | } 92 | buf.WriteByte('\n') 93 | } 94 | 95 | func (root *assetTree) WriteAsGoMap(w io.Writer) error { 96 | _, err := w.Write([]byte(`type bintree struct { 97 | Func func() (*asset, error) 98 | Children map[string]*bintree 99 | } 100 | 101 | var _bintree = `)) 102 | if err != nil { 103 | return err 104 | } 105 | buf := new(bytes.Buffer) 106 | root.writeGoMap(buf, 0) 107 | _, writeErr := w.Write(buf.Bytes()) 108 | return writeErr 109 | } 110 | 111 | func writeTOCTree(w io.Writer, toc []Asset) error { 112 | innerBuf := new(strings.Builder) 113 | _, err := innerBuf.Write([]byte(`// AssetDir returns the file names below a certain 114 | // directory embedded in the file by go-bindata. 115 | // For example if you run go-bindata on data/... and data contains the 116 | // following hierarchy: 117 | // 118 | // data/ 119 | // foo.txt 120 | // img/ 121 | // a.png 122 | // b.png 123 | // 124 | // then AssetDir("data") would return []string{"foo.txt", "img"}, 125 | // AssetDir("data/img") would return []string{"a.png", "b.png"}, 126 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and 127 | // AssetDir("") will return []string{"data"}. 128 | func AssetDir(name string) ([]string, error) { 129 | node := _bintree 130 | if len(name) != 0 { 131 | canonicalName := strings.Replace(name, "\\", "/", -1) 132 | pathList := strings.Split(canonicalName, "/") 133 | for _, p := range pathList { 134 | node = node.Children[p] 135 | if node == nil { 136 | return nil, fmt.Errorf("Asset %s not found", name) 137 | } 138 | } 139 | } 140 | if node.Func != nil { 141 | return nil, fmt.Errorf("Asset %s not found", name) 142 | } 143 | rv := make([]string, 0, len(node.Children)) 144 | for childName := range node.Children { 145 | rv = append(rv, childName) 146 | } 147 | return rv, nil 148 | } 149 | 150 | `)) 151 | if err != nil { 152 | return err 153 | } 154 | tree := newAssetTree() 155 | for i := range toc { 156 | pathList := strings.Split(toc[i].Name, "/") 157 | tree.Add(pathList, toc[i]) 158 | } 159 | if err := tree.WriteAsGoMap(innerBuf); err != nil { 160 | return err 161 | } 162 | fmted, err := format.Source([]byte(innerBuf.String())) 163 | if err != nil { 164 | return err 165 | } 166 | _, err = w.Write(fmted) 167 | return err 168 | } 169 | 170 | // writeTOC writes the table of contents file. 171 | func writeTOC(buf *bytes.Buffer, toc []Asset) error { 172 | writeTOCHeader(buf) 173 | 174 | // Need an innerBuf so we can call gofmt and get map keys formatted at the 175 | // appropriate indentation. 176 | innerBuf := new(strings.Builder) 177 | if err := writeTOCMapHeader(innerBuf); err != nil { 178 | return err 179 | } 180 | 181 | for i := range toc { 182 | if err := writeTOCAsset(innerBuf, &toc[i]); err != nil { 183 | return err 184 | } 185 | } 186 | 187 | writeTOCFooter(innerBuf) 188 | fmted, err := format.Source([]byte(innerBuf.String())) 189 | if err != nil { 190 | return err 191 | } 192 | if _, err := buf.Write(fmted); err != nil { 193 | return err 194 | } 195 | return nil 196 | } 197 | 198 | // writeTOCHeader writes the table of contents file header. 199 | func writeTOCHeader(buf *bytes.Buffer) { 200 | buf.WriteString(`// Asset loads and returns the asset for the given name. 201 | // It returns an error if the asset could not be found or 202 | // could not be loaded. 203 | func Asset(name string) ([]byte, error) { 204 | canonicalName := strings.Replace(name, "\\", "/", -1) 205 | if f, ok := _bindata[canonicalName]; ok { 206 | a, err := f() 207 | if err != nil { 208 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 209 | } 210 | return a.bytes, nil 211 | } 212 | return nil, fmt.Errorf("Asset %s not found", name) 213 | } 214 | 215 | // AssetString returns the asset contents as a string (instead of a []byte). 216 | func AssetString(name string) (string, error) { 217 | data, err := Asset(name) 218 | return string(data), err 219 | } 220 | 221 | // MustAsset is like Asset but panics when Asset would return an error. 222 | // It simplifies safe initialization of global variables. 223 | func MustAsset(name string) []byte { 224 | a, err := Asset(name) 225 | if err != nil { 226 | panic("asset: Asset(" + name + "): " + err.Error()) 227 | } 228 | 229 | return a 230 | } 231 | 232 | // MustAssetString is like AssetString but panics when Asset would return an 233 | // error. It simplifies safe initialization of global variables. 234 | func MustAssetString(name string) string { 235 | return string(MustAsset(name)) 236 | } 237 | 238 | // AssetInfo loads and returns the asset info for the given name. 239 | // It returns an error if the asset could not be found or 240 | // could not be loaded. 241 | func AssetInfo(name string) (os.FileInfo, error) { 242 | canonicalName := strings.Replace(name, "\\", "/", -1) 243 | if f, ok := _bindata[canonicalName]; ok { 244 | a, err := f() 245 | if err != nil { 246 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 247 | } 248 | return a.info, nil 249 | } 250 | return nil, fmt.Errorf("AssetInfo %s not found", name) 251 | } 252 | 253 | // AssetDigest returns the digest of the file with the given name. It returns an 254 | // error if the asset could not be found or the digest could not be loaded. 255 | func AssetDigest(name string) ([sha256.Size]byte, error) { 256 | canonicalName := strings.Replace(name, "\\", "/", -1) 257 | if f, ok := _bindata[canonicalName]; ok { 258 | a, err := f() 259 | if err != nil { 260 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) 261 | } 262 | return a.digest, nil 263 | } 264 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) 265 | } 266 | 267 | // Digests returns a map of all known files and their checksums. 268 | func Digests() (map[string][sha256.Size]byte, error) { 269 | mp := make(map[string][sha256.Size]byte, len(_bindata)) 270 | for name := range _bindata { 271 | a, err := _bindata[name]() 272 | if err != nil { 273 | return nil, err 274 | } 275 | mp[name] = a.digest 276 | } 277 | return mp, nil 278 | } 279 | 280 | // AssetNames returns the names of the assets. 281 | func AssetNames() []string { 282 | names := make([]string, 0, len(_bindata)) 283 | for name := range _bindata { 284 | names = append(names, name) 285 | } 286 | return names 287 | } 288 | `) 289 | } 290 | 291 | func writeTOCMapHeader(w io.StringWriter) error { 292 | _, err := w.WriteString(` 293 | // _bindata is a table, holding each asset generator, mapped to its name. 294 | var _bindata = map[string]func() (*asset, error){ 295 | `) 296 | return err 297 | } 298 | 299 | // writeTOCAsset writes a TOC entry for the given asset. 300 | func writeTOCAsset(w io.Writer, asset *Asset) error { 301 | _, err := fmt.Fprintf(w, "\t%q: %s,\n", asset.Name, asset.Func) 302 | return err 303 | } 304 | 305 | // writeTOCFooter writes the table of contents file footer. 306 | func writeTOCFooter(w io.StringWriter) { 307 | w.WriteString(`} 308 | 309 | `) 310 | } 311 | --------------------------------------------------------------------------------