├── .gitignore ├── go.mod ├── doc.go ├── .github └── workflows │ └── release.yml ├── .goreleaser.yml ├── Makefile ├── LICENSE ├── README.md ├── assetfs.go └── go-bindata-assetfs ├── main.go └── main_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | tags 4 | builds 5 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/elazarl/go-bindata-assetfs 2 | 3 | go 1.15 4 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // assetfs allows packages to serve static content embedded 2 | // with the go-bindata tool with the standard net/http package. 3 | // 4 | // See https://github.com/go-bindata/go-bindata for more information 5 | // about embedding binary data with go-bindata. 6 | // 7 | // Usage example, after running 8 | // $ go-bindata data/... 9 | // use: 10 | // http.Handle("/", 11 | // http.FileServer( 12 | // &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "data"})) 13 | package assetfs 14 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | name: Build 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Set up Go 1.x 14 | uses: actions/setup-go@v2 15 | with: 16 | go-version: ^1.15 17 | - name: Check out code into the Go module directory 18 | uses: actions/checkout@v2 19 | - name: Run GoReleaser 20 | uses: goreleaser/goreleaser-action@v2 21 | with: 22 | version: latest 23 | args: release --rm-dist 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example goreleaser.yaml file with some sane defaults. 2 | # Make sure to check the documentation at http://goreleaser.com 3 | 4 | builds: 5 | - env: 6 | - CGO_ENABLED=0 7 | goos: 8 | - linux 9 | - darwin 10 | - windows 11 | goarch: 12 | - 386 13 | - amd64 14 | - arm64 15 | ignore: 16 | - goos: darwin 17 | goarch: 386 18 | - goos: windows 19 | goarch: arm64 20 | - goos: windows 21 | goarch: 386 22 | id: go-bindata-assetfs 23 | main: ./go-bindata-assetfs 24 | binary: go-bindata-assetfs 25 | 26 | archives: 27 | - replacements: 28 | darwin: Darwin 29 | linux: Linux 30 | windows: Windows 31 | 386: i386 32 | amd64: x86_64 33 | checksum: 34 | name_template: 'checksums.txt' 35 | 36 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Check for required command tools to build or stop immediately 2 | SHELL := bash 3 | EXECUTABLES = git go find pwd 4 | K := $(foreach exec,$(EXECUTABLES),\ 5 | $(if $(shell which $(exec)),some string,$(error "No ${exec} in PATH"))) 6 | 7 | ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 8 | 9 | OUT_DIR=builds 10 | BINARY=go-bindata-assetfs 11 | VERSION=1.0.1 12 | BUILD=`git rev-parse HEAD` 13 | PLATFORMS=darwin linux windows 14 | ARCHITECTURES=amd64 arm64 15 | 16 | # Setup linker flags option for build that interoperate with variable names in src code 17 | LDFLAGS=CGO_ENABLED=0 -ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD}" 18 | 19 | default: build 20 | 21 | all: clean build_all install 22 | 23 | build: 24 | go build ${LDFLAGS} -o ${BINARY} 25 | 26 | build_all: 27 | mkdir -p $(OUT_DIR) 28 | @go mod verify 29 | $(foreach GOOS, $(PLATFORMS),\ 30 | $(foreach GOARCH, $(ARCHITECTURES), $(shell export GOOS=$(GOOS); export GOARCH=$(GOARCH); go build -v -o $(OUT_DIR)/$(BINARY)-v$(VERSION)-$(GOOS)-$(GOARCH)))) 31 | 32 | install: 33 | go install ${LDFLAGS} 34 | 35 | # Remove only what we've created 36 | clean: 37 | find ${OUT_DIR} -name '${BINARY}[-?][a-zA-Z0-9]*[-?][a-zA-Z0-9]*' -delete 38 | 39 | .PHONY: check clean install build_all all -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Elazar Leibovich 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-bindata-assetfs 2 | 3 | Serve embedded files from [go-bindata](https://github.com/go-bindata/go-bindata) with `net/http`. 4 | 5 | [GoDoc](http://godoc.org/github.com/elazarl/go-bindata-assetfs) 6 | 7 | ### Installation 8 | 9 | Install with 10 | 11 | $ go get github.com/go-bindata/go-bindata/... 12 | $ go get github.com/elazarl/go-bindata-assetfs/... 13 | 14 | ### Creating embedded data 15 | 16 | Usage is identical to [go-bindata](https://github.com/go-bindata/go-bindata) usage, 17 | instead of running `go-bindata` run `go-bindata-assetfs`. 18 | 19 | The tool will create a `bindata_assetfs.go` file, which contains the embedded data. 20 | 21 | A typical use case is 22 | 23 | $ go-bindata-assetfs data/... 24 | 25 | ### Using assetFS in your code 26 | 27 | The generated file provides an `assetFS()` function that returns a `http.Filesystem` 28 | wrapping the embedded files. What you usually want to do is: 29 | 30 | http.Handle("/", http.FileServer(assetFS())) 31 | 32 | This would run an HTTP server serving the embedded files. 33 | 34 | ## Without running binary tool 35 | 36 | You can always just run the `go-bindata` tool, and then 37 | 38 | use 39 | 40 | ```go 41 | import "github.com/elazarl/go-bindata-assetfs" 42 | ... 43 | http.Handle("/", 44 | http.FileServer( 45 | &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: "data"})) 46 | ``` 47 | 48 | to serve files embedded from the `data` directory. 49 | 50 | ## SPA applications 51 | 52 | For single page applications you can use `Fallback: "index.html"` in AssetFS context, so if route doesn't match the pattern it will fallback to file specified. 53 | 54 | example 55 | 56 | ```go 57 | import "github.com/elazarl/go-bindata-assetfs" 58 | ... 59 | http.Handle("/", 60 | http.FileServer( 61 | &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: "data", Fallback: "index.html"})) 62 | ``` 63 | -------------------------------------------------------------------------------- /assetfs.go: -------------------------------------------------------------------------------- 1 | package assetfs 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io" 7 | "io/ioutil" 8 | "net/http" 9 | "os" 10 | "path" 11 | "path/filepath" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | var ( 17 | defaultFileTimestamp = time.Now() 18 | ) 19 | 20 | // FakeFile implements os.FileInfo interface for a given path and size 21 | type FakeFile struct { 22 | // Path is the path of this file 23 | Path string 24 | // Dir marks of the path is a directory 25 | Dir bool 26 | // Len is the length of the fake file, zero if it is a directory 27 | Len int64 28 | // Timestamp is the ModTime of this file 29 | Timestamp time.Time 30 | } 31 | 32 | func (f *FakeFile) Name() string { 33 | _, name := filepath.Split(f.Path) 34 | return name 35 | } 36 | 37 | func (f *FakeFile) Mode() os.FileMode { 38 | mode := os.FileMode(0644) 39 | if f.Dir { 40 | return mode | os.ModeDir 41 | } 42 | return mode 43 | } 44 | 45 | func (f *FakeFile) ModTime() time.Time { 46 | return f.Timestamp 47 | } 48 | 49 | func (f *FakeFile) Size() int64 { 50 | return f.Len 51 | } 52 | 53 | func (f *FakeFile) IsDir() bool { 54 | return f.Mode().IsDir() 55 | } 56 | 57 | func (f *FakeFile) Sys() interface{} { 58 | return nil 59 | } 60 | 61 | // AssetFile implements http.File interface for a no-directory file with content 62 | type AssetFile struct { 63 | *bytes.Reader 64 | io.Closer 65 | FakeFile 66 | } 67 | 68 | func NewAssetFile(name string, content []byte, timestamp time.Time) *AssetFile { 69 | if timestamp.IsZero() { 70 | timestamp = defaultFileTimestamp 71 | } 72 | return &AssetFile{ 73 | bytes.NewReader(content), 74 | ioutil.NopCloser(nil), 75 | FakeFile{name, false, int64(len(content)), timestamp}} 76 | } 77 | 78 | func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) { 79 | return nil, errors.New("not a directory") 80 | } 81 | 82 | func (f *AssetFile) Size() int64 { 83 | return f.FakeFile.Size() 84 | } 85 | 86 | func (f *AssetFile) Stat() (os.FileInfo, error) { 87 | return f, nil 88 | } 89 | 90 | // AssetDirectory implements http.File interface for a directory 91 | type AssetDirectory struct { 92 | AssetFile 93 | ChildrenRead int 94 | Children []os.FileInfo 95 | } 96 | 97 | func NewAssetDirectory(name string, children []string, fs *AssetFS) *AssetDirectory { 98 | fileinfos := make([]os.FileInfo, 0, len(children)) 99 | for _, child := range children { 100 | _, err := fs.AssetDir(filepath.Join(name, child)) 101 | fileinfos = append(fileinfos, &FakeFile{child, err == nil, 0, time.Time{}}) 102 | } 103 | return &AssetDirectory{ 104 | AssetFile{ 105 | bytes.NewReader(nil), 106 | ioutil.NopCloser(nil), 107 | FakeFile{name, true, 0, time.Time{}}, 108 | }, 109 | 0, 110 | fileinfos} 111 | } 112 | 113 | func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) { 114 | if count <= 0 { 115 | return f.Children, nil 116 | } 117 | if f.ChildrenRead+count > len(f.Children) { 118 | count = len(f.Children) - f.ChildrenRead 119 | } 120 | rv := f.Children[f.ChildrenRead : f.ChildrenRead+count] 121 | f.ChildrenRead += count 122 | return rv, nil 123 | } 124 | 125 | func (f *AssetDirectory) Stat() (os.FileInfo, error) { 126 | return f, nil 127 | } 128 | 129 | // AssetFS implements http.FileSystem, allowing 130 | // embedded files to be served from net/http package. 131 | type AssetFS struct { 132 | // Asset should return content of file in path if exists 133 | Asset func(path string) ([]byte, error) 134 | // AssetDir should return list of files in the path 135 | AssetDir func(path string) ([]string, error) 136 | // AssetInfo should return the info of file in path if exists 137 | AssetInfo func(path string) (os.FileInfo, error) 138 | // Prefix would be prepended to http requests 139 | Prefix string 140 | // Fallback file that is served if no other is found 141 | Fallback string 142 | } 143 | 144 | func (fs *AssetFS) Open(name string) (http.File, error) { 145 | name = path.Join(fs.Prefix, name) 146 | if len(name) > 0 && name[0] == '/' { 147 | name = name[1:] 148 | } 149 | if b, err := fs.Asset(name); err == nil { 150 | timestamp := defaultFileTimestamp 151 | if fs.AssetInfo != nil { 152 | if info, err := fs.AssetInfo(name); err == nil { 153 | timestamp = info.ModTime() 154 | } 155 | } 156 | return NewAssetFile(name, b, timestamp), nil 157 | } 158 | children, err := fs.AssetDir(name) 159 | 160 | if err != nil { 161 | if len(fs.Fallback) > 0 { 162 | return fs.Open(fs.Fallback) 163 | } 164 | 165 | // If the error is not found, return an error that will 166 | // result in a 404 error. Otherwise the server returns 167 | // a 500 error for files not found. 168 | if strings.Contains(err.Error(), "not found") { 169 | return nil, os.ErrNotExist 170 | } 171 | return nil, err 172 | } 173 | 174 | return NewAssetDirectory(name, children, fs), nil 175 | } 176 | -------------------------------------------------------------------------------- /go-bindata-assetfs/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "log" 8 | "os" 9 | "os/exec" 10 | ) 11 | 12 | type Config struct { 13 | // Do not embed assets, just structure 14 | Debug bool 15 | // Path to go-bindata executable 16 | ExecPath string 17 | // Path to temporary file produced by go-bindata (default: random file in OS tempdir) 18 | TempPath string 19 | // Final output path (default: bindata.go) 20 | OutPath string 21 | // Remaining misc args to pass through to go-bindata 22 | Args []string 23 | } 24 | 25 | // If this function succeeds, the caller is responsible for deleting the 26 | // temporary file at c.TempPath. This usually makes sense to do with a: 27 | // 28 | // defer os.Remove(c.TempPath) 29 | // 30 | // right after checking for errors. 31 | func parseConfig(args []string) (Config, error) { 32 | c := Config{ 33 | Debug: false, 34 | ExecPath: "", 35 | TempPath: "", 36 | OutPath: "bindata.go", 37 | Args: []string{}, 38 | } 39 | extra_args := []string{} 40 | 41 | path, err := exec.LookPath("go-bindata") 42 | if err != nil { 43 | fmt.Println("Cannot find go-bindata executable in path") 44 | fmt.Println("Maybe you need: go get github.com/elazarl/go-bindata-assetfs/...") 45 | return c, err 46 | } 47 | c.ExecPath = path 48 | 49 | // Do this dumb manually-tracked for loop so we can do skips. 50 | i := 0 51 | for { 52 | if i >= len(args) { 53 | break 54 | } 55 | arg := args[i] 56 | 57 | if arg == "-debug" { 58 | c.Debug = true 59 | } else if arg == "-t" && i+1 < len(args) { 60 | c.TempPath = args[i+1] 61 | i = i + 1 62 | } else if arg == "-o" && i+1 < len(args) { 63 | c.OutPath = args[i+1] 64 | i = i + 1 65 | } else { 66 | extra_args = append(extra_args, arg) 67 | } 68 | i = i + 1 69 | } 70 | 71 | // We don't hold onto the original file handle, as we can expect 72 | // go-bindata to replace it. We do establish the existence of the 73 | // file on-disk, though, to avoid collisions. 74 | if c.TempPath == "" { 75 | f, err := os.CreateTemp("", "go-bindata-assetfs") 76 | if err != nil { 77 | return c, err 78 | } 79 | c.TempPath = f.Name() 80 | f.Close() 81 | } 82 | 83 | // Polish up Args with stuff we pulled out/deduped earlier 84 | c.Args = []string{"-o", c.TempPath} 85 | if (c.Debug) { 86 | c.Args = append(c.Args, "-debug") 87 | } 88 | c.Args = append(c.Args, extra_args...) 89 | return c, nil 90 | } 91 | 92 | // Use go-bindata to output c.TempPath. 93 | func produceTempfile(c Config) error { 94 | cmd := exec.Command(c.ExecPath, c.Args...) 95 | cmd.Stdin = os.Stdin 96 | cmd.Stdout = os.Stdout 97 | cmd.Stderr = os.Stderr 98 | err := cmd.Run() 99 | if err != nil { 100 | return fmt.Errorf("go-bindata: %v", err) 101 | } 102 | return nil 103 | } 104 | 105 | 106 | // Read c.TempPath, and write modified version to c.OutPath. 107 | func produceOutfile(c Config) error { 108 | in, err := os.Open(c.TempPath) 109 | if err != nil { 110 | return fmt.Errorf("cannot read temporary file: %v", err) 111 | } 112 | defer in.Close() 113 | 114 | out, err := os.Create(c.OutPath) 115 | if err != nil { 116 | return fmt.Errorf("cannot create output file: %v", err) 117 | } 118 | defer out.Close() 119 | 120 | r := bufio.NewReader(in) 121 | done := false 122 | for line, isPrefix, err := r.ReadLine(); err == nil; line, isPrefix, err = r.ReadLine() { 123 | if !isPrefix { 124 | line = append(line, '\n') 125 | } 126 | if _, err := out.Write(line); err != nil { 127 | return fmt.Errorf("Cannot write to %s: %v", out.Name(), err) 128 | } 129 | if !done && !isPrefix && bytes.HasPrefix(line, []byte("import (")) { 130 | if c.Debug { 131 | fmt.Fprintln(out, "\t\"net/http\"") 132 | } else { 133 | fmt.Fprintln(out, "\t\"github.com/elazarl/go-bindata-assetfs\"") 134 | } 135 | done = true 136 | } 137 | } 138 | if c.Debug { 139 | fmt.Fprintln(out, ` 140 | func assetFS() http.FileSystem { 141 | for k := range _bintree.Children { 142 | return http.Dir(k) 143 | } 144 | panic("unreachable") 145 | } 146 | 147 | func AssetFS() http.FileSystem { 148 | return assetFS() 149 | }`) 150 | } else { 151 | fmt.Fprintln(out, ` 152 | func assetFS() *assetfs.AssetFS { 153 | for k := range _bintree.Children { 154 | return &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: k} 155 | } 156 | panic("unreachable") 157 | } 158 | 159 | func AssetFS() *assetfs.AssetFS { 160 | return assetFS() 161 | }`) 162 | } 163 | return nil 164 | } 165 | 166 | func generate(args []string) error { 167 | c, err := parseConfig(args) 168 | if err != nil { 169 | return err 170 | } 171 | defer os.Remove(c.TempPath) 172 | 173 | err = produceTempfile(c) 174 | if err != nil { 175 | return err 176 | } 177 | 178 | return produceOutfile(c) 179 | } 180 | 181 | func main() { 182 | err := generate(os.Args[1:]) 183 | if err != nil { 184 | log.Fatalf("Error: %v", err) 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /go-bindata-assetfs/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "os" 7 | "reflect" 8 | "strings" 9 | "testing" 10 | ) 11 | 12 | func helper(t *testing.T, tmp string, args []string) Config { 13 | c, err := parseConfig(args) 14 | if err != nil { 15 | t.Fatalf("parseConfig failed: %v", err) 16 | } 17 | 18 | if tmp != "" { 19 | if c.TempPath != tmp { 20 | t.Fatalf("Expected c.TempFile to be %s, got %s", tmp, c.TempPath) 21 | } 22 | } else if strings.HasPrefix(c.TempPath, os.TempDir()) { 23 | os.Remove(c.TempPath) 24 | } else { 25 | t.Fatalf("TempPath should live in system temp directory, got %s", c.TempPath) 26 | } 27 | 28 | if !strings.HasSuffix(c.ExecPath, "go-bindata") { 29 | t.Fatalf("ExecPath should point to go-bindata binary, got %s", c.ExecPath) 30 | } 31 | return c 32 | } 33 | 34 | func TestConfigParseEmpty(t *testing.T) { 35 | c := helper(t, "", []string{}) 36 | expected := Config{ 37 | Debug: false, 38 | ExecPath: c.ExecPath, 39 | TempPath: c.TempPath, 40 | OutPath: "bindata.go", 41 | Args: []string{"-o", c.TempPath}, 42 | } 43 | if !reflect.DeepEqual(c, expected) { 44 | t.Fatalf("Expected %v, got %v", expected, c) 45 | } 46 | } 47 | 48 | func TestConfigParseDebug(t *testing.T) { 49 | c := helper(t, "", []string{"-debug", "-debug", "-debug"}) 50 | expected := Config{ 51 | Debug: true, 52 | ExecPath: c.ExecPath, 53 | TempPath: c.TempPath, 54 | OutPath: "bindata.go", 55 | Args: []string{"-o", c.TempPath, "-debug"}, 56 | } 57 | if !reflect.DeepEqual(c, expected) { 58 | t.Fatalf("Expected %v, got %v", expected, c) 59 | } 60 | } 61 | 62 | func TestConfigParseArgs(t *testing.T) { 63 | c := helper(t, "", []string{"x", "y", "-debug", "z"}) 64 | expected := Config{ 65 | Debug: true, 66 | ExecPath: c.ExecPath, 67 | TempPath: c.TempPath, 68 | OutPath: "bindata.go", 69 | Args: []string{"-o", c.TempPath, "-debug", "x", "y", "z"}, 70 | } 71 | if !reflect.DeepEqual(c, expected) { 72 | t.Fatalf("Expected %v, got %v", expected, c) 73 | } 74 | } 75 | 76 | func TestConfigParsePaths(t *testing.T) { 77 | c := helper(t, "tempfile.go", []string{"-t", "tempfile.go", "-o", "outfile.go"}) 78 | expected := Config{ 79 | Debug: false, 80 | ExecPath: c.ExecPath, 81 | TempPath: "tempfile.go", 82 | OutPath: "outfile.go", 83 | Args: []string{"-o", "tempfile.go"}, 84 | } 85 | if !reflect.DeepEqual(c, expected) { 86 | t.Fatalf("Expected %v, got %v", expected, c) 87 | } 88 | } 89 | 90 | func TestProduceTempfile(t *testing.T) { 91 | c := helper(t, "", []string{"."}) 92 | err := produceTempfile(c) 93 | if err != nil { 94 | t.Fatalf("Couldn't produce %s: %v", c.TempPath, err) 95 | } 96 | defer os.Remove(c.TempPath) 97 | 98 | // Let's look at that tempfile and sanity check the contents! 99 | f, err := os.Open(c.TempPath) 100 | if err != nil { 101 | t.Fatalf("Couldn't open %s: %v", c.TempPath, err) 102 | } 103 | defer f.Close() 104 | 105 | sc := bufio.NewReader(f) 106 | line, err := sc.ReadString([]byte("\n")[0]) 107 | if err != nil { 108 | t.Fatalf("Couldn't read %s: %v", c.TempPath, err) 109 | } 110 | expected := "// Code generated by go-bindata. DO NOT EDIT.\n" 111 | if line != expected { 112 | t.Fatalf("Expected %v, got %v", expected, line) 113 | } 114 | } 115 | 116 | func TestProduceOutfile(t *testing.T) { 117 | c := helper(t, "", []string{".", "-o", "an-output.go"}) 118 | err := os.WriteFile(c.TempPath, []byte(` 119 | // Imagine, just imagine, that this file was produced by go-bindata. 120 | 121 | import ( 122 | "foo" 123 | "bar" 124 | ) 125 | 126 | func example() { 127 | } 128 | `), 0644) 129 | if err != nil { 130 | t.Fatalf("Could not write to %s, %v:", c.TempPath, err) 131 | } 132 | defer os.Remove(c.TempPath) 133 | 134 | err = produceOutfile(c) 135 | if err != nil { 136 | t.Fatalf("produceOutfile failed: %v", err) 137 | } 138 | defer os.Remove(c.OutPath) 139 | 140 | out, err := os.ReadFile(c.OutPath) 141 | if err != nil { 142 | t.Fatalf("Could not read from %s, %v:", c.OutPath, err) 143 | } 144 | expected := ` 145 | // Imagine, just imagine, that this file was produced by go-bindata. 146 | 147 | import ( 148 | "github.com/elazarl/go-bindata-assetfs" 149 | "foo" 150 | "bar" 151 | ) 152 | 153 | func example() { 154 | } 155 | 156 | func assetFS() *assetfs.AssetFS { 157 | for k := range _bintree.Children { 158 | return &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: k} 159 | } 160 | panic("unreachable") 161 | } 162 | 163 | func AssetFS() *assetfs.AssetFS { 164 | return assetFS() 165 | } 166 | ` 167 | if string(out) != expected { 168 | t.Fatalf("Expected: %v\n\nGot: %v", expected, string(out)) 169 | } 170 | } 171 | 172 | func TestProduceOutfileDebug(t *testing.T) { 173 | c := helper(t, "", []string{".", "-debug", "-o", "an-output.go"}) 174 | err := os.WriteFile(c.TempPath, []byte(` 175 | // Imagine, just imagine, that this file was produced by go-bindata. 176 | 177 | import ( 178 | "foo" 179 | "bar" 180 | ) 181 | 182 | func example() { 183 | } 184 | `), 0644) 185 | if err != nil { 186 | t.Fatalf("Could not write to %s, %v:", c.TempPath, err) 187 | } 188 | defer os.Remove(c.TempPath) 189 | 190 | err = produceOutfile(c) 191 | if err != nil { 192 | t.Fatalf("produceOutfile failed: %v", err) 193 | } 194 | defer os.Remove(c.OutPath) 195 | 196 | out, err := os.ReadFile(c.OutPath) 197 | if err != nil { 198 | t.Fatalf("Could not read from %s, %v:", c.OutPath, err) 199 | } 200 | expected := ` 201 | // Imagine, just imagine, that this file was produced by go-bindata. 202 | 203 | import ( 204 | "net/http" 205 | "foo" 206 | "bar" 207 | ) 208 | 209 | func example() { 210 | } 211 | 212 | func assetFS() http.FileSystem { 213 | for k := range _bintree.Children { 214 | return http.Dir(k) 215 | } 216 | panic("unreachable") 217 | } 218 | 219 | func AssetFS() http.FileSystem { 220 | return assetFS() 221 | } 222 | ` 223 | if string(out) != expected { 224 | t.Fatalf("Expected: %v\n\nGot: %v", expected, string(out)) 225 | } 226 | } 227 | 228 | func TestGenerate(t *testing.T) { 229 | err := generate([]string{".", "-o", "outfile.go"}) 230 | if err != nil { 231 | t.Fatalf("Generate failed: %v", err) 232 | } 233 | defer os.Remove("outfile.go") 234 | 235 | out, err := os.ReadFile("outfile.go") 236 | if !bytes.Contains(out, []byte(` "github.com/elazarl/go-bindata-assetfs"`)) { 237 | t.Fatalf("Outfile did not contain go-bindata-assetfs import") 238 | } 239 | } 240 | --------------------------------------------------------------------------------