Initial Commit
Mark Bates
7 years ago
0 | --- | |
1 | engines: | |
2 | golint: | |
3 | enabled: true | |
4 | checks: | |
5 | GoLint/Naming/MixedCaps: | |
6 | enabled: false | |
7 | govet: | |
8 | enabled: true | |
9 | gofmt: | |
10 | enabled: true | |
11 | fixme: | |
12 | enabled: true | |
13 | ratings: | |
14 | paths: | |
15 | - "**.go" | |
16 | exclude_paths: | |
17 | - "**/*_test.go" | |
18 | - "*_test.go" | |
19 | - "fixtures/" |
0 | *.log | |
1 | .DS_Store | |
2 | doc | |
3 | tmp | |
4 | pkg | |
5 | *.gem | |
6 | *.pid | |
7 | coverage | |
8 | coverage.data | |
9 | build/* | |
10 | *.pbxuser | |
11 | *.mode1v3 | |
12 | .svn | |
13 | profile | |
14 | .console_history | |
15 | .sass-cache/* | |
16 | .rake_tasks~ | |
17 | *.log.lck | |
18 | solr/ | |
19 | .jhw-cache/ | |
20 | jhw.* | |
21 | *.sublime* | |
22 | node_modules/ | |
23 | dist/ | |
24 | generated/ | |
25 | .vendor/ | |
26 | bin/* | |
27 | gin-bin |
0 | language: go | |
1 | ||
2 | sudo: false | |
3 | ||
4 | go: | |
5 | - 1.7 | |
6 | - 1.8 | |
7 | - tip | |
8 | ||
9 | matrix: | |
10 | allow_failures: | |
11 | - go: 'tip' |
0 | The MIT License (MIT) | |
1 | Copyright (c) 2016 Mark Bates | |
2 | ||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
4 | ||
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
6 | ||
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "io/ioutil" | |
4 | "path/filepath" | |
5 | "runtime" | |
6 | ) | |
7 | ||
8 | // NewBox returns a Box that can be used to | |
9 | // retrieve files from either disk or the embedded | |
10 | // binary. | |
11 | func NewBox(path string) Box { | |
12 | _, filename, _, _ := runtime.Caller(1) | |
13 | return Box{ | |
14 | Path: path, | |
15 | callingDir: filepath.Dir(filename), | |
16 | } | |
17 | } | |
18 | ||
19 | // Box represent a folder on a disk you want to | |
20 | // have access to in the built Go binary. | |
21 | type Box struct { | |
22 | Path string | |
23 | callingDir string | |
24 | data map[string][]byte | |
25 | } | |
26 | ||
27 | // String of the file asked for or an empty string. | |
28 | func (b Box) String(name string) string { | |
29 | return string(b.Bytes(name)) | |
30 | } | |
31 | ||
32 | // MustString returns either the string of the requested | |
33 | // file or an error if it can not be found. | |
34 | func (b Box) MustString(name string) (string, error) { | |
35 | bb, err := b.MustBytes(name) | |
36 | return string(bb), err | |
37 | } | |
38 | ||
39 | // Bytes of the file asked for or an empty byte slice. | |
40 | func (b Box) Bytes(name string) []byte { | |
41 | bb, _ := b.MustBytes(name) | |
42 | return bb | |
43 | } | |
44 | ||
45 | // MustBytes returns either the byte slice of the requested | |
46 | // file or an error if it can not be found. | |
47 | func (b Box) MustBytes(name string) ([]byte, error) { | |
48 | bb, err := find(b.Path, name) | |
49 | if err == nil { | |
50 | return bb, err | |
51 | } | |
52 | p := filepath.Join(b.callingDir, b.Path, name) | |
53 | return ioutil.ReadFile(p) | |
54 | } |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | ||
5 | "github.com/stretchr/testify/require" | |
6 | ) | |
7 | ||
8 | func Test_Box_String(t *testing.T) { | |
9 | r := require.New(t) | |
10 | s := testBox.String("hello.txt") | |
11 | r.Equal("hello world!\n", s) | |
12 | } | |
13 | ||
14 | func Test_Box_MustString(t *testing.T) { | |
15 | r := require.New(t) | |
16 | _, err := testBox.MustString("idontexist.txt") | |
17 | r.Error(err) | |
18 | } | |
19 | ||
20 | func Test_Box_Bytes(t *testing.T) { | |
21 | r := require.New(t) | |
22 | s := testBox.Bytes("hello.txt") | |
23 | r.Equal([]byte("hello world!\n"), s) | |
24 | } | |
25 | ||
26 | func Test_Box_MustBytes(t *testing.T) { | |
27 | r := require.New(t) | |
28 | _, err := testBox.MustBytes("idontexist.txt") | |
29 | r.Error(err) | |
30 | } |
0 | package builder | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "io/ioutil" | |
5 | "os" | |
6 | "path/filepath" | |
7 | "strings" | |
8 | ||
9 | "github.com/pkg/errors" | |
10 | ) | |
11 | ||
12 | type box struct { | |
13 | Name string | |
14 | Files []file | |
15 | } | |
16 | ||
17 | func (b *box) Walk(root string) error { | |
18 | return filepath.Walk(root, func(path string, info os.FileInfo, err error) error { | |
19 | if info == nil || info.IsDir() { | |
20 | return nil | |
21 | } | |
22 | f := file{ | |
23 | Name: strings.Replace(path, root, "", 1), | |
24 | } | |
25 | ||
26 | bb, err := ioutil.ReadFile(path) | |
27 | if err != nil { | |
28 | return errors.WithStack(err) | |
29 | } | |
30 | bb, err = json.Marshal(bb) | |
31 | if err != nil { | |
32 | return errors.WithStack(err) | |
33 | } | |
34 | f.Contents = strings.Replace(string(bb), "\"", "\\\"", -1) | |
35 | ||
36 | b.Files = append(b.Files, f) | |
37 | return nil | |
38 | }) | |
39 | } |
0 | package builder | |
1 | ||
2 | import ( | |
3 | "context" | |
4 | "fmt" | |
5 | "io/ioutil" | |
6 | "os" | |
7 | "path/filepath" | |
8 | "regexp" | |
9 | "text/template" | |
10 | ||
11 | "github.com/pkg/errors" | |
12 | ) | |
13 | ||
14 | var boxPattern = regexp.MustCompile(`packr.NewBox\(["` + "`" + `](.+)["` + "`" + `]\)`) | |
15 | var packagePattern = regexp.MustCompile(`package\s+(.+)`) | |
16 | var invalidFilePattern = regexp.MustCompile(`(_test|-packr).go$`) | |
17 | ||
18 | // Builder scans folders/files looking for `packr.NewBox` and then compiling | |
19 | // the required static files into `<package-name>-packr.go` files so they can | |
20 | // be built into Go binaries. | |
21 | type Builder struct { | |
22 | context.Context | |
23 | RootPath string | |
24 | pkgs map[string]pkg | |
25 | } | |
26 | ||
27 | // Run the builder. | |
28 | func (b *Builder) Run() error { | |
29 | err := filepath.Walk(b.RootPath, func(path string, info os.FileInfo, err error) error { | |
30 | base := filepath.Base(path) | |
31 | if base == ".git" || base == "vendor" || base == "node_modules" { | |
32 | return filepath.SkipDir | |
33 | } | |
34 | ||
35 | if !info.IsDir() { | |
36 | return b.process(path) | |
37 | } | |
38 | return nil | |
39 | }) | |
40 | if err != nil { | |
41 | return errors.WithStack(err) | |
42 | } | |
43 | return b.dump() | |
44 | } | |
45 | ||
46 | func (b *Builder) dump() error { | |
47 | for _, p := range b.pkgs { | |
48 | name := filepath.Join(p.Dir, p.Name+"-packr.go") | |
49 | fmt.Printf("--> packing %s\n", name) | |
50 | f, err := os.Create(name) | |
51 | if err != nil { | |
52 | return errors.WithStack(err) | |
53 | } | |
54 | t, err := template.New("").Parse(tmpl) | |
55 | ||
56 | if err != nil { | |
57 | return errors.WithStack(err) | |
58 | } | |
59 | err = t.Execute(f, p) | |
60 | if err != nil { | |
61 | return errors.WithStack(err) | |
62 | } | |
63 | } | |
64 | return nil | |
65 | } | |
66 | ||
67 | func (b *Builder) process(path string) error { | |
68 | ext := filepath.Ext(path) | |
69 | if ext != ".go" || invalidFilePattern.MatchString(path) { | |
70 | return nil | |
71 | } | |
72 | ||
73 | bb, err := ioutil.ReadFile(path) | |
74 | if err != nil { | |
75 | return errors.WithStack(err) | |
76 | } | |
77 | fb := string(bb) | |
78 | ||
79 | matches := boxPattern.FindAllStringSubmatch(fb, -1) | |
80 | if len(matches) == 0 { | |
81 | return nil | |
82 | } | |
83 | ||
84 | pk := pkg{ | |
85 | Dir: filepath.Dir(path), | |
86 | Boxes: []box{}, | |
87 | } | |
88 | pname := packagePattern.FindStringSubmatch(fb) | |
89 | pk.Name = pname[1] | |
90 | ||
91 | for _, m := range matches { | |
92 | bx := &box{ | |
93 | Name: m[1], | |
94 | Files: []file{}, | |
95 | } | |
96 | err = bx.Walk(filepath.Join(pk.Dir, bx.Name)) | |
97 | if err != nil { | |
98 | return errors.WithStack(err) | |
99 | } | |
100 | if len(bx.Files) > 0 { | |
101 | pk.Boxes = append(pk.Boxes, *bx) | |
102 | } | |
103 | } | |
104 | ||
105 | if len(pk.Boxes) > 0 { | |
106 | b.addPkg(pk) | |
107 | } | |
108 | return nil | |
109 | } | |
110 | ||
111 | func (b *Builder) addPkg(p pkg) { | |
112 | if _, ok := b.pkgs[p.Name]; !ok { | |
113 | b.pkgs[p.Name] = p | |
114 | return | |
115 | } | |
116 | pp := b.pkgs[p.Name] | |
117 | pp.Boxes = append(pp.Boxes, p.Boxes...) | |
118 | b.pkgs[p.Name] = pp | |
119 | } | |
120 | ||
121 | // New Builder with a given context and path | |
122 | func New(ctx context.Context, path string) *Builder { | |
123 | return &Builder{ | |
124 | Context: ctx, | |
125 | RootPath: path, | |
126 | pkgs: map[string]pkg{}, | |
127 | } | |
128 | } |
0 | package builder | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "context" | |
5 | "io/ioutil" | |
6 | "os" | |
7 | "os/exec" | |
8 | "path/filepath" | |
9 | "testing" | |
10 | ||
11 | "github.com/stretchr/testify/require" | |
12 | ) | |
13 | ||
14 | func Test_Builder_Run(t *testing.T) { | |
15 | r := require.New(t) | |
16 | ||
17 | root := "../example" | |
18 | defer Clean(root) | |
19 | ||
20 | exPackr := filepath.Join(root, "example-packr.go") | |
21 | r.False(fileExists(exPackr)) | |
22 | ||
23 | fooPackr := filepath.Join(root, "foo", "foo-packr.go") | |
24 | r.False(fileExists(fooPackr)) | |
25 | ||
26 | b := New(context.Background(), root) | |
27 | err := b.Run() | |
28 | r.NoError(err) | |
29 | ||
30 | r.True(fileExists(exPackr)) | |
31 | r.True(fileExists(fooPackr)) | |
32 | ||
33 | bb, err := ioutil.ReadFile(exPackr) | |
34 | r.NoError(err) | |
35 | r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./assets", "/app.css", "\"Ym9keSB7CiAgYmFja2dyb3VuZDogcmVkOwp9Cg==\"")`))) | |
36 | r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./assets", "/app.js", "\"YWxlcnQoImhlbGxvISIpOwo=\"")`))) | |
37 | ||
38 | bb, err = ioutil.ReadFile(fooPackr) | |
39 | r.NoError(err) | |
40 | r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../assets", "/app.css", "\"Ym9keSB7CiAgYmFja2dyb3VuZDogcmVkOwp9Cg==\"")`))) | |
41 | r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../assets", "/app.js", "\"YWxlcnQoImhlbGxvISIpOwo=\"")`))) | |
42 | r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../templates", "/index.html", "\"PCFET0NUWVBFIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiIC8+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoIiAvPgogICAgPHRpdGxlPklOREVYPC90aXRsZT4KICAgIGxpbmsKICA8L2hlYWQ+CiAgPGJvZHk+CiAgICBib2R5CiAgPC9ib2R5Pgo8L2h0bWw+Cg==\"")`))) | |
43 | } | |
44 | ||
45 | func Test_Binary_Builds(t *testing.T) { | |
46 | r := require.New(t) | |
47 | pwd, _ := os.Getwd() | |
48 | defer os.Chdir(pwd) | |
49 | ||
50 | root := "../example" | |
51 | defer Clean(root) | |
52 | defer os.RemoveAll(filepath.Join(root, "bin")) | |
53 | ||
54 | b := New(context.Background(), root) | |
55 | err := b.Run() | |
56 | r.NoError(err) | |
57 | ||
58 | os.Chdir(root) | |
59 | cmd := exec.Command("go", "build", "-v", "-o", "bin/example") | |
60 | err = cmd.Run() | |
61 | r.NoError(err) | |
62 | ||
63 | r.True(fileExists("bin/example")) | |
64 | } | |
65 | ||
66 | func fileExists(path string) bool { | |
67 | _, err := os.Stat(path) | |
68 | return err == nil | |
69 | } |
0 | package builder | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "os" | |
5 | "path/filepath" | |
6 | "strings" | |
7 | ) | |
8 | ||
9 | // Clean up an *-packr.go files | |
10 | func Clean(root string) { | |
11 | filepath.Walk(root, func(path string, info os.FileInfo, err error) error { | |
12 | base := filepath.Base(path) | |
13 | if base == ".git" || base == "vendor" || base == "node_modules" { | |
14 | return filepath.SkipDir | |
15 | } | |
16 | if info.IsDir() { | |
17 | return nil | |
18 | } | |
19 | if strings.Contains(base, "-packr.go") { | |
20 | fmt.Printf("----> cleaning up %s\n", path) | |
21 | os.Remove(path) | |
22 | } | |
23 | return nil | |
24 | }) | |
25 | } |
0 | package builder | |
1 | ||
2 | var tmpl = `package {{.Name}} | |
3 | ||
4 | import "github.com/gobuffalo/packr" | |
5 | ||
6 | // !!! GENERATE FILE !!! | |
7 | // Do NOT hand edit this file!! | |
8 | // It is recommended that you do not check into this file into SCM. | |
9 | // We STRONGLY recommend you delete this file after you have built your | |
10 | // Go binary. You can use the "packr clean" command to clean up this, | |
11 | // and any other packr generated files. | |
12 | func init() { | |
13 | {{ range $box := .Boxes -}} | |
14 | {{range .Files -}} | |
15 | packr.PackJSONBytes("{{$box.Name}}", "{{.Name}}", "{{.Contents}}") | |
16 | {{end -}} | |
17 | {{end -}} | |
18 | } | |
19 | ` |
0 | alert("hello!"); |
0 | package example | |
1 | ||
2 | import "github.com/gobuffalo/packr" | |
3 | ||
4 | func init() { | |
5 | packr.NewBox("./assets") | |
6 | } |
0 | package foo | |
1 | ||
2 | import "github.com/gobuffalo/packr" | |
3 | ||
4 | func init() { | |
5 | packr.NewBox("../assets") | |
6 | } |
0 | package foo | |
1 | ||
2 | import "github.com/gobuffalo/packr" | |
3 | ||
4 | func init() { | |
5 | packr.NewBox("../templates") | |
6 | } |
0 | <!DOCTYPE html> | |
1 | <html> | |
2 | <head> | |
3 | <meta charset="utf-8" /> | |
4 | <meta name="viewport" content="width=device-width" /> | |
5 | <title>INDEX</title> | |
6 | link | |
7 | </head> | |
8 | <body> | |
9 | body | |
10 | </body> | |
11 | </html> |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "os" | |
5 | ) | |
6 | ||
7 | type file struct { | |
8 | *bytes.Buffer | |
9 | Name string | |
10 | info fileInfo | |
11 | } | |
12 | ||
13 | func (f file) Close() error { | |
14 | return nil | |
15 | } | |
16 | ||
17 | func (f file) Seek(offset int64, whence int) (int64, error) { | |
18 | return 0, nil | |
19 | } | |
20 | ||
21 | func (f file) Readdir(count int) ([]os.FileInfo, error) { | |
22 | return []os.FileInfo{f.info}, nil | |
23 | } | |
24 | ||
25 | func (f file) Stat() (os.FileInfo, error) { | |
26 | return f.info, nil | |
27 | } |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "os" | |
4 | "time" | |
5 | ) | |
6 | ||
7 | type fileInfo struct { | |
8 | Path string | |
9 | Contents []byte | |
10 | size int64 | |
11 | modTime time.Time | |
12 | } | |
13 | ||
14 | func (f fileInfo) Name() string { | |
15 | return f.Path | |
16 | } | |
17 | ||
18 | func (f fileInfo) Size() int64 { | |
19 | return f.size | |
20 | } | |
21 | ||
22 | func (f fileInfo) Mode() os.FileMode { | |
23 | return 0444 | |
24 | } | |
25 | ||
26 | func (f fileInfo) ModTime() time.Time { | |
27 | return f.modTime | |
28 | } | |
29 | ||
30 | func (f fileInfo) IsDir() bool { | |
31 | return false | |
32 | } | |
33 | ||
34 | func (f fileInfo) Sys() interface{} { | |
35 | return nil | |
36 | } |
0 | goodbye cruel world! |
0 | hello world! |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "net/http" | |
5 | "time" | |
6 | ) | |
7 | ||
8 | // HTTPBox implements http.FileSystem which allows the use of Box with a http.FileServer. | |
9 | // e.g.: http.Handle("/", http.FileServer(packr.NewBox("http-files").HTTPBox())) | |
10 | type HTTPBox struct { | |
11 | Box | |
12 | } | |
13 | ||
14 | // HTTPBox creates a new HTTPBox from an existing Box | |
15 | func (b Box) HTTPBox() HTTPBox { | |
16 | return HTTPBox{ | |
17 | Box: b, | |
18 | } | |
19 | } | |
20 | ||
21 | // Open returns a File using the http.File interface | |
22 | func (hb HTTPBox) Open(name string) (http.File, error) { | |
23 | bb := &bytes.Buffer{} | |
24 | b, err := hb.MustBytes(name) | |
25 | if err != nil { | |
26 | return nil, err | |
27 | } | |
28 | bb.Write(b) | |
29 | f := file{ | |
30 | Buffer: bb, | |
31 | Name: name, | |
32 | info: fileInfo{ | |
33 | Path: name, | |
34 | Contents: b, | |
35 | size: int64(len(b)), | |
36 | modTime: time.Now(), | |
37 | }, | |
38 | } | |
39 | return f, nil | |
40 | } |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "net/http" | |
4 | "net/http/httptest" | |
5 | "testing" | |
6 | ||
7 | "github.com/stretchr/testify/require" | |
8 | ) | |
9 | ||
10 | func Test_HTTPBox(t *testing.T) { | |
11 | r := require.New(t) | |
12 | ||
13 | mux := http.NewServeMux() | |
14 | mux.Handle("/", http.FileServer(testBox.HTTPBox())) | |
15 | ||
16 | req, err := http.NewRequest("GET", "/hello.txt", nil) | |
17 | r.NoError(err) | |
18 | ||
19 | res := httptest.NewRecorder() | |
20 | ||
21 | mux.ServeHTTP(res, req) | |
22 | ||
23 | r.Equal(200, res.Code) | |
24 | r.Equal("hello world!\n", res.Body.String()) | |
25 | } |
0 | package cmd | |
1 | ||
2 | import ( | |
3 | "github.com/gobuffalo/packr/builder" | |
4 | "github.com/spf13/cobra" | |
5 | ) | |
6 | ||
7 | var cleanCmd = &cobra.Command{ | |
8 | Use: "clean", | |
9 | Short: "removes any *-packr.go files", | |
10 | Run: func(cmd *cobra.Command, args []string) { | |
11 | builder.Clean(input) | |
12 | }, | |
13 | } | |
14 | ||
15 | func init() { | |
16 | rootCmd.AddCommand(cleanCmd) | |
17 | } |
0 | package cmd | |
1 | ||
2 | import ( | |
3 | "context" | |
4 | "os" | |
5 | ||
6 | "github.com/gobuffalo/packr/builder" | |
7 | "github.com/spf13/cobra" | |
8 | ) | |
9 | ||
10 | var input string | |
11 | ||
12 | var rootCmd = &cobra.Command{ | |
13 | Use: "packr", | |
14 | Short: "compiles static files into Go files", | |
15 | RunE: func(cmd *cobra.Command, args []string) error { | |
16 | b := builder.New(context.Background(), input) | |
17 | return b.Run() | |
18 | }, | |
19 | } | |
20 | ||
21 | func init() { | |
22 | rootCmd.Flags().StringVarP(&input, "input", "i", ".", "path to scan for packr Boxes") | |
23 | } | |
24 | ||
25 | // Execute the commands | |
26 | func Execute() { | |
27 | if err := rootCmd.Execute(); err != nil { | |
28 | os.Exit(-1) | |
29 | } | |
30 | } |
0 | // Copyright © 2017 NAME HERE <EMAIL ADDRESS> | |
1 | // | |
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | // you may not use this file except in compliance with the License. | |
4 | // You may obtain a copy of the License at | |
5 | // | |
6 | // http://www.apache.org/licenses/LICENSE-2.0 | |
7 | // | |
8 | // Unless required by applicable law or agreed to in writing, software | |
9 | // distributed under the License is distributed on an "AS IS" BASIS, | |
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
11 | // See the License for the specific language governing permissions and | |
12 | // limitations under the License. | |
13 | ||
14 | package main | |
15 | ||
16 | import "github.com/gobuffalo/packr/packr/cmd" | |
17 | ||
18 | func main() { | |
19 | cmd.Execute() | |
20 | } |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "path/filepath" | |
5 | "sync" | |
6 | ||
7 | "github.com/pkg/errors" | |
8 | ) | |
9 | ||
10 | var gil = &sync.Mutex{} | |
11 | var data = map[string][]byte{} | |
12 | ||
13 | // PackBytes packs bytes for a file into a box. | |
14 | func PackBytes(box string, name string, bb []byte) { | |
15 | gil.Lock() | |
16 | defer gil.Unlock() | |
17 | data[filepath.Join(box, name)] = bb | |
18 | } | |
19 | ||
20 | // PackJSONBytes packs JSON encoded bytes for a file into a box. | |
21 | func PackJSONBytes(box string, name string, jbb string) error { | |
22 | bb := []byte{} | |
23 | err := json.Unmarshal([]byte(jbb), &bb) | |
24 | if err != nil { | |
25 | return err | |
26 | } | |
27 | PackBytes(box, name, bb) | |
28 | return nil | |
29 | } | |
30 | ||
31 | func find(box string, name string) ([]byte, error) { | |
32 | p := filepath.Join(box, name) | |
33 | if b, ok := data[p]; ok { | |
34 | return b, nil | |
35 | } | |
36 | return []byte{}, errors.Errorf("%s not found", p) | |
37 | } |
0 | package packr | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "testing" | |
5 | ||
6 | "github.com/stretchr/testify/require" | |
7 | ) | |
8 | ||
9 | var testBox = NewBox("./fixtures") | |
10 | ||
11 | func Test_PackBytes(t *testing.T) { | |
12 | r := require.New(t) | |
13 | PackBytes(testBox.Path, "foo", []byte("bar")) | |
14 | s := testBox.String("foo") | |
15 | r.Equal("bar", s) | |
16 | } | |
17 | ||
18 | func Test_PackJSONBytes(t *testing.T) { | |
19 | r := require.New(t) | |
20 | b, err := json.Marshal([]byte("json bytes")) | |
21 | r.NoError(err) | |
22 | err = PackJSONBytes(testBox.Path, "the bytes", string(b)) | |
23 | r.NoError(err) | |
24 | s, err := testBox.MustBytes("the bytes") | |
25 | r.NoError(err) | |
26 | r.Equal([]byte("json bytes"), s) | |
27 | } |