Codebase list golang-github-gobuffalo-packr / cbdaebd
New upstream version 1.30.1 Sophie Brun 3 years ago
187 changed file(s) with 8740 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
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 ./packr2
2 .DS_Store
3 doc
4 tmp
5 pkg
6 *.gem
7 *.pid
8 coverage
9 coverage.data
10 build/*
11 *.pbxuser
12 *.mode1v3
13 .svn
14 profile
15 .console_history
16 .sass-cache/*
17 .rake_tasks~
18 *.log.lck
19 solr/
20 .jhw-cache/
21 jhw.*
22 *.sublime*
23 node_modules/
24 dist/
25 generated/
26 .vendor/
27 bin/*
28 gin-bin
29 /packr_darwin_amd64
30 /packr_linux_amd64
31 .vscode/
32 debug.test
33 .grifter/
34 *-packr.go
35
0 {
1 "Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"]
2 }
0 # Code generated by github.com/gobuffalo/release. DO NOT EDIT.
1 # Edit .goreleaser.yml.plush instead
2
3 builds:
4 -
5 goos:
6 - darwin
7 - linux
8 - windows
9 env:
10 - CGO_ENABLED=0
11 main: ./packr/main.go
12 binary: packr
13
14 checksum:
15 name_template: 'checksums.txt'
16
17 snapshot:
18 name_template: "{{ .Tag }}-next"
19
20 changelog:
21 sort: asc
22 filters:
23 exclude:
24 - '^docs:'
25 - '^test:'
26
27 brew:
28 github:
29 owner: gobuffalo
30 name: homebrew-tap
31
0 builds:
1 -
2 goos:
3 - darwin
4 - linux
5 - windows
6 env:
7 - CGO_ENABLED=0
8 main: ./packr/main.go
9 binary: packr
10
11 checksum:
12 name_template: 'checksums.txt'
13
14 snapshot:
15 name_template: "{{ .Tag }}-next"
16
17 changelog:
18 sort: asc
19 filters:
20 exclude:
21 - '^docs:'
22 - '^test:'
23 <%= if (brew) { %>
24 brew:
25 github:
26 owner: gobuffalo
27 name: homebrew-tap
28 <% } %>
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 TAGS ?= "sqlite"
1 GO_BIN ?= go
2
3 install: deps
4 echo "installing packr v1"
5 packr
6 $(GO_BIN) install -v ./packr
7
8 tidy:
9 ifeq ($(GO111MODULE),on)
10 $(GO_BIN) mod tidy
11 else
12 echo skipping go mod tidy
13 endif
14
15 deps:
16 rm -rf packrd
17 rm -rf v2/packrd
18 $(GO_BIN) get github.com/gobuffalo/release
19 $(GO_BIN) get -tags ${TAGS} -t ./...
20 $(GO_BIN) install -v ./packr
21 packr clean
22 make tidy
23
24 build: deps
25 packr
26 $(GO_BIN) build -v .
27 make tidy
28
29 test:
30 packr clean
31 $(GO_BIN) test -tags ${TAGS} ./...
32 packr clean
33
34 ci-deps:
35 rm -rf packrd
36 rm -rf v2/packrd
37 $(GO_BIN) get -tags ${TAGS} -t ./...
38 $(GO_BIN) install -v ./packr
39 packr clean
40 make tidy
41
42 ci-test:
43 $(GO_BIN) test -v -tags ${TAGS} -race ./...
44 make tidy
45 cd ./v2 && make ci-test
46
47 lint:
48 gometalinter --vendor ./... --deadline=1m --skip=internal
49
50 update:
51 $(GO_BIN) get -u -tags ${TAGS}
52 make tidy
53 packr
54 make test
55 make install
56 make tidy
57
58 release-test:
59 $(GO_BIN) test -tags ${TAGS} -race ./...
60
61 release:
62 release -y -f version.go
63 make tidy
0 # packr (v1)
1
2 [![GoDoc](https://godoc.org/github.com/gobuffalo/packr?status.svg)](https://godoc.org/github.com/gobuffalo/packr)
3
4 ## Packr has been updated to `v2`! Please read the `./v2/README.md` file for more details.
5
6 ---
7
8 Packr is a simple solution for bundling static assets inside of Go binaries. Most importantly it does it in a way that is friendly to developers while they are developing.
9
10 ## Intro Video
11
12 To get an idea of the what and why of packr, please enjoy this short video: [https://vimeo.com/219863271](https://vimeo.com/219863271).
13
14 ## Installation
15
16 To install Packr utility
17
18 ```text
19 $ go get -u github.com/gobuffalo/packr/packr
20 ```
21
22 To get the dependency
23
24 ```text
25 $ go get -u github.com/gobuffalo/packr
26 ```
27
28 ## Usage
29
30 ### In Code
31
32 The first step in using Packr is to create a new box. A box represents a folder on disk. Once you have a box you can get `string` or `[]byte` representations of the file.
33
34 ```go
35 // set up a new box by giving it a (relative) path to a folder on disk:
36 box := packr.NewBox("./templates")
37
38 // Get the string representation of a file, or an error if it doesn't exist:
39 html, err := box.FindString("index.html")
40
41 // Get the []byte representation of a file, or an error if it doesn't exist:
42 html, err := box.FindBytes("index.html")
43 ```
44
45 ### What is a Box?
46
47 A box represents a folder, and any sub-folders, on disk that you want to have access to in your binary. When compiling a binary using the `packr` CLI the contents of the folder will be converted into Go files that can be compiled inside of a "standard" go binary. Inside of the compiled binary the files will be read from memory. When working locally the files will be read directly off of disk. This is a seamless switch that doesn't require any special attention on your part.
48
49 #### Example
50
51 Assume the follow directory structure:
52
53 ```
54 ├── main.go
55 └── templates
56 ├── admin
57 │   └── index.html
58 └── index.html
59 ```
60
61 The following program will read the `./templates/admin/index.html` file and print it out.
62
63 ```go
64 package main
65
66 import (
67 "fmt"
68
69 "github.com/gobuffalo/packr"
70 )
71
72 func main() {
73 box := packr.NewBox("./templates")
74
75 s, err := box.FindString("admin/index.html")
76 if err != nil {
77 log.Fatal(err)
78 }
79 fmt.Println(s)
80 }
81 ```
82
83 ### Development Made Easy
84
85 In order to get static files into a Go binary, those files must first be converted to Go code. To do that, Packr, ships with a few tools to help build binaries. See below.
86
87 During development, however, it is painful to have to keep running a tool to compile those files.
88
89 Packr uses the following resolution rules when looking for a file:
90
91 1. Look for the file in-memory (inside a Go binary)
92 1. Look for the file on disk (during development)
93
94 Because Packr knows how to fall through to the file system, developers don't need to worry about constantly compiling their static files into a binary. They can work unimpeded.
95
96 Packr takes file resolution a step further. When declaring a new box you use a relative path, `./templates`. When Packr receives this call it calculates out the absolute path to that directory. By doing this it means you can be guaranteed that Packr can find your files correctly, even if you're not running in the directory that the box was created in. This helps with the problem of testing, where Go changes the `pwd` for each package, making relative paths difficult to work with. This is not a problem when using Packr.
97
98 ---
99
100 ## Usage with HTTP
101
102 A box implements the [`http.FileSystem`](https://golang.org/pkg/net/http/#FileSystem) interface, meaning it can be used to serve static files.
103
104 ```go
105 package main
106
107 import (
108 "net/http"
109
110 "github.com/gobuffalo/packr"
111 )
112
113 func main() {
114 box := packr.NewBox("./templates")
115
116 http.Handle("/", http.FileServer(box))
117 http.ListenAndServe(":3000", nil)
118 }
119 ```
120
121 ---
122
123 ## Building a Binary (the easy way)
124
125 When it comes time to build, or install, your Go binary, simply use `packr build` or `packr install` just as you would `go build` or `go install`. All flags for the `go` tool are supported and everything works the way you expect, the only difference is your static assets are now bundled in the generated binary. If you want more control over how this happens, looking at the following section on building binaries (the hard way).
126
127 ## Building a Binary (the hard way)
128
129 Before you build your Go binary, run the `packr` command first. It will look for all the boxes in your code and then generate `.go` files that pack the static files into bytes that can be bundled into the Go binary.
130
131 ```
132 $ packr
133 ```
134
135 Then run your `go build command` like normal.
136
137 *NOTE*: It is not recommended to check-in these generated `-packr.go` files. They can be large, and can easily become out of date if not careful. It is recommended that you always run `packr clean` after running the `packr` tool.
138
139 #### Cleaning Up
140
141 When you're done it is recommended that you run the `packr clean` command. This will remove all of the generated files that Packr created for you.
142
143 ```
144 $ packr clean
145 ```
146
147 Why do you want to do this? Packr first looks to the information stored in these generated files, if the information isn't there it looks to disk. This makes it easy to work with in development.
148
149 ---
150
151 ## Building/Moving a portable release
152
153 When it comes to building multiple releases you typically want that release to be built in a specific directory.
154
155 For example: `./releases`
156
157 However, because passing a `.go` file requires absolute paths, we must compile the release in the appropriate absolute path.
158
159 ```bash
160 GOOS=linux GOARCH=amd64 packr build
161 ```
162
163 Now your `project_name` binary will be built at the root of your project dir. Great!
164
165 All that is left to do is to move that binary to your release dir:
166
167 Linux/macOS/Windows (bash)
168
169 ```bash
170 mv ./project_name ./releases
171 ```
172
173 Windows (cmd):
174
175 ```cmd
176 move ./project_name ./releases
177 ```
178
179 Powershell:
180
181 ```powershell
182 Move-Item -Path .\project_name -Destination .\releases\
183 ```
184
185 If you _target_ for Windows when building don't forget that it's `project_name.exe`
186
187 Now you can make multiple releases and all of your needed static files will be available!
188
189 #### Summing it up:
190
191 Example Script for building to 3 common targets:
192
193 ```bash
194 GOOS=darwin GOARCH=amd64 packr build && mv ./project_name ./releases/darwin-project_name \
195 && GOOS=linux GOARCH=amd64 packr build && mv ./project_name ./releases/linux-project_name \
196 && GOOS=windows GOARCH=386 packr build && mv ./project_name.exe ./releases/project_name.exe \
197 && packr clean
198 ```
199
200 ---
201
202 ## Debugging
203
204 The `packr` command passes all arguments down to the underlying `go` command, this includes the `-v` flag to print out `go build` information. Packr looks for the `-v` flag, and will turn on its own verbose logging. This is very useful for trying to understand what the `packr` command is doing when it is run.
0 # github.com/gobuffalo/packr Stands on the Shoulders of Giants
1
2 github.com/gobuffalo/packr does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants, this project would not be possible. Please make sure to check them out and thank them for all of their hard work.
3
4 Thank you to the following **GIANTS**:
5
6
7 * [github.com/gobuffalo/envy](https://godoc.org/github.com/gobuffalo/envy)
8
9 * [github.com/gobuffalo/packd](https://godoc.org/github.com/gobuffalo/packd)
10
11 * [github.com/gobuffalo/packr/v2](https://godoc.org/github.com/gobuffalo/packr/v2)
12
13 * [github.com/spf13/cobra](https://godoc.org/github.com/spf13/cobra)
14
15 * [github.com/stretchr/testify](https://godoc.org/github.com/stretchr/testify)
16
17 * [golang.org/x/sync](https://godoc.org/golang.org/x/sync)
0 variables:
1 GOBIN: "$(GOPATH)/bin" # Go binaries path
2 GOPATH: "$(system.defaultWorkingDirectory)/gopath" # Go workspace path
3 modulePath: "$(GOPATH)/src/github.com/$(build.repository.name)" # Path to the module"s code
4
5 jobs:
6 - job: Windows
7 pool:
8 vmImage: "vs2017-win2016"
9 strategy:
10 matrix:
11 go 1.10:
12 go_version: "1.10"
13 go 1.11 (on):
14 go_version: "1.11.5"
15 GO111MODULE: "on"
16 go 1.11 (off):
17 go_version: "1.11.5"
18 GO111MODULE: "off"
19 go 1.12 (on):
20 go_version: "1.12"
21 GO111MODULE: "on"
22 go 1.12 (off):
23 go_version: "1.12"
24 GO111MODULE: "off"
25 steps:
26 - template: azure-tests.yml
27
28 - job: macOS
29 pool:
30 vmImage: "macOS-10.13"
31 strategy:
32 matrix:
33 go 1.10:
34 go_version: "1.10"
35 go 1.11 (on):
36 go_version: "1.11.5"
37 GO111MODULE: "on"
38 go 1.11 (off):
39 go_version: "1.11.5"
40 GO111MODULE: "off"
41 go 1.12 (on):
42 go_version: "1.12"
43 GO111MODULE: "on"
44 go 1.12 (off):
45 go_version: "1.12"
46 GO111MODULE: "off"
47 steps:
48 - template: azure-tests.yml
49
50 - job: Linux
51 pool:
52 vmImage: "ubuntu-16.04"
53 strategy:
54 matrix:
55 go 1.10:
56 go_version: "1.10"
57 go 1.11 (on):
58 go_version: "1.11.5"
59 GO111MODULE: "on"
60 go 1.11 (off):
61 go_version: "1.11.5"
62 GO111MODULE: "off"
63 go 1.12 (on):
64 go_version: "1.12"
65 GO111MODULE: "on"
66 go 1.12 (off):
67 go_version: "1.12"
68 GO111MODULE: "off"
69 steps:
70 - template: azure-tests.yml
0 steps:
1 - task: GoTool@0
2 inputs:
3 version: $(go_version)
4 - task: Bash@3
5 inputs:
6 targetType: inline
7 script: |
8 mkdir -p "$(GOBIN)"
9 mkdir -p "$(GOPATH)/pkg"
10 mkdir -p "$(modulePath)"
11 shopt -s extglob
12 mv !(gopath) "$(modulePath)"
13 displayName: "Setup Go Workspace"
14 - script: |
15 go get -t -v ./...
16 go test -race ./...
17 go install -v ./packr
18 cd v2
19 go get -t -v ./...
20 go test -race ./...
21 go install -v ./packr2
22 workingDirectory: "$(modulePath)"
23 displayName: "Tests"
0 package packr
1
2 import (
3 "bytes"
4 "compress/gzip"
5 "fmt"
6 "io/ioutil"
7 "net/http"
8 "os"
9 "path"
10 "path/filepath"
11 "runtime"
12 "strings"
13
14 "github.com/gobuffalo/packd"
15 )
16
17 var (
18 // ErrResOutsideBox gets returned in case of the requested resources being outside the box
19 ErrResOutsideBox = fmt.Errorf("Can't find a resource outside the box")
20 )
21
22 var _ packd.Box = Box{}
23 var _ packd.HTTPBox = Box{}
24 var _ packd.Lister = Box{}
25 var _ packd.Addable = Box{}
26 var _ packd.Walkable = Box{}
27 var _ packd.Finder = Box{}
28 var _ packd.LegacyBox = Box{}
29
30 // NewBox returns a Box that can be used to
31 // retrieve files from either disk or the embedded
32 // binary.
33 func NewBox(path string) Box {
34 var cd string
35 if !filepath.IsAbs(path) {
36 _, filename, _, _ := runtime.Caller(1)
37 cd = filepath.Dir(filename)
38 }
39
40 // this little hack courtesy of the `-cover` flag!!
41 cov := filepath.Join("_test", "_obj_test")
42 cd = strings.Replace(cd, string(filepath.Separator)+cov, "", 1)
43 if !filepath.IsAbs(cd) && cd != "" {
44 cd = filepath.Join(GoPath(), "src", cd)
45 }
46
47 return Box{
48 Path: path,
49 callingDir: cd,
50 data: map[string][]byte{},
51 }
52 }
53
54 // Box represent a folder on a disk you want to
55 // have access to in the built Go binary.
56 type Box struct {
57 Path string
58 callingDir string
59 data map[string][]byte
60 directories map[string]bool
61 }
62
63 // AddString converts t to a byteslice and delegates to AddBytes to add to b.data
64 func (b Box) AddString(path string, t string) error {
65 b.AddBytes(path, []byte(t))
66 return nil
67 }
68
69 // AddBytes sets t in b.data by the given path
70 func (b Box) AddBytes(path string, t []byte) error {
71 b.data[path] = t
72 return nil
73 }
74
75 // Deprecated: Use FindString instead.
76 func (b Box) String(name string) string {
77 bb, _ := b.FindString(name)
78 return bb
79 }
80
81 // Deprecated: Use FindString instead.
82 func (b Box) MustString(name string) (string, error) {
83 return b.FindString(name)
84 }
85
86 // Deprecated: Use Find instead.
87 func (b Box) Bytes(name string) []byte {
88 bb, _ := b.Find(name)
89 return bb
90 }
91
92 // Deprecated: Use Find instead.
93 func (b Box) MustBytes(name string) ([]byte, error) {
94 return b.Find(name)
95 }
96
97 // FindString returns either the string of the requested
98 // file or an error if it can not be found.
99 func (b Box) FindString(name string) (string, error) {
100 bb, err := b.Find(name)
101 return string(bb), err
102 }
103
104 // Find returns either the byte slice of the requested
105 // file or an error if it can not be found.
106 func (b Box) Find(name string) ([]byte, error) {
107 f, err := b.find(name)
108 if err == nil {
109 bb := &bytes.Buffer{}
110 bb.ReadFrom(f)
111 return bb.Bytes(), err
112 }
113 return nil, err
114 }
115
116 // Has returns true if the resource exists in the box
117 func (b Box) Has(name string) bool {
118 _, err := b.find(name)
119 if err != nil {
120 return false
121 }
122 return true
123 }
124
125 func (b Box) decompress(bb []byte) []byte {
126 reader, err := gzip.NewReader(bytes.NewReader(bb))
127 if err != nil {
128 return bb
129 }
130 defer reader.Close()
131
132 data, err := ioutil.ReadAll(reader)
133 if err != nil {
134 return bb
135 }
136 return data
137 }
138
139 func (b Box) find(name string) (File, error) {
140 if bb, ok := b.data[name]; ok {
141 return packd.NewFile(name, bytes.NewReader(bb))
142 }
143
144 if b.directories == nil {
145 b.indexDirectories()
146 }
147
148 cleanName := filepath.ToSlash(filepath.Clean(name))
149 // Ensure name is not outside the box
150 if strings.HasPrefix(cleanName, "../") {
151 return nil, ErrResOutsideBox
152 }
153 // Absolute name is considered as relative to the box root
154 cleanName = strings.TrimPrefix(cleanName, "/")
155
156 if _, ok := data[b.Path]; ok {
157 if bb, ok := data[b.Path][cleanName]; ok {
158 bb = b.decompress(bb)
159 return packd.NewFile(cleanName, bytes.NewReader(bb))
160 }
161 if _, ok := b.directories[cleanName]; ok {
162 return packd.NewDir(cleanName)
163 }
164 if filepath.Ext(cleanName) != "" {
165 // The Handler created by http.FileSystem checks for those errors and
166 // returns http.StatusNotFound instead of http.StatusInternalServerError.
167 return nil, os.ErrNotExist
168 }
169 return nil, os.ErrNotExist
170 }
171
172 // Not found in the box virtual fs, try to get it from the file system
173 cleanName = filepath.FromSlash(cleanName)
174 p := filepath.Join(b.callingDir, b.Path, cleanName)
175 return fileFor(p, cleanName)
176 }
177
178 // Open returns a File using the http.File interface
179 func (b Box) Open(name string) (http.File, error) {
180 return b.find(name)
181 }
182
183 // List shows "What's in the box?"
184 func (b Box) List() []string {
185 var keys []string
186
187 if b.data == nil || len(b.data) == 0 {
188 b.Walk(func(path string, info File) error {
189 finfo, _ := info.FileInfo()
190 if !finfo.IsDir() {
191 keys = append(keys, finfo.Name())
192 }
193 return nil
194 })
195 } else {
196 for k := range b.data {
197 keys = append(keys, k)
198 }
199 }
200 return keys
201 }
202
203 func (b *Box) indexDirectories() {
204 b.directories = map[string]bool{}
205 if _, ok := data[b.Path]; ok {
206 for name := range data[b.Path] {
207 prefix, _ := path.Split(name)
208 // Even on Windows the suffix appears to be a /
209 prefix = strings.TrimSuffix(prefix, "/")
210 b.directories[prefix] = true
211 }
212 }
213 }
214
215 func fileFor(p string, name string) (File, error) {
216 fi, err := os.Stat(p)
217 if err != nil {
218 return nil, err
219 }
220 if fi.IsDir() {
221 return packd.NewDir(p)
222 }
223 if bb, err := ioutil.ReadFile(p); err == nil {
224 return packd.NewFile(name, bytes.NewReader(bb))
225 }
226 return nil, os.ErrNotExist
227 }
0 package packr
1
2 import (
3 "bytes"
4 "io/ioutil"
5 "os"
6 "runtime"
7 "sort"
8 "strings"
9 "testing"
10
11 "github.com/stretchr/testify/require"
12 )
13
14 func Test_Box_FindString(t *testing.T) {
15 r := require.New(t)
16 s, err := testBox.FindString("hello.txt")
17 r.NoError(err)
18 r.Equal("hello world!", strings.TrimSpace(s))
19
20 _, err = testBox.Find("idontexist.txt")
21 r.Error(err)
22 }
23
24 func Test_Box_FindBytes(t *testing.T) {
25 r := require.New(t)
26 s, err := testBox.Find("hello.txt")
27 r.NoError(err)
28 r.Equal([]byte("hello world!"), bytes.TrimSpace(s))
29
30 _, err = testBox.Find("idontexist.txt")
31 r.Error(err)
32 }
33
34 func Test_Box_Has(t *testing.T) {
35 r := require.New(t)
36 r.True(testBox.Has("hello.txt"))
37 r.False(testBox.Has("idontexist.txt"))
38 }
39
40 func Test_List_Virtual(t *testing.T) {
41 r := require.New(t)
42 mustHave := []string{"a", "b", "c", "d/a"}
43 actual := virtualBox.List()
44 sort.Strings(actual)
45 r.Equal(mustHave, actual)
46 }
47
48 func Test_List_Physical(t *testing.T) {
49 r := require.New(t)
50 mustHave := osPaths("MyFile.txt", "foo/a.txt", "foo/bar/b.txt", "goodbye.txt", "hello.txt", "index.html")
51 actual := testBox.List()
52 r.Equal(mustHave, actual)
53 }
54
55 func Test_Outside_Box(t *testing.T) {
56 r := require.New(t)
57 f, err := ioutil.TempFile("", "")
58 r.NoError(err)
59 defer os.RemoveAll(f.Name())
60 _, err = testBox.FindString(f.Name())
61 r.Error(err)
62 }
63
64 func Test_Box_find(t *testing.T) {
65 box := NewBox("./example")
66
67 onWindows := runtime.GOOS == "windows"
68 table := []struct {
69 name string
70 found bool
71 }{
72 {"assets/app.css", true},
73 {"assets\\app.css", onWindows},
74 {"foo/bar.baz", false},
75 {"bar", true},
76 {"bar/sub", true},
77 {"bar/foo", false},
78 {"bar/sub/sub.html", true},
79 }
80
81 for _, tt := range table {
82 t.Run(tt.name, func(st *testing.T) {
83 r := require.New(st)
84 _, err := box.find(tt.name)
85 if tt.found {
86 r.True(box.Has(tt.name))
87 r.NoError(err)
88 } else {
89 r.False(box.Has(tt.name))
90 r.Error(err)
91 }
92 })
93 }
94 }
95
96 func Test_Virtual_Directory_Not_Found(t *testing.T) {
97 r := require.New(t)
98 _, err := virtualBox.find("d")
99 r.NoError(err)
100 _, err = virtualBox.find("does-not-exist")
101 r.Error(err)
102 }
103
104 func Test_AddString(t *testing.T) {
105 r := require.New(t)
106
107 _, err := virtualBox.Find("string")
108 r.Error(err)
109
110 virtualBox.AddString("string", "hello")
111
112 s, err := virtualBox.FindString("string")
113 r.NoError(err)
114 r.Equal("hello", s)
115 }
116
117 func Test_AddBytes(t *testing.T) {
118 r := require.New(t)
119
120 _, err := virtualBox.Find("bytes")
121 r.Error(err)
122
123 virtualBox.AddBytes("bytes", []byte("hello"))
124
125 s, err := virtualBox.Find("bytes")
126 r.NoError(err)
127 r.Equal([]byte("hello"), s)
128 }
0 package builder
1
2 import (
3 "bytes"
4 "compress/gzip"
5 "encoding/json"
6 "fmt"
7 "io/ioutil"
8 "os"
9 "path/filepath"
10 "strings"
11 )
12
13 type box struct {
14 Name string
15 Files []file
16 compress bool
17 }
18
19 func (b *box) Walk(root string) error {
20 root, err := filepath.EvalSymlinks(root)
21 if err != nil {
22 return err
23 }
24 if _, err := os.Stat(root); err != nil {
25 // return nil
26 return fmt.Errorf("could not find folder for box: %s", root)
27 }
28 return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
29 if info == nil || info.IsDir() || strings.HasSuffix(info.Name(), "-packr.go") {
30 return nil
31 }
32 name := strings.Replace(path, root+string(os.PathSeparator), "", 1)
33 name = strings.Replace(name, "\\", "/", -1)
34 f := file{
35 Name: name,
36 }
37
38 DebugLog("packing file %s\n", f.Name)
39
40 bb, err := ioutil.ReadFile(path)
41 if err != nil {
42 return err
43 }
44 if b.compress {
45 bb, err = compressFile(bb)
46 if err != nil {
47 return err
48 }
49 }
50 bb, err = json.Marshal(bb)
51 if err != nil {
52 return err
53 }
54 f.Contents = strings.Replace(string(bb), "\"", "\\\"", -1)
55
56 DebugLog("packed file %s\n", f.Name)
57 b.Files = append(b.Files, f)
58 return nil
59 })
60 }
61
62 func compressFile(bb []byte) ([]byte, error) {
63 var buf bytes.Buffer
64 writer := gzip.NewWriter(&buf)
65 _, err := writer.Write(bb)
66 if err != nil {
67 return bb, err
68 }
69 err = writer.Close()
70 if err != nil {
71 return bb, err
72 }
73 return buf.Bytes(), nil
74 }
0 package builder
1
2 import (
3 "context"
4 "os"
5 "path/filepath"
6 "regexp"
7 "strings"
8 "sync"
9 "text/template"
10
11 "golang.org/x/sync/errgroup"
12 )
13
14 var DebugLog func(string, ...interface{})
15
16 func init() {
17 DebugLog = func(string, ...interface{}) {}
18 }
19
20 var invalidFilePattern = regexp.MustCompile(`(_test|-packr).go$`)
21
22 // Builder scans folders/files looking for `packr.NewBox` and then compiling
23 // the required static files into `<package-name>-packr.go` files so they can
24 // be built into Go binaries.
25 type Builder struct {
26 context.Context
27 RootPath string
28 IgnoredBoxes []string
29 IgnoredFolders []string
30 pkgs map[string]pkg
31 moot *sync.Mutex
32 Compress bool
33 }
34
35 // Run the builder.
36 func (b *Builder) Run() error {
37 wg := &errgroup.Group{}
38 root, err := filepath.EvalSymlinks(b.RootPath)
39 if err != nil {
40 return err
41 }
42 err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
43 if info == nil {
44 return filepath.SkipDir
45 }
46
47 base := strings.ToLower(filepath.Base(path))
48 if strings.HasPrefix(base, "_") {
49 return filepath.SkipDir
50 }
51 for _, f := range b.IgnoredFolders {
52 if strings.ToLower(f) == base {
53 if info.IsDir() {
54 return filepath.SkipDir
55 } else {
56 return nil
57 }
58 }
59 }
60 if !info.IsDir() {
61 wg.Go(func() error {
62 return b.process(path)
63 })
64 }
65 return nil
66 })
67 if err != nil {
68 return err
69 }
70 if err := wg.Wait(); err != nil {
71 return err
72 }
73 return b.dump()
74 }
75
76 func (b *Builder) dump() error {
77 for _, p := range b.pkgs {
78 name := filepath.Join(p.Dir, "a_"+p.Name+"-packr.go")
79 f, err := os.Create(name)
80 defer f.Close()
81 if err != nil {
82 return err
83 }
84 t, err := template.New("").Parse(tmpl)
85
86 if err != nil {
87 return err
88 }
89 err = t.Execute(f, p)
90 if err != nil {
91 return err
92 }
93 }
94 return nil
95 }
96
97 func (b *Builder) process(path string) error {
98 ext := filepath.Ext(path)
99 if ext != ".go" || invalidFilePattern.MatchString(path) {
100 return nil
101 }
102
103 v := newVisitor(path)
104 if err := v.Run(); err != nil {
105 return err
106 }
107
108 pk := pkg{
109 Dir: filepath.Dir(path),
110 Boxes: []box{},
111 Name: v.Package,
112 }
113
114 for _, n := range v.Boxes {
115 var ignored bool
116 for _, i := range b.IgnoredBoxes {
117 if n == i {
118 // this is an ignored box
119 ignored = true
120 break
121 }
122 }
123 if ignored {
124 continue
125 }
126 bx := &box{
127 Name: n,
128 Files: []file{},
129 compress: b.Compress,
130 }
131 DebugLog("building box %s\n", bx.Name)
132 p := filepath.Join(pk.Dir, bx.Name)
133 if err := bx.Walk(p); err != nil {
134 return err
135 }
136 if len(bx.Files) > 0 {
137 pk.Boxes = append(pk.Boxes, *bx)
138 }
139 DebugLog("built box %s with %q\n", bx.Name, bx.Files)
140 }
141
142 if len(pk.Boxes) > 0 {
143 b.addPkg(pk)
144 }
145 return nil
146 }
147
148 func (b *Builder) addPkg(p pkg) {
149 b.moot.Lock()
150 defer b.moot.Unlock()
151 if _, ok := b.pkgs[p.Name]; !ok {
152 b.pkgs[p.Name] = p
153 return
154 }
155 pp := b.pkgs[p.Name]
156 pp.Boxes = append(pp.Boxes, p.Boxes...)
157 b.pkgs[p.Name] = pp
158 }
159
160 // New Builder with a given context and path
161 func New(ctx context.Context, path string) *Builder {
162 return &Builder{
163 Context: ctx,
164 RootPath: path,
165 IgnoredBoxes: []string{},
166 IgnoredFolders: []string{"vendor", ".git", "node_modules", ".idea"},
167 pkgs: map[string]pkg{},
168 moot: &sync.Mutex{},
169 }
170 }
0 package builder
1
2 import (
3 "bytes"
4 "context"
5 "io/ioutil"
6 "os"
7 "path/filepath"
8 "testing"
9
10 "github.com/stretchr/testify/require"
11 )
12
13 func Test_Builder_Run(t *testing.T) {
14 r := require.New(t)
15
16 root := filepath.Join("..", "example")
17 Clean(root)
18 defer Clean(root)
19
20 exPackr := filepath.Join(root, "a_example-packr.go")
21
22 fooPackr := filepath.Join(root, "foo", "a_foo-packr.go")
23
24 b := New(context.Background(), root)
25 err := b.Run()
26 r.NoError(err)
27
28 r.True(fileExists(exPackr))
29 r.True(fileExists(fooPackr))
30
31 bb, err := ioutil.ReadFile(exPackr)
32 r.NoError(err)
33 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./assets", "app.css", "\"Ym9ke`)))
34 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./assets", "app.js", "\"YWxlcn`)))
35 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./templates", "index.html", "\"PCFET0NUWVBF`)))
36
37 bb, err = ioutil.ReadFile(fooPackr)
38 r.NoError(err)
39 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../assets", "app.css", "\"Ym9keS`)))
40 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../assets", "app.js", "\"YWxlcn`)))
41 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../templates", "index.html", "\"PCFET0NUW`)))
42 }
43
44 func Test_Builder_Run_Compress(t *testing.T) {
45 r := require.New(t)
46
47 root := filepath.Join("..", "example")
48 defer Clean(root)
49
50 exPackr := filepath.Join(root, "a_example-packr.go")
51
52 fooPackr := filepath.Join(root, "foo", "a_foo-packr.go")
53
54 b := New(context.Background(), root)
55 b.Compress = true
56 err := b.Run()
57 r.NoError(err)
58
59 r.True(fileExists(exPackr))
60 r.True(fileExists(fooPackr))
61
62 bb, err := ioutil.ReadFile(exPackr)
63 r.NoError(err)
64 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./assets", "app.css", "\"H4sIAAAAAAAA/0rKT`)))
65 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("./assets", "app.js", "\"H4sIAAAAAAAA/0rMSS`)))
66
67 bb, err = ioutil.ReadFile(fooPackr)
68 r.NoError(err)
69 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../assets", "app.css", "\"H4sIAAAAAAAA/0rKT`)))
70 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../assets", "app.js", "\"H4sIAAAAAAAA/0rMSS`)))
71 r.True(bytes.Contains(bb, []byte(`packr.PackJSONBytes("../templates", "index.html", "\"H4sIAAAAAAAA`)))
72 }
73
74 func fileExists(path string) bool {
75 _, err := os.Stat(path)
76 return err == nil
77 }
0 package builder
1
2 import (
3 "os"
4 "path/filepath"
5
6 "github.com/gobuffalo/packr/v2/jam/parser"
7 "github.com/gobuffalo/packr/v2/jam/store"
8 )
9
10 // Clean up an *-packr.go files
11 func Clean(root string) error {
12 defer func() {
13 packd := filepath.Join(root, "packrd")
14 os.RemoveAll(packd)
15 }()
16
17 p, err := parser.NewFromRoots([]string{root}, &parser.RootsOptions{
18 IgnoreImports: true,
19 })
20 if err != nil {
21 return err
22 }
23
24 boxes, err := p.Run()
25 if err != nil {
26 return err
27 }
28
29 d := store.NewDisk("", "")
30 for _, box := range boxes {
31 if err := d.Clean(box); err != nil {
32 return err
33 }
34 }
35 return nil
36 }
0 package builder
1
2 type file struct {
3 Name string
4 Contents string
5 }
6
7 func (f file) String() string {
8 return f.Name
9 }
0 package builder
1
2 type pkg struct {
3 Name string
4 Dir string
5 Boxes []box
6 }
0 package builder
1
2 var tmpl = `// Code generated by github.com/gobuffalo/packr. DO NOT EDIT.
3
4 package {{.Name}}
5
6 import "github.com/gobuffalo/packr"
7
8 // You can use the "packr clean" command to clean up this,
9 // and any other packr generated files.
10 func init() {
11 {{- range $box := .Boxes }}
12 {{- range .Files }}
13 packr.PackJSONBytes("{{$box.Name}}", "{{.Name}}", "{{.Contents}}")
14 {{- end }}
15 {{- end }}
16 }
17 `
0 package builder
1
2 import (
3 "errors"
4 "go/ast"
5 "go/parser"
6 "go/token"
7 "io/ioutil"
8 "sort"
9 "strings"
10 )
11
12 type visitor struct {
13 Path string
14 Package string
15 Boxes []string
16 Errors []error
17 }
18
19 func newVisitor(path string) *visitor {
20 return &visitor{
21 Path: path,
22 Boxes: []string{},
23 Errors: []error{},
24 }
25 }
26
27 func (v *visitor) Run() error {
28 b, err := ioutil.ReadFile(v.Path)
29 if err != nil {
30 return err
31 }
32
33 fset := token.NewFileSet()
34 file, err := parser.ParseFile(fset, v.Path, string(b), parser.ParseComments)
35 if err != nil {
36 return err
37 }
38
39 v.Package = file.Name.Name
40 ast.Walk(v, file)
41
42 m := map[string]string{}
43 for _, s := range v.Boxes {
44 m[s] = s
45 }
46 v.Boxes = []string{}
47 for k := range m {
48 v.Boxes = append(v.Boxes, k)
49 }
50
51 sort.Strings(v.Boxes)
52
53 if len(v.Errors) > 0 {
54 s := make([]string, len(v.Errors))
55 for i, e := range v.Errors {
56 s[i] = e.Error()
57 }
58 return errors.New(strings.Join(s, "\n"))
59 }
60 return nil
61 }
62
63 func (v *visitor) Visit(node ast.Node) ast.Visitor {
64 if node == nil {
65 return v
66 }
67 if err := v.eval(node); err != nil {
68 v.Errors = append(v.Errors, err)
69 }
70 return v
71 }
72
73 func (v *visitor) eval(node ast.Node) error {
74 switch t := node.(type) {
75 case *ast.CallExpr:
76 return v.evalExpr(t)
77 case *ast.Ident:
78 return v.evalIdent(t)
79 case *ast.GenDecl:
80 for _, n := range t.Specs {
81 if err := v.eval(n); err != nil {
82 return err
83 }
84 }
85 case *ast.FuncDecl:
86 if t.Body == nil {
87 return nil
88 }
89 for _, b := range t.Body.List {
90 if err := v.evalStmt(b); err != nil {
91 return err
92 }
93 }
94 return nil
95 case *ast.ValueSpec:
96 for _, e := range t.Values {
97 if err := v.evalExpr(e); err != nil {
98 return err
99 }
100 }
101 }
102 return nil
103 }
104
105 func (v *visitor) evalStmt(stmt ast.Stmt) error {
106 switch t := stmt.(type) {
107 case *ast.ExprStmt:
108 return v.evalExpr(t.X)
109 case *ast.AssignStmt:
110 for _, e := range t.Rhs {
111 if err := v.evalArgs(e); err != nil {
112 return err
113 }
114 }
115 }
116 return nil
117 }
118
119 func (v *visitor) evalExpr(expr ast.Expr) error {
120 switch t := expr.(type) {
121 case *ast.CallExpr:
122 if t.Fun == nil {
123 return nil
124 }
125 for _, a := range t.Args {
126 switch at := a.(type) {
127 case *ast.CallExpr:
128 if sel, ok := t.Fun.(*ast.SelectorExpr); ok {
129 return v.evalSelector(at, sel)
130 }
131
132 if err := v.evalArgs(at); err != nil {
133 return err
134 }
135 case *ast.CompositeLit:
136 for _, e := range at.Elts {
137 if err := v.evalExpr(e); err != nil {
138 return err
139 }
140 }
141 }
142 }
143 if ft, ok := t.Fun.(*ast.SelectorExpr); ok {
144 return v.evalSelector(t, ft)
145 }
146 case *ast.KeyValueExpr:
147 return v.evalExpr(t.Value)
148 }
149 return nil
150 }
151
152 func (v *visitor) evalArgs(expr ast.Expr) error {
153 switch at := expr.(type) {
154 case *ast.CompositeLit:
155 for _, e := range at.Elts {
156 if err := v.evalExpr(e); err != nil {
157 return err
158 }
159 }
160 // case *ast.BasicLit:
161 // fmt.Println("evalArgs", at.Value)
162 // v.addBox(at.Value)
163 case *ast.CallExpr:
164 if at.Fun == nil {
165 return nil
166 }
167 switch st := at.Fun.(type) {
168 case *ast.SelectorExpr:
169 if err := v.evalSelector(at, st); err != nil {
170 return err
171 }
172 case *ast.Ident:
173 return v.evalIdent(st)
174 }
175 for _, a := range at.Args {
176 if err := v.evalArgs(a); err != nil {
177 return err
178 }
179 }
180 }
181 return nil
182 }
183
184 func (v *visitor) evalSelector(expr *ast.CallExpr, sel *ast.SelectorExpr) error {
185 x, ok := sel.X.(*ast.Ident)
186 if !ok {
187 return nil
188 }
189 if x.Name == "packr" && sel.Sel.Name == "NewBox" {
190 for _, e := range expr.Args {
191 switch at := e.(type) {
192 case *ast.Ident:
193 switch at.Obj.Kind {
194 case ast.Var:
195 if as, ok := at.Obj.Decl.(*ast.AssignStmt); ok {
196 v.addVariable(as)
197 }
198 case ast.Con:
199 if vs, ok := at.Obj.Decl.(*ast.ValueSpec); ok {
200 v.addConstant(vs)
201 }
202 }
203 return v.evalIdent(at)
204 case *ast.BasicLit:
205 v.addBox(at.Value)
206 case *ast.CallExpr:
207 return v.evalExpr(at)
208 }
209 }
210 }
211
212 return nil
213 }
214
215 func (v *visitor) evalIdent(i *ast.Ident) error {
216 if i.Obj == nil {
217 return nil
218 }
219 if s, ok := i.Obj.Decl.(*ast.AssignStmt); ok {
220 return v.evalStmt(s)
221 }
222 return nil
223 }
224
225 func (v *visitor) addBox(b string) {
226 b = strings.Replace(b, "\"", "", -1)
227 v.Boxes = append(v.Boxes, b)
228 }
229
230 func (v *visitor) addVariable(as *ast.AssignStmt) error {
231 if len(as.Rhs) == 1 {
232 if bs, ok := as.Rhs[0].(*ast.BasicLit); ok {
233 v.addBox(bs.Value)
234 }
235 }
236 return nil
237 }
238
239 func (v *visitor) addConstant(vs *ast.ValueSpec) error {
240 if len(vs.Values) == 1 {
241 if bs, ok := vs.Values[0].(*ast.BasicLit); ok {
242 v.addBox(bs.Value)
243 }
244 }
245 return nil
246 }
0 package builder
1
2 import (
3 "testing"
4
5 "github.com/stretchr/testify/require"
6 )
7
8 func Test_Visitor(t *testing.T) {
9 r := require.New(t)
10 v := newVisitor("../example/example.go")
11 r.NoError(v.Run())
12
13 r.Equal("example", v.Package)
14 r.Len(v.Errors, 0)
15 r.Len(v.Boxes, 7)
16 r.Equal([]string{"./assets", "./bar", "./constant", "./foo", "./sf", "./templates", "./variable"}, v.Boxes)
17 }
0 package packr
1
2 import (
3 "github.com/gobuffalo/envy"
4 )
5
6 // GoPath returns the current GOPATH env var
7 // or if it's missing, the default.
8 var GoPath = envy.GoPath
9
10 // GoBin returns the current GO_BIN env var
11 // or if it's missing, a default of "go"
12 var GoBin = envy.GoBin
0 body {
1 background: red;
2 }
0 alert("hello!");
(New empty file)
(New empty file)
(New empty file)
0 package example
1
2 import (
3 "github.com/gobuffalo/packr"
4 )
5
6 var a = packr.NewBox("./foo")
7
8 const constString = "./constant"
9
10 type S struct{}
11
12 func (S) f(packr.Box) {}
13
14 func init() {
15
16 b := "./variable"
17 packr.NewBox(b)
18
19 packr.NewBox(constString)
20
21 // Cannot work from a function
22 packr.NewBox(strFromFunc())
23
24 // This variable should not be added
25 fromFunc := strFromFunc()
26 packr.NewBox(fromFunc)
27
28 foo("/templates", packr.NewBox("./templates"))
29 packr.NewBox("./assets")
30
31 packr.NewBox("./bar")
32
33 s := S{}
34 s.f(packr.NewBox("./sf"))
35 }
36
37 func strFromFunc() string {
38 return "./fromFunc"
39 }
40
41 func foo(s string, box packr.Box) {}
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>Foo</title>
6 </head>
7 <body>
8 body
9 </body>
10 </html>
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 "github.com/gobuffalo/packd"
3
4 type File = packd.File
0 this is my file
(New empty file)
(New empty file)
0 goodbye cruel world!
0 hello world!
0 <h1>Index!</h1>
0 module github.com/gobuffalo/packr
1
2 go 1.12
3
4 require (
5 github.com/gobuffalo/envy v1.7.0
6 github.com/gobuffalo/packd v0.3.0
7 github.com/gobuffalo/packr/v2 v2.5.1
8 github.com/spf13/cobra v0.0.5
9 github.com/stretchr/testify v1.3.0
10 golang.org/x/sync v0.0.0-20190423024810-112230192c58
11 )
0 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
1 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
2 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
3 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
4 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
5 github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
6 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
8 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
10 github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
11 github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
12 github.com/gobuffalo/logger v1.0.0 h1:xw9Ko9EcC5iAFprrjJ6oZco9UpzS5MQ4jAwghsLHdy4=
13 github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
14 github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
15 github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
16 github.com/gobuffalo/packr/v2 v2.5.1 h1:TFOeY2VoGamPjQLiNDT3mn//ytzk236VMO2j7iHxJR4=
17 github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
18 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
19 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
20 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
21 github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
22 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
23 github.com/karrick/godirwalk v1.10.12 h1:BqUm+LuJcXjGv1d2mj3gBiQyrQ57a0rYoAmhvJQ7RDU=
24 github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
25 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
26 github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
27 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
28 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
29 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
30 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
31 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
32 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
33 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
34 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
35 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
36 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
37 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
38 github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
39 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
40 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
41 github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
42 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
43 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
44 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
45 github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
46 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
47 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
48 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
49 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
50 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
51 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
52 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
53 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
54 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
55 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
56 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
57 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
58 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
59 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
60 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
61 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
62 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
63 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
64 golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
65 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
66 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
67 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
68 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
69 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
70 golang.org/x/sys v0.0.0-20190515120540-06a5c4944438 h1:khxRGsvPk4n2y8I/mLLjp7e5dMTJmH75wvqS6nMwUtY=
71 golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
72 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
73 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c h1:KfpJVdWhuRqNk4XVXzjXf2KAV4TBEP77SYdFGjeGuIE=
74 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
75 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
76 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
77 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
78 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
0 package packr
1
2 import (
3 "net/http"
4 "net/http/httptest"
5 "strings"
6 "testing"
7
8 "github.com/stretchr/testify/require"
9 )
10
11 func Test_HTTPBox(t *testing.T) {
12 r := require.New(t)
13
14 mux := http.NewServeMux()
15 mux.Handle("/", http.FileServer(testBox))
16
17 req, err := http.NewRequest("GET", "/hello.txt", nil)
18 r.NoError(err)
19
20 res := httptest.NewRecorder()
21
22 mux.ServeHTTP(res, req)
23
24 r.Equal(200, res.Code)
25 r.Equal("hello world!", strings.TrimSpace(res.Body.String()))
26 }
27
28 // func Test_HTTPBox_CaseInsensitive(t *testing.T) {
29 //
30 // mux := http.NewServeMux()
31 // testBox.AddString("myfile.txt", "this is my file")
32 // mux.Handle("/", http.FileServer(testBox))
33 //
34 // for _, path := range []string{"/MyFile.txt", "/myfile.txt", "/Myfile.txt"} {
35 // t.Run(path, func(st *testing.T) {
36 // r := require.New(st)
37 //
38 // req, err := http.NewRequest("GET", path, nil)
39 // r.NoError(err)
40 //
41 // res := httptest.NewRecorder()
42 //
43 // mux.ServeHTTP(res, req)
44 //
45 // r.Equal(200, res.Code)
46 // r.Equal("this is my file", strings.TrimSpace(res.Body.String()))
47 // })
48 // }
49 // }
50
51 func Test_HTTPBox_NotFound(t *testing.T) {
52 r := require.New(t)
53
54 mux := http.NewServeMux()
55 mux.Handle("/", http.FileServer(testBox))
56
57 req, err := http.NewRequest("GET", "/notInBox.txt", nil)
58 r.NoError(err)
59
60 res := httptest.NewRecorder()
61
62 mux.ServeHTTP(res, req)
63
64 r.Equal(404, res.Code)
65 }
66
67 func Test_HTTPBox_Handles_IndexHTML(t *testing.T) {
68 r := require.New(t)
69
70 mux := http.NewServeMux()
71 mux.Handle("/", http.FileServer(testBox))
72
73 req, err := http.NewRequest("GET", "/", nil)
74 r.NoError(err)
75
76 res := httptest.NewRecorder()
77
78 mux.ServeHTTP(res, req)
79
80 r.Equal("<h1>Index!</h1>", strings.TrimSpace(res.Body.String()))
81 }
0 package cmd
1
2 import (
3 "context"
4 "os"
5 "os/exec"
6
7 "github.com/gobuffalo/packr"
8 "github.com/gobuffalo/packr/builder"
9 "github.com/spf13/cobra"
10 )
11
12 // buildCmd represents the build command
13 var buildCmd = &cobra.Command{
14 Use: "build",
15 Short: "Wraps the go build command with packr",
16 DisableFlagParsing: true,
17 RunE: func(cmd *cobra.Command, args []string) error {
18 defer builder.Clean(input)
19 b := builder.New(context.Background(), input)
20 err := b.Run()
21 if err != nil {
22 return err
23 }
24
25 cargs := []string{"build"}
26 cargs = append(cargs, args...)
27 cp := exec.Command(packr.GoBin(), cargs...)
28 cp.Stderr = os.Stderr
29 cp.Stdin = os.Stdin
30 cp.Stdout = os.Stdout
31
32 return cp.Run()
33 },
34 }
35
36 func init() {
37 rootCmd.AddCommand(buildCmd)
38 }
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 "os/exec"
6 "path/filepath"
7 "strings"
8
9 "github.com/gobuffalo/packr"
10 "github.com/gobuffalo/packr/builder"
11 "github.com/spf13/cobra"
12 )
13
14 // installCmd represents the install command
15 var installCmd = &cobra.Command{
16 Use: "install",
17 Short: "Wraps the go install command with packr",
18 DisableFlagParsing: true,
19 RunE: func(cmd *cobra.Command, args []string) error {
20 if len(args) > 0 {
21 input = args[len(args)-1]
22 if !strings.HasPrefix(input, ".") {
23 input = filepath.Join(packr.GoPath(), "src", input)
24 if _, err := os.Stat(input); err != nil {
25 return err
26 }
27 }
28 }
29 defer builder.Clean(input)
30 b := builder.New(context.Background(), input)
31 err := b.Run()
32 if err != nil {
33 return err
34 }
35
36 cargs := []string{"install"}
37 cargs = append(cargs, args...)
38 cp := exec.Command(packr.GoBin(), cargs...)
39 cp.Stderr = os.Stderr
40 cp.Stdin = os.Stdin
41 cp.Stdout = os.Stdout
42
43 return cp.Run()
44 },
45 }
46
47 func init() {
48 rootCmd.AddCommand(installCmd)
49 }
0 package cmd
1
2 import (
3 "context"
4 "fmt"
5 "os"
6
7 "github.com/gobuffalo/packr/builder"
8 "github.com/spf13/cobra"
9 )
10
11 var input string
12 var compress bool
13 var verbose bool
14
15 var rootCmd = &cobra.Command{
16 Use: "packr",
17 Short: "compiles static files into Go files",
18 PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
19 if !verbose {
20 for _, a := range args {
21 if a == "-v" {
22 verbose = true
23 break
24 }
25 }
26 }
27
28 if verbose {
29 builder.DebugLog = func(s string, a ...interface{}) {
30 os.Stdout.WriteString(fmt.Sprintf(s, a...))
31 }
32 }
33 return nil
34 },
35 RunE: func(cmd *cobra.Command, args []string) error {
36 b := builder.New(context.Background(), input)
37 b.Compress = compress
38 return b.Run()
39 },
40 }
41
42 func init() {
43 pwd, _ := os.Getwd()
44 rootCmd.Flags().StringVarP(&input, "input", "i", pwd, "path to scan for packr Boxes")
45 rootCmd.Flags().BoolVarP(&compress, "compress", "z", false, "compress box contents")
46 rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "print verbose logging information")
47 }
48
49 // Execute the commands
50 func Execute() {
51 if err := rootCmd.Execute(); err != nil {
52 os.Exit(-1)
53 }
54 }
0 package cmd
1
2 import (
3 "fmt"
4
5 "github.com/gobuffalo/packr"
6 "github.com/spf13/cobra"
7 )
8
9 var versionCmd = &cobra.Command{
10 Use: "version",
11 Short: "prints packr version",
12 Run: func(cmd *cobra.Command, args []string) {
13 fmt.Print(packr.Version)
14 },
15 }
16
17 func init() {
18 rootCmd.AddCommand(versionCmd)
19 }
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 "bytes"
4 "compress/gzip"
5 "encoding/json"
6 "runtime"
7 "strings"
8 "sync"
9 )
10
11 var gil = &sync.Mutex{}
12 var data = map[string]map[string][]byte{}
13
14 // PackBytes packs bytes for a file into a box.
15 func PackBytes(box string, name string, bb []byte) {
16 gil.Lock()
17 defer gil.Unlock()
18 if _, ok := data[box]; !ok {
19 data[box] = map[string][]byte{}
20 }
21 data[box][name] = bb
22 }
23
24 // PackBytesGzip packets the gzipped compressed bytes into a box.
25 func PackBytesGzip(box string, name string, bb []byte) error {
26 var buf bytes.Buffer
27 w := gzip.NewWriter(&buf)
28 _, err := w.Write(bb)
29 if err != nil {
30 return err
31 }
32 err = w.Close()
33 if err != nil {
34 return err
35 }
36 PackBytes(box, name, buf.Bytes())
37 return nil
38 }
39
40 // PackJSONBytes packs JSON encoded bytes for a file into a box.
41 func PackJSONBytes(box string, name string, jbb string) error {
42 var bb []byte
43 err := json.Unmarshal([]byte(jbb), &bb)
44 if err != nil {
45 return err
46 }
47 PackBytes(box, name, bb)
48 return nil
49 }
50
51 // UnpackBytes unpacks bytes for specific box.
52 func UnpackBytes(box string) {
53 gil.Lock()
54 defer gil.Unlock()
55 delete(data, box)
56 }
57
58 func osPaths(paths ...string) []string {
59 if runtime.GOOS == "windows" {
60 for i, path := range paths {
61 paths[i] = strings.Replace(path, "/", "\\", -1)
62 }
63 }
64
65 return paths
66 }
67
68 func osPath(path string) string {
69 if runtime.GOOS == "windows" {
70 return strings.Replace(path, "/", "\\", -1)
71 }
72 return path
73 }
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 var virtualBox = NewBox("./virtual")
11
12 func init() {
13 PackBytes(virtualBox.Path, "a", []byte("a"))
14 PackBytes(virtualBox.Path, "b", []byte("b"))
15 PackBytes(virtualBox.Path, "c", []byte("c"))
16 PackBytes(virtualBox.Path, "d/a", []byte("d/a"))
17 }
18
19 func Test_PackBytes(t *testing.T) {
20 r := require.New(t)
21 PackBytes(testBox.Path, "foo", []byte("bar"))
22 s, err := testBox.FindString("foo")
23 r.NoError(err)
24 r.Equal("bar", s)
25 }
26
27 func Test_PackJSONBytes(t *testing.T) {
28 r := require.New(t)
29 b, err := json.Marshal([]byte("json bytes"))
30 r.NoError(err)
31 err = PackJSONBytes(testBox.Path, "the bytes", string(b))
32 r.NoError(err)
33 s, err := testBox.Find("the bytes")
34 r.NoError(err)
35 r.Equal([]byte("json bytes"), s)
36 }
37
38 func Test_PackBytesGzip(t *testing.T) {
39 r := require.New(t)
40 err := PackBytesGzip(testBox.Path, "gzip", []byte("gzip foobar"))
41 r.NoError(err)
42 s, err := testBox.FindString("gzip")
43 r.NoError(err)
44 r.Equal("gzip foobar", s)
45 }
0 {
1 "Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"]
2 }
0 # Code generated by github.com/gobuffalo/release. DO NOT EDIT.
1 # Edit .goreleaser.yml.plush instead
2
3 builds:
4 -
5 goos:
6 - darwin
7 - linux
8 - windows
9 goarch:
10 - ppc64le
11 - 386
12 - amd64
13 env:
14 - CGO_ENABLED=0
15 ignore:
16 - goos: darwin
17 goarch: ppc64le
18 - goos: windows
19 goarch: ppc64le
20 main: ./packr2/main.go
21 binary: packr2
22
23 checksum:
24 name_template: 'checksums.txt'
25
26 snapshot:
27 name_template: "{{ .Tag }}-next"
28
29 changelog:
30 sort: asc
31 filters:
32 exclude:
33 - '^docs:'
34 - '^test:'
35
36 brew:
37 github:
38 owner: gobuffalo
39 name: homebrew-tap
40
0 builds:
1 -
2 goos:
3 - darwin
4 - linux
5 - windows
6 goarch:
7 - ppc64le
8 - 386
9 - amd64
10 env:
11 - CGO_ENABLED=0
12 ignore:
13 - goos: darwin
14 goarch: ppc64le
15 - goos: windows
16 goarch: ppc64le
17 main: ./packr2/main.go
18 binary: packr2
19
20 checksum:
21 name_template: 'checksums.txt'
22
23 snapshot:
24 name_template: "{{ .Tag }}-next"
25
26 changelog:
27 sort: asc
28 filters:
29 exclude:
30 - '^docs:'
31 - '^test:'
32 <%= if (brew) { %>
33 brew:
34 github:
35 owner: gobuffalo
36 name: homebrew-tap
37 <% } %>
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 TAGS ?= "sqlite"
1 GO_BIN ?= go
2
3 install: deps
4 echo "installing packr v2"
5 packr2
6 $(GO_BIN) install -v ./packr2
7
8 tidy:
9 ifeq ($(GO111MODULE),on)
10 $(GO_BIN) mod tidy
11 else
12 echo skipping go mod tidy
13 endif
14
15 deps:
16 $(GO_BIN) get github.com/gobuffalo/release
17 $(GO_BIN) get -tags ${TAGS} -t ./...
18 $(GO_BIN) install -v ./packr2
19 make tidy
20
21 build: deps
22 packr2
23 $(GO_BIN) build -v ./packr2
24 make tidy
25
26 test:
27 packr2
28 $(GO_BIN) test -tags ${TAGS} ./...
29 make tidy
30
31 lint:
32 gometalinter --vendor ./... --deadline=1m --skip=internal
33
34 update:
35 $(GO_BIN) get -u -tags ${TAGS} ./...
36 make tidy
37 make install
38 make test
39 make tidy
40
41 release-test:
42 $(GO_BIN) test -tags ${TAGS} -race ./...
43
44 release:
45 release -y -f version.go
46 make tidy
0 # Packr (v2)
1
2 [![GoDoc](https://godoc.org/github.com/gobuffalo/packr/v2?status.svg)](https://godoc.org/github.com/gobuffalo/packr/v2)
3
4 Packr is a simple solution for bundling static assets inside of Go binaries. Most importantly it does it in a way that is friendly to developers while they are developing.
5
6 ## Intro Video
7
8 To get an idea of the what and why of Packr, please enjoy this short video: [https://vimeo.com/219863271](https://vimeo.com/219863271).
9
10 ## Library Installation
11
12 ```text
13 $ go get -u github.com/gobuffalo/packr/v2/...
14 ```
15
16 ## Binary Installation
17
18 ```text
19 $ go get -u github.com/gobuffalo/packr/v2/packr2
20 ```
21
22 ## New File Format FAQs
23
24 In version `v2.0.0` the file format changed and is not backward compatible with the `packr-v1.x` library.
25
26 #### Can `packr-v1.x` read the new format?
27
28 No, it can not. Because of the way the new file format works porting it to `packr-v1.x` would be difficult. PRs are welcome though. :)
29
30 #### Can `packr-v2.x` read `packr-v1.x` files?
31
32 Yes it can, but that ability will eventually be phased out. Because of that we recommend moving to the new format.
33
34 #### Can `packr-v2.x` generate `packr-v1.x` files?
35
36 Yes it can, but that ability will eventually be phased out. Because of that we recommend moving to the new format.
37
38 The `--legacy` command is available on all commands that generate `-packr.go` files.
39
40 ```bash
41 $ packr2 --legacy
42 ```
43
44 ## Usage
45
46 ### In Code
47
48 The first step in using Packr is to create a new box. A box represents a folder on disk. Once you have a box you can get `string` or `[]byte` representations of the file.
49
50 ```go
51 // set up a new box by giving it a name and an optional (relative) path to a folder on disk:
52 box := packr.New("My Box", "./templates")
53
54 // Get the string representation of a file, or an error if it doesn't exist:
55 html, err := box.FindString("index.html")
56
57 // Get the []byte representation of a file, or an error if it doesn't exist:
58 html, err := box.Find("index.html")
59 ```
60
61 ### What is a Box?
62
63 A box represents a folder, and any sub-folders, on disk that you want to have access to in your binary. When compiling a binary using the `packr2` CLI the contents of the folder will be converted into Go files that can be compiled inside of a "standard" go binary. Inside of the compiled binary the files will be read from memory. When working locally the files will be read directly off of disk. This is a seamless switch that doesn't require any special attention on your part.
64
65 #### Example
66
67 Assume the follow directory structure:
68
69 ```
70 ├── main.go
71 └── templates
72 ├── admin
73 │   └── index.html
74 └── index.html
75 ```
76
77 The following program will read the `./templates/admin/index.html` file and print it out.
78
79 ```go
80 package main
81
82 import (
83 "fmt"
84
85 "github.com/gobuffalo/packr/v2"
86 )
87
88 func main() {
89 box := packr.New("myBox", "./templates")
90
91 s, err := box.FindString("admin/index.html")
92 if err != nil {
93 log.Fatal(err)
94 }
95 fmt.Println(s)
96 }
97 ```
98
99 ### Development Made Easy
100
101 In order to get static files into a Go binary, those files must first be converted to Go code. To do that, Packr, ships with a few tools to help build binaries. See below.
102
103 During development, however, it is painful to have to keep running a tool to compile those files.
104
105 Packr uses the following resolution rules when looking for a file:
106
107 1. Look for the file in-memory (inside a Go binary)
108 1. Look for the file on disk (during development)
109
110 Because Packr knows how to fall through to the file system, developers don't need to worry about constantly compiling their static files into a binary. They can work unimpeded.
111
112 Packr takes file resolution a step further. When declaring a new box you use a relative path, `./templates`. When Packr receives this call it calculates out the absolute path to that directory. By doing this it means you can be guaranteed that Packr can find your files correctly, even if you're not running in the directory that the box was created in. This helps with the problem of testing, where Go changes the `pwd` for each package, making relative paths difficult to work with. This is not a problem when using Packr.
113
114 ---
115
116 ## Usage with HTTP
117
118 A box implements the [`http.FileSystem`](https://golang.org/pkg/net/http/#FileSystem) interface, meaning it can be used to serve static files.
119
120 ```go
121 package main
122
123 import (
124 "net/http"
125
126 "github.com/gobuffalo/packr/v2"
127 )
128
129 func main() {
130 box := packr.New("someBoxName", "./templates")
131
132 http.Handle("/", http.FileServer(box))
133 http.ListenAndServe(":3000", nil)
134 }
135 ```
136
137 ---
138
139 ## Building a Binary
140
141 Before you build your Go binary, run the `packr2` command first. It will look for all the boxes in your code and then generate `.go` files that pack the static files into bytes that can be bundled into the Go binary.
142
143 ```
144 $ packr2
145 ```
146
147 Then run your `go build command` like normal.
148
149 *NOTE*: It is not recommended to check-in these generated `-packr.go` files. They can be large, and can easily become out of date if not careful. It is recommended that you always run `packr2 clean` after running the `packr2` tool.
150
151 #### Cleaning Up
152
153 When you're done it is recommended that you run the `packr2 clean` command. This will remove all of the generated files that Packr created for you.
154
155 ```
156 $ packr2 clean
157 ```
158
159 Why do you want to do this? Packr first looks to the information stored in these generated files, if the information isn't there it looks to disk. This makes it easy to work with in development.
160
161 ---
162
163 ## Debugging
164
165 The `packr2` command passes all arguments down to the underlying `go` command, this includes the `-v` flag to print out `go build` information. Packr looks for the `-v` flag, and will turn on its own verbose logging. This is very useful for trying to understand what the `packr` command is doing when it is run.
166
167 ---
168
169 ## FAQ
170
171 ### Compilation Errors with Go Templates
172
173 Q: I have a program with Go template files, those files are named `foo.go` and look like the following:
174
175 ```
176 // Copyright {{.Year}} {{.Author}}. All rights reserved.
177 // Use of this source code is governed by a BSD-style
178 // license that can be found in the LICENSE file.
179
180 package {{.Project}}
181 ```
182
183 When I run `packr2` I get errors like:
184
185 ```
186 expected 'IDENT', found '{'
187 ```
188
189 A: Packr works by searching your `.go` files for [`github.com/gobuffalo/packr/v2#New`](https://godoc.org/github.com/gobuffalo/packr/v2#New) or [`github.com/gobuffalo/packr/v2#NewBox`](https://godoc.org/github.com/gobuffalo/packr/v2#NewBox) calls. Because those files aren't "proper" Go files, Packr can't parse them to find the box declarations. To fix this you need to tell Packr to ignore those files when searching for boxes. A couple solutions to this problem are:
190
191 * Name the files something else. The `.tmpl` extension is the idiomatic way of naming these types of files.
192 * Rename the folder containing these files to start with an `_`, for example `_templates`. Packr, like Go, will ignore folders starting with the `_` character when searching for boxes.
193
194 ### Dynamic Box Paths
195
196 Q: I need to set the path of a box using a variable, but `packr.New("foo", myVar)` doesn't work correctly.
197
198 A: Packr attempts to "automagically" set it's resolution directory when using [`github.com/gobuffalo/packr/v2#New`](https://godoc.org/github.com/gobuffalo/packr/v2#New), however, for dynamic paths you need to set it manually:
199
200 ```go
201 box := packr.New("foo", "|")
202 box.ResolutionDir = myVar
203 ```
204
205 ### I don't want to pack files, but still use the Packr interface.
206
207 Q: I want to write code that using the Packr tools, but doesn't actually pack the files into my binary. How can I do that?
208
209 A: Using [`github.com/gobuffalo/packr/v2#Folder`](https://godoc.org/github.com/gobuffalo/packr/v2#Folder) gives you back a `*packr.Box` that can be used as normal, but is excluded by the Packr tool when compiling.
210
211 ### Packr Finds No Boxes
212
213 Q: I run `packr2 -v` but it doesn't find my boxes:
214
215 ```
216 DEBU[2019-03-18T18:48:52+01:00] *parser.Parser#NewFromRoots found prospects=0
217 DEBU[2019-03-18T18:48:52+01:00] found 0 boxes
218 ```
219
220 A: Packr works by parsing `.go` files to find [`github.com/gobuffalo/packr/v2#Box`](https://godoc.org/github.com/gobuffalo/packr/v2#Box) and [`github.com/gobuffalo/packr/v2#NewBox`](https://godoc.org/github.com/gobuffalo/packr/v2#NewBox) declarations. If there aren't any `.go` in the folder that `packr2` is run in it can not find those declarations. To fix this problem run the `packr2` command in the directory containing your `.go` files.
221
222 ### Box Interfaces
223
224 Q: I want to be able to easily test my applications by passing in mock boxes. How do I do that?
225
226 A: Packr boxes and files conform to the interfaces found at [`github.com/gobuffalo/packd`](https://godoc.org/github.com/gobuffalo/packd). Change your application to use those interfaces instead of the concrete Packr types.
227
228 ```go
229 // using concrete type
230 func myFunc(box *packr.Box) {}
231
232 // using interfaces
233 func myFunc(box packd.Box) {}
234 ```
0 # github.com/gobuffalo/packr/v2 Stands on the Shoulders of Giants
1
2 github.com/gobuffalo/packr/v2 does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants, this project would not be possible. Please make sure to check them out and thank them for all of their hard work.
3
4 Thank you to the following **GIANTS**:
5
6
7 * [github.com/gobuffalo/envy](https://godoc.org/github.com/gobuffalo/envy)
8
9 * [github.com/gobuffalo/logger](https://godoc.org/github.com/gobuffalo/logger)
10
11 * [github.com/gobuffalo/packd](https://godoc.org/github.com/gobuffalo/packd)
12
13 * [github.com/karrick/godirwalk](https://godoc.org/github.com/karrick/godirwalk)
14
15 * [github.com/rogpeppe/go-internal](https://godoc.org/github.com/rogpeppe/go-internal)
16
17 * [github.com/sirupsen/logrus](https://godoc.org/github.com/sirupsen/logrus)
18
19 * [github.com/spf13/cobra](https://godoc.org/github.com/spf13/cobra)
20
21 * [github.com/stretchr/testify](https://godoc.org/github.com/stretchr/testify)
22
23 * [golang.org/x/sync](https://godoc.org/golang.org/x/sync)
24
25 * [golang.org/x/tools](https://godoc.org/golang.org/x/tools)
0 package import_pkg
1
2 import (
3 "github.com/gobuffalo/packr/v2"
4 )
5
6 var BoxTestNew = packr.New("pkg_test", "./pkg_test")
7 var BoxTestNewBox = packr.NewBox("./pkg_test")
0 package import_pkg
1
2 import (
3 "testing"
4
5 "github.com/gobuffalo/packr/v2"
6 "github.com/stretchr/testify/require"
7 )
8
9 func Test_NewBox(t *testing.T) {
10 r := require.New(t)
11
12 box := packr.NewBox("./pkg_test")
13 r.Len(box.List(), 2)
14 }
15
16 func Test_New(t *testing.T) {
17 r := require.New(t)
18
19 box := packr.New("pkg_test", "./pkg_test")
20 r.Len(box.List(), 2)
21 }
0 package packr
1
2 import (
3 "bytes"
4 "fmt"
5 "io"
6 "io/ioutil"
7 "net/http"
8 "os"
9 "path"
10 "path/filepath"
11 "sort"
12 "strings"
13
14 "github.com/gobuffalo/packd"
15 "github.com/gobuffalo/packr/v2/file"
16 "github.com/gobuffalo/packr/v2/file/resolver"
17 "github.com/gobuffalo/packr/v2/plog"
18 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/oncer"
19 )
20
21 var _ packd.Box = &Box{}
22 var _ packd.HTTPBox = &Box{}
23 var _ packd.Addable = &Box{}
24 var _ packd.Walkable = &Box{}
25 var _ packd.Finder = &Box{}
26
27 // Box represent a folder on a disk you want to
28 // have access to in the built Go binary.
29 type Box struct {
30 Path string `json:"path"`
31 Name string `json:"name"`
32 ResolutionDir string `json:"resolution_dir"`
33 DefaultResolver resolver.Resolver `json:"default_resolver"`
34 resolvers resolversMap
35 dirs dirsMap
36 }
37
38 // NewBox returns a Box that can be used to
39 // retrieve files from either disk or the embedded
40 // binary.
41 // Deprecated: Use New instead.
42 func NewBox(path string) *Box {
43 oncer.Deprecate(0, "packr.NewBox", "Use packr.New instead.")
44 return New(path, path)
45 }
46
47 // New returns a new Box with the name of the box
48 // and the path of the box.
49 func New(name string, path string) *Box {
50 plog.Debug("packr", "New", "name", name, "path", path)
51 b, _ := findBox(name)
52 if b != nil {
53 return b
54 }
55
56 b = construct(name, path)
57 plog.Debug(b, "New", "Box", b, "ResolutionDir", b.ResolutionDir)
58 b, err := placeBox(b)
59 if err != nil {
60 panic(err)
61 }
62
63 return b
64 }
65
66 // Folder returns a Box that will NOT be packed.
67 // This is useful for writing tests or tools that
68 // need to work with a folder at runtime.
69 func Folder(path string) *Box {
70 return New(path, path)
71 }
72
73 // SetResolver allows for the use of a custom resolver for
74 // the specified file
75 func (b *Box) SetResolver(file string, res resolver.Resolver) {
76 d := filepath.Dir(file)
77 b.dirs.Store(d, true)
78 plog.Debug(b, "SetResolver", "file", file, "resolver", fmt.Sprintf("%T", res))
79 b.resolvers.Store(resolver.Key(file), res)
80 }
81
82 // AddString converts t to a byteslice and delegates to AddBytes to add to b.data
83 func (b *Box) AddString(path string, t string) error {
84 return b.AddBytes(path, []byte(t))
85 }
86
87 // AddBytes sets t in b.data by the given path
88 func (b *Box) AddBytes(path string, t []byte) error {
89 m := map[string]file.File{}
90 f, err := file.NewFile(path, t)
91 if err != nil {
92 return err
93 }
94 m[resolver.Key(path)] = f
95 res := resolver.NewInMemory(m)
96 b.SetResolver(path, res)
97 return nil
98 }
99
100 // FindString returns either the string of the requested
101 // file or an error if it can not be found.
102 func (b *Box) FindString(name string) (string, error) {
103 bb, err := b.Find(name)
104 return string(bb), err
105 }
106
107 // Find returns either the byte slice of the requested
108 // file or an error if it can not be found.
109 func (b *Box) Find(name string) ([]byte, error) {
110 f, err := b.Resolve(name)
111 if err != nil {
112 return []byte(""), err
113 }
114 bb := &bytes.Buffer{}
115 io.Copy(bb, f)
116 return bb.Bytes(), nil
117 }
118
119 // Has returns true if the resource exists in the box
120 func (b *Box) Has(name string) bool {
121 _, err := b.Find(name)
122 return err == nil
123 }
124
125 // HasDir returns true if the directory exists in the box
126 func (b *Box) HasDir(name string) bool {
127 oncer.Do("packr2/box/HasDir"+b.Name, func() {
128 for _, f := range b.List() {
129 for d := filepath.Dir(f); d != "."; d = filepath.Dir(d) {
130 b.dirs.Store(d, true)
131 }
132 }
133 })
134 if name == "/" {
135 return b.Has("index.html")
136 }
137 _, ok := b.dirs.Load(name)
138 return ok
139 }
140
141 // Open returns a File using the http.File interface
142 func (b *Box) Open(name string) (http.File, error) {
143 plog.Debug(b, "Open", "name", name)
144 f, err := b.Resolve(name)
145 if err != nil {
146 if len(filepath.Ext(name)) == 0 {
147 return b.openWoExt(name)
148 }
149 return f, err
150 }
151 f, err = file.NewFileR(name, f)
152 plog.Debug(b, "Open", "name", f.Name(), "file", f.Name())
153 return f, err
154 }
155
156 func (b *Box) openWoExt(name string) (http.File, error) {
157 if !b.HasDir(name) {
158 id := path.Join(name, "index.html")
159 if b.Has(id) {
160 return b.Open(id)
161 }
162 return nil, os.ErrNotExist
163 }
164 d, err := file.NewDir(name)
165 plog.Debug(b, "Open", "name", name, "dir", d)
166 return d, err
167 }
168
169 // List shows "What's in the box?"
170 func (b *Box) List() []string {
171 var keys []string
172
173 b.Walk(func(path string, info File) error {
174 if info == nil {
175 return nil
176 }
177 finfo, _ := info.FileInfo()
178 if !finfo.IsDir() {
179 keys = append(keys, path)
180 }
181 return nil
182 })
183 sort.Strings(keys)
184 return keys
185 }
186
187 // Resolve will attempt to find the file in the box,
188 // returning an error if the find can not be found.
189 func (b *Box) Resolve(key string) (file.File, error) {
190 key = strings.TrimPrefix(key, "/")
191
192 var r resolver.Resolver
193
194 b.resolvers.Range(func(k string, vr resolver.Resolver) bool {
195 lk := strings.ToLower(resolver.Key(k))
196 lkey := strings.ToLower(resolver.Key(key))
197 if lk == lkey {
198 r = vr
199 return false
200 }
201 return true
202 })
203
204 if r == nil {
205 r = b.DefaultResolver
206 if r == nil {
207 r = resolver.DefaultResolver
208 if r == nil {
209 return nil, fmt.Errorf("resolver.DefaultResolver is nil")
210 }
211 }
212 }
213 plog.Debug(r, "Resolve", "box", b.Name, "key", key)
214
215 f, err := r.Resolve(b.Name, key)
216 if err != nil {
217 z := filepath.Join(resolver.OsPath(b.ResolutionDir), filepath.FromSlash(path.Clean("/"+resolver.OsPath(key))))
218 f, err = r.Resolve(b.Name, z)
219 if err != nil {
220 plog.Debug(r, "Resolve", "box", b.Name, "key", z, "err", err)
221 return f, err
222 }
223 b, err := ioutil.ReadAll(f)
224 if err != nil {
225 return f, err
226 }
227 f, err = file.NewFile(key, b)
228 if err != nil {
229 return f, err
230 }
231 }
232 plog.Debug(r, "Resolve", "box", b.Name, "key", key, "file", f.Name())
233 return f, nil
234 }
0 package packr_test
1
2 import (
3 "testing"
4
5 "github.com/gobuffalo/packr/v2/_fixtures/import_pkg"
6 "github.com/stretchr/testify/require"
7 )
8
9 func Test_ImportWithBox(t *testing.T) {
10 r := require.New(t)
11
12 r.Len(import_pkg.BoxTestNew.List(), 2)
13
14 r.Len(import_pkg.BoxTestNewBox.List(), 2)
15 }
0 //go:generate mapgen -name "box" -zero "nil" -go-type "*Box" -pkg "" -a "New(`test-a`, ``)" -b "New(`test-b`, ``)" -c "New(`test-c`, ``)" -bb "New(`test-bb`, ``)" -destination "packr"
1 // Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
2
3 package packr
4
5 import (
6 "sort"
7 "sync"
8 )
9
10 // boxMap wraps sync.Map and uses the following types:
11 // key: string
12 // value: *Box
13 type boxMap struct {
14 data sync.Map
15 }
16
17 // Delete the key from the map
18 func (m *boxMap) Delete(key string) {
19 m.data.Delete(key)
20 }
21
22 // Load the key from the map.
23 // Returns *Box or bool.
24 // A false return indicates either the key was not found
25 // or the value is not of type *Box
26 func (m *boxMap) Load(key string) (*Box, bool) {
27 i, ok := m.data.Load(key)
28 if !ok {
29 return nil, false
30 }
31 s, ok := i.(*Box)
32 return s, ok
33 }
34
35 // LoadOrStore will return an existing key or
36 // store the value if not already in the map
37 func (m *boxMap) LoadOrStore(key string, value *Box) (*Box, bool) {
38 i, _ := m.data.LoadOrStore(key, value)
39 s, ok := i.(*Box)
40 return s, ok
41 }
42
43 // Range over the *Box values in the map
44 func (m *boxMap) Range(f func(key string, value *Box) bool) {
45 m.data.Range(func(k, v interface{}) bool {
46 key, ok := k.(string)
47 if !ok {
48 return false
49 }
50 value, ok := v.(*Box)
51 if !ok {
52 return false
53 }
54 return f(key, value)
55 })
56 }
57
58 // Store a *Box in the map
59 func (m *boxMap) Store(key string, value *Box) {
60 m.data.Store(key, value)
61 }
62
63 // Keys returns a list of keys in the map
64 func (m *boxMap) Keys() []string {
65 var keys []string
66 m.Range(func(key string, value *Box) bool {
67 keys = append(keys, key)
68 return true
69 })
70 sort.Strings(keys)
71 return keys
72 }
0 // Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
1
2 package packr
3
4 import (
5 "sort"
6 "testing"
7
8 "github.com/stretchr/testify/require"
9 )
10
11 func Test_boxMap(t *testing.T) {
12 r := require.New(t)
13
14 sm := &boxMap{}
15
16 sm.Store("a", New(`test-a`, ``))
17
18 s, ok := sm.Load("a")
19 r.True(ok)
20 r.Equal(New(`test-a`, ``), s)
21
22 s, ok = sm.LoadOrStore("b", New(`test-b`, ``))
23 r.True(ok)
24 r.Equal(New(`test-b`, ``), s)
25
26 s, ok = sm.LoadOrStore("b", New(`test-bb`, ``))
27 r.True(ok)
28 r.Equal(New(`test-b`, ``), s)
29
30 var keys []string
31
32 sm.Range(func(key string, value *Box) bool {
33 keys = append(keys, key)
34 return true
35 })
36
37 sort.Strings(keys)
38
39 r.Equal(sm.Keys(), keys)
40
41 sm.Delete("b")
42 r.Equal([]string{"a", "b"}, keys)
43
44 sm.Delete("b")
45 _, ok = sm.Load("b")
46 r.False(ok)
47
48 func(m *boxMap) {
49 m.Store("c", New(`test-c`, ``))
50 }(sm)
51 s, ok = sm.Load("c")
52 r.True(ok)
53 r.Equal(New(`test-c`, ``), s)
54 }
0 package packr
1
2 import (
3 "bytes"
4 "path/filepath"
5 "strings"
6 "testing"
7
8 "github.com/gobuffalo/packr/v2/file"
9 "github.com/gobuffalo/packr/v2/file/resolver"
10 "github.com/stretchr/testify/require"
11 )
12
13 func Test_New(t *testing.T) {
14 r := require.New(t)
15
16 box := New("Test_NewBox", filepath.Join("_fixtures", "list_test"))
17 r.Len(box.List(), 4)
18
19 }
20 func Test_Box_AddString(t *testing.T) {
21 r := require.New(t)
22
23 box := New("Test_Box_AddString", "./templates")
24 s, err := box.FindString("foo.txt")
25 r.Error(err)
26 r.Equal("", s)
27
28 r.NoError(box.AddString("foo.txt", "foo!!"))
29 s, err = box.FindString("foo.txt")
30 r.NoError(err)
31 r.Equal("foo!!", s)
32 }
33
34 func Test_Box_AddBytes(t *testing.T) {
35 r := require.New(t)
36
37 box := New("Test_Box_AddBytes", "")
38 s, err := box.FindString("foo.txt")
39 r.Error(err)
40 r.Equal("", s)
41
42 r.NoError(box.AddBytes("foo.txt", []byte("foo!!")))
43 s, err = box.FindString("foo.txt")
44 r.NoError(err)
45 r.Equal("foo!!", s)
46 }
47
48 func Test_Box_String(t *testing.T) {
49 r := require.New(t)
50
51 box := New("Test_Box_String", "./templates")
52 d := resolver.NewInMemory(map[string]file.File{
53 "foo.txt": qfile("foo.txt", "foo!"),
54 })
55 box.SetResolver("foo.txt", d)
56
57 s := box.String("foo.txt")
58 r.Equal("foo!", s)
59
60 s = box.String("idontexist")
61 r.Equal("", s)
62 }
63
64 func Test_Box_String_Miss(t *testing.T) {
65 r := require.New(t)
66
67 box := New("Test_Box_String_Miss", filepath.Join("_fixtures", "templates"))
68
69 s := box.String("foo.txt")
70 r.Equal("FOO!!!", strings.TrimSpace(s))
71
72 s = box.String("idontexist")
73 r.Equal("", s)
74 }
75
76 func Test_Box_FindString(t *testing.T) {
77 r := require.New(t)
78
79 box := New("Test_Box_FindString", "./templates")
80 d := resolver.NewInMemory(map[string]file.File{
81 "foo.txt": qfile("foo.txt", "foo!"),
82 })
83 box.SetResolver("foo.txt", d)
84
85 s, err := box.FindString("foo.txt")
86 r.NoError(err)
87 r.Equal("foo!", s)
88
89 s, err = box.FindString("idontexist")
90 r.Error(err)
91 r.Equal("", s)
92 }
93
94 func Test_Box_FindString_Miss(t *testing.T) {
95 r := require.New(t)
96
97 box := New("Test_Box_FindString_Miss", filepath.Join("_fixtures", "templates"))
98
99 s, err := box.FindString("foo.txt")
100 r.NoError(err)
101 r.Equal("FOO!!!", strings.TrimSpace(s))
102
103 s, err = box.FindString("idontexist")
104 r.Error(err)
105 r.Equal("", s)
106 }
107
108 func Test_Box_Bytes(t *testing.T) {
109 r := require.New(t)
110
111 box := New("Test_Box_Bytes", "./templates")
112 d := resolver.NewInMemory(map[string]file.File{
113 "foo.txt": qfile("foo.txt", "foo!"),
114 })
115 box.SetResolver("foo.txt", d)
116
117 s := box.Bytes("foo.txt")
118 r.Equal([]byte("foo!"), s)
119
120 s = box.Bytes("idontexist")
121 r.Equal([]byte(""), s)
122 }
123
124 func Test_Box_Bytes_Miss(t *testing.T) {
125 r := require.New(t)
126
127 box := New("Test_Box_Bytes_Miss", filepath.Join("_fixtures", "templates"))
128
129 s := box.Bytes("foo.txt")
130 r.Equal([]byte("FOO!!!"), bytes.TrimSpace(s))
131
132 s = box.Bytes("idontexist")
133 r.Equal([]byte(""), s)
134 }
135
136 func Test_Box_Find(t *testing.T) {
137 r := require.New(t)
138
139 box := New("Test_Box_Find", "./templates")
140 d := resolver.NewInMemory(map[string]file.File{
141 "foo.txt": qfile("foo.txt", "foo!"),
142 })
143 box.SetResolver("foo.txt", d)
144
145 s, err := box.Find("foo.txt")
146 r.NoError(err)
147 r.Equal("foo!", string(s))
148
149 s, err = box.Find("idontexist")
150 r.Error(err)
151 r.Equal("", string(s))
152 }
153
154 func Test_Box_Find_Miss(t *testing.T) {
155 r := require.New(t)
156
157 box := New("Test_Box_Find_Miss", "./_fixtures/templates")
158 s, err := box.Find("foo.txt")
159 r.NoError(err)
160 r.Equal("FOO!!!", strings.TrimSpace(string(s)))
161
162 s, err = box.Find("idontexist")
163 r.Error(err)
164 r.Equal("", string(s))
165 }
166
167 func Test_Box_Has(t *testing.T) {
168 r := require.New(t)
169
170 box := New("Test_Box_Has", "./templates")
171 d := resolver.NewInMemory(map[string]file.File{
172 "foo.txt": qfile("foo.txt", "foo!"),
173 })
174 box.SetResolver("foo.txt", d)
175
176 r.True(box.Has("foo.txt"))
177 r.False(box.Has("idontexist"))
178 }
179
180 func Test_Box_Open(t *testing.T) {
181 r := require.New(t)
182
183 d := resolver.NewInMemory(map[string]file.File{
184 "foo.txt": qfile("foo.txt", "foo!"),
185 "bar": qfile("bar", "bar!"),
186 "baz/index.html": qfile("baz", "baz!"),
187 })
188 box := New("Test_Box_Open", "./templates")
189
190 box.DefaultResolver = d
191
192 for _, x := range []string{"foo.txt", "/foo.txt", "bar", "/bar", "baz", "/baz"} {
193 f, err := box.Open(x)
194 r.NoError(err)
195 r.NotZero(f)
196 }
197
198 f, err := box.Open("idontexist.txt")
199 r.Error(err)
200 r.Zero(f)
201 }
202
203 func Test_Box_List(t *testing.T) {
204 r := require.New(t)
205
206 box := New("Test_Box_List", filepath.Join("_fixtures", "list_test"))
207 r.NoError(box.AddString(filepath.Join("d", "d.txt"), "D"))
208
209 act := box.List()
210 exp := []string{"a.txt", filepath.Join("b", "b.txt"), filepath.Join("b", "b2.txt"), filepath.Join("c", "c.txt"), filepath.Join("d", "d.txt")}
211 r.Equal(exp, act)
212 }
213
214 func Test_Box_HasDir(t *testing.T) {
215 r := require.New(t)
216
217 box := New("Test_Box_HasDir", filepath.Join("_fixtures", "list_test"))
218 r.NoError(box.AddString("d/e/f.txt", "D"))
219
220 r.True(box.HasDir("d/e"))
221 r.True(box.HasDir("d"))
222 r.True(box.HasDir("c"))
223 r.False(box.HasDir("a"))
224 }
0 package packr
1
2 import (
3 "encoding/json"
4 "fmt"
5
6 "github.com/gobuffalo/packr/v2/file"
7 "github.com/gobuffalo/packr/v2/file/resolver"
8 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/oncer"
9 )
10
11 // File has been deprecated and file.File should be used instead
12 type File = file.File
13
14 var (
15 // ErrResOutsideBox gets returned in case of the requested resources being outside the box
16 // Deprecated
17 ErrResOutsideBox = fmt.Errorf("can't find a resource outside the box")
18 )
19
20 // PackBytes packs bytes for a file into a box.
21 // Deprecated
22 func PackBytes(box string, name string, bb []byte) {
23 b := NewBox(box)
24 d := resolver.NewInMemory(map[string]file.File{})
25 f, err := file.NewFile(name, bb)
26 if err != nil {
27 panic(err)
28 }
29 if err := d.Pack(name, f); err != nil {
30 panic(err)
31 }
32 b.SetResolver(name, d)
33 }
34
35 // PackBytesGzip packets the gzipped compressed bytes into a box.
36 // Deprecated
37 func PackBytesGzip(box string, name string, bb []byte) error {
38 // TODO: this function never did what it was supposed to do!
39 PackBytes(box, name, bb)
40 return nil
41 }
42
43 // PackJSONBytes packs JSON encoded bytes for a file into a box.
44 // Deprecated
45 func PackJSONBytes(box string, name string, jbb string) error {
46 var bb []byte
47 err := json.Unmarshal([]byte(jbb), &bb)
48 if err != nil {
49 return err
50 }
51 PackBytes(box, name, bb)
52 return nil
53 }
54
55 // Bytes is deprecated. Use Find instead
56 func (b *Box) Bytes(name string) []byte {
57 bb, _ := b.Find(name)
58 oncer.Deprecate(0, "github.com/gobuffalo/packr/v2#Box.Bytes", "Use github.com/gobuffalo/packr/v2#Box.Find instead.")
59 return bb
60 }
61
62 // MustBytes is deprecated. Use Find instead.
63 func (b *Box) MustBytes(name string) ([]byte, error) {
64 oncer.Deprecate(0, "github.com/gobuffalo/packr/v2#Box.MustBytes", "Use github.com/gobuffalo/packr/v2#Box.Find instead.")
65 return b.Find(name)
66 }
67
68 // String is deprecated. Use FindString instead
69 func (b *Box) String(name string) string {
70 oncer.Deprecate(0, "github.com/gobuffalo/packr/v2#Box.String", "Use github.com/gobuffalo/packr/v2#Box.FindString instead.")
71 return string(b.Bytes(name))
72 }
73
74 // MustString is deprecated. Use FindString instead
75 func (b *Box) MustString(name string) (string, error) {
76 oncer.Deprecate(0, "github.com/gobuffalo/packr/v2#Box.MustString", "Use github.com/gobuffalo/packr/v2#Box.FindString instead.")
77 return b.FindString(name)
78 }
0 package packr
1
2 import (
3 "testing"
4
5 "github.com/stretchr/testify/require"
6 )
7
8 func Test_PackBytes(t *testing.T) {
9 r := require.New(t)
10
11 box := NewBox("my/box")
12 name := "foo.txt"
13 body := []byte("foo!!")
14 PackBytes(box.Name, name, body)
15
16 f, err := box.FindString(name)
17 r.NoError(err)
18 r.Equal(string(body), f)
19 }
20
21 func Test_PackBytesGzip(t *testing.T) {
22 r := require.New(t)
23
24 box := NewBox("my/box")
25 name := "foo.txt"
26 body := []byte("foo!!")
27 PackBytesGzip(box.Name, name, body)
28
29 f, err := box.FindString(name)
30 r.NoError(err)
31 r.Equal(string(body), f)
32 }
33
34 func Test_PackJSONBytes(t *testing.T) {
35 r := require.New(t)
36
37 box := NewBox("my/box")
38 name := "foo.txt"
39 body := "\"PGgxPnRlbXBsYXRlcy9tYWlsZXJzL2xheW91dC5odG1sPC9oMT4KCjwlPSB5aWVsZCAlPgo=\""
40 PackJSONBytes(box.Name, name, body)
41
42 f, err := box.FindString(name)
43 r.NoError(err)
44 r.Equal("<h1>templates/mailers/layout.html</h1>\n\n<%= yield %>\n", f)
45 }
0 //go:generate mapgen -name "dirs" -zero "false" -go-type "bool" -pkg "" -a "nil" -b "nil" -c "nil" -bb "nil" -destination "packr"
1 // Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
2
3 package packr
4
5 import (
6 "sort"
7 "strings"
8 "sync"
9 )
10
11 // dirsMap wraps sync.Map and uses the following types:
12 // key: string
13 // value: bool
14 type dirsMap struct {
15 data sync.Map
16 }
17
18 // Delete the key from the map
19 func (m *dirsMap) Delete(key string) {
20 m.data.Delete(m.normalizeKey(key))
21 }
22
23 // Load the key from the map.
24 // Returns bool or bool.
25 // A false return indicates either the key was not found
26 // or the value is not of type bool
27 func (m *dirsMap) Load(key string) (bool, bool) {
28 i, ok := m.data.Load(m.normalizeKey(key))
29 if !ok {
30 return false, false
31 }
32 s, ok := i.(bool)
33 return s, ok
34 }
35
36 // LoadOrStore will return an existing key or
37 // store the value if not already in the map
38 func (m *dirsMap) LoadOrStore(key string, value bool) (bool, bool) {
39 i, _ := m.data.LoadOrStore(m.normalizeKey(key), value)
40 s, ok := i.(bool)
41 return s, ok
42 }
43
44 // Range over the bool values in the map
45 func (m *dirsMap) Range(f func(key string, value bool) bool) {
46 m.data.Range(func(k, v interface{}) bool {
47 key, ok := k.(string)
48 if !ok {
49 return false
50 }
51 value, ok := v.(bool)
52 if !ok {
53 return false
54 }
55 return f(key, value)
56 })
57 }
58
59 // Store a bool in the map
60 func (m *dirsMap) Store(key string, value bool) {
61 d := m.normalizeKey(key)
62 m.data.Store(d, value)
63 m.data.Store(strings.TrimPrefix(d, "/"), value)
64 }
65
66 // Keys returns a list of keys in the map
67 func (m *dirsMap) Keys() []string {
68 var keys []string
69 m.Range(func(key string, value bool) bool {
70 keys = append(keys, key)
71 return true
72 })
73 sort.Strings(keys)
74 return keys
75 }
76
77 func (m *dirsMap) normalizeKey(key string) string {
78 key = strings.Replace(key, "\\", "/", -1)
79
80 return key
81 }
0 package file
1
2 import (
3 "bytes"
4 "io"
5
6 "github.com/gobuffalo/packd"
7 )
8
9 // File represents a virtual, or physical, backing of
10 // a file object in a Box
11 type File = packd.File
12
13 // FileMappable types are capable of returning a map of
14 // path => File
15 type FileMappable interface {
16 FileMap() map[string]File
17 }
18
19 // NewFile returns a virtual File implementation
20 func NewFile(name string, b []byte) (File, error) {
21 return packd.NewFile(name, bytes.NewReader(b))
22 }
23
24 // NewDir returns a virtual dir implementation
25 func NewDir(name string) (File, error) {
26 return packd.NewDir(name)
27 }
28
29 func NewFileR(name string, r io.Reader) (File, error) {
30 return packd.NewFile(name, r)
31 }
0 package file
1
2 import (
3 "os"
4 "time"
5 )
6
7 type info struct {
8 Path string
9 Contents []byte
10 size int64
11 modTime time.Time
12 isDir bool
13 }
14
15 func (f info) Name() string {
16 return f.Path
17 }
18
19 func (f info) Size() int64 {
20 return f.size
21 }
22
23 func (f info) Mode() os.FileMode {
24 return 0444
25 }
26
27 func (f info) ModTime() time.Time {
28 return f.modTime
29 }
30
31 func (f info) IsDir() bool {
32 return f.isDir
33 }
34
35 func (f info) Sys() interface{} {
36 return nil
37 }
0 package resolver
1
2 import (
3 "io/ioutil"
4 "os"
5 "path/filepath"
6 "strings"
7 "sync"
8
9 "github.com/gobuffalo/packr/v2/file"
10 "github.com/gobuffalo/packr/v2/plog"
11 "github.com/karrick/godirwalk"
12 )
13
14 var _ Resolver = &Disk{}
15
16 type Disk struct {
17 Root string
18 }
19
20 func (d Disk) String() string {
21 return String(&d)
22 }
23
24 func (d *Disk) Resolve(box string, name string) (file.File, error) {
25 path := OsPath(name)
26 if !filepath.IsAbs(path) {
27 path = filepath.Join(OsPath(d.Root), path)
28 }
29 fi, err := os.Stat(path)
30 if err != nil {
31 return nil, err
32 }
33 if fi.IsDir() {
34 return file.NewDir(OsPath(name))
35 }
36 if bb, err := ioutil.ReadFile(path); err == nil {
37 return file.NewFile(OsPath(name), bb)
38 }
39 return nil, os.ErrNotExist
40 }
41
42 var _ file.FileMappable = &Disk{}
43
44 func (d *Disk) FileMap() map[string]file.File {
45 moot := &sync.Mutex{}
46 m := map[string]file.File{}
47 root := OsPath(d.Root)
48 if _, err := os.Stat(root); err != nil {
49 return m
50 }
51 callback := func(path string, de *godirwalk.Dirent) error {
52 if _, err := os.Stat(root); err != nil {
53 return nil
54 }
55 if !de.IsRegular() {
56 return nil
57 }
58 moot.Lock()
59 name := strings.TrimPrefix(path, root+string(filepath.Separator))
60 b, err := ioutil.ReadFile(path)
61 if err != nil {
62 return err
63 }
64 m[name], err = file.NewFile(name, b)
65 if err != nil {
66 return err
67 }
68 moot.Unlock()
69 return nil
70 }
71 err := godirwalk.Walk(root, &godirwalk.Options{
72 FollowSymbolicLinks: true,
73 Callback: callback,
74 })
75 if err != nil {
76 plog.Logger.Errorf("[%s] error walking %v", root, err)
77 }
78 return m
79 }
0 package resolver
1
2 import (
3 "io/ioutil"
4 "strings"
5 "testing"
6
7 "github.com/stretchr/testify/require"
8 )
9
10 func Test_Disk_Find(t *testing.T) {
11 r := require.New(t)
12
13 d := &Disk{
14 Root: "_fixtures\\templates",
15 }
16
17 f, err := d.Resolve("", "foo.txt")
18 r.NoError(err)
19
20 fi, err := f.FileInfo()
21 r.NoError(err)
22 r.Equal("foo.txt", fi.Name())
23
24 b, err := ioutil.ReadAll(f)
25 r.NoError(err)
26 r.Equal("foo!", strings.TrimSpace(string(b)))
27 }
0 // Copyright 2009 The Go Authors. All rights reserved.
1 // Use of this source code is governed by a BSD-style
2 // license that can be found in the LICENSE file.
3
4 // Package hex implements hexadecimal encoding and decoding.
5 package hex
6
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 )
12
13 const hextable = "0123456789abcdef"
14
15 // EncodedLen returns the length of an encoding of n source bytes.
16 // Specifically, it returns n * 2.
17 func EncodedLen(n int) int { return n * 2 }
18
19 // Encode encodes src into EncodedLen(len(src))
20 // bytes of dst. As a convenience, it returns the number
21 // of bytes written to dst, but this value is always EncodedLen(len(src)).
22 // Encode implements hexadecimal encoding.
23 func Encode(dst, src []byte) int {
24 for i, v := range src {
25 dst[i*2] = hextable[v>>4]
26 dst[i*2+1] = hextable[v&0x0f]
27 }
28
29 return len(src) * 2
30 }
31
32 // ErrLength reports an attempt to decode an odd-length input
33 // using Decode or DecodeString.
34 // The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
35 var ErrLength = fmt.Errorf("encoding/hex: odd length hex string")
36
37 // InvalidByteError values describe errors resulting from an invalid byte in a hex string.
38 type InvalidByteError byte
39
40 func (e InvalidByteError) Error() string {
41 return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
42 }
43
44 // DecodedLen returns the length of a decoding of x source bytes.
45 // Specifically, it returns x / 2.
46 func DecodedLen(x int) int { return x / 2 }
47
48 // Decode decodes src into DecodedLen(len(src)) bytes,
49 // returning the actual number of bytes written to dst.
50 //
51 // Decode expects that src contains only hexadecimal
52 // characters and that src has even length.
53 // If the input is malformed, Decode returns the number
54 // of bytes decoded before the error.
55 func Decode(dst, src []byte) (int, error) {
56 var i int
57 for i = 0; i < len(src)/2; i++ {
58 a, ok := fromHexChar(src[i*2])
59 if !ok {
60 return i, InvalidByteError(src[i*2])
61 }
62 b, ok := fromHexChar(src[i*2+1])
63 if !ok {
64 return i, InvalidByteError(src[i*2+1])
65 }
66 dst[i] = (a << 4) | b
67 }
68 if len(src)%2 == 1 {
69 // Check for invalid char before reporting bad length,
70 // since the invalid char (if present) is an earlier problem.
71 if _, ok := fromHexChar(src[i*2]); !ok {
72 return i, InvalidByteError(src[i*2])
73 }
74 return i, ErrLength
75 }
76 return i, nil
77 }
78
79 // fromHexChar converts a hex character into its value and a success flag.
80 func fromHexChar(c byte) (byte, bool) {
81 switch {
82 case '0' <= c && c <= '9':
83 return c - '0', true
84 case 'a' <= c && c <= 'f':
85 return c - 'a' + 10, true
86 case 'A' <= c && c <= 'F':
87 return c - 'A' + 10, true
88 }
89
90 return 0, false
91 }
92
93 // EncodeToString returns the hexadecimal encoding of src.
94 func EncodeToString(src []byte) string {
95 dst := make([]byte, EncodedLen(len(src)))
96 Encode(dst, src)
97 return string(dst)
98 }
99
100 // DecodeString returns the bytes represented by the hexadecimal string s.
101 //
102 // DecodeString expects that src contains only hexadecimal
103 // characters and that src has even length.
104 // If the input is malformed, DecodeString returns
105 // the bytes decoded before the error.
106 func DecodeString(s string) ([]byte, error) {
107 src := []byte(s)
108 // We can use the source slice itself as the destination
109 // because the decode loop increments by one and then the 'seen' byte is not used anymore.
110 n, err := Decode(src, src)
111 return src[:n], err
112 }
113
114 // Dump returns a string that contains a hex dump of the given data. The format
115 // of the hex dump matches the output of `hexdump -C` on the command line.
116 func Dump(data []byte) string {
117 var buf bytes.Buffer
118 dumper := Dumper(&buf)
119 dumper.Write(data)
120 dumper.Close()
121 return buf.String()
122 }
123
124 // bufferSize is the number of hexadecimal characters to buffer in encoder and decoder.
125 const bufferSize = 1024
126
127 type encoder struct {
128 w io.Writer
129 err error
130 out [bufferSize]byte // output buffer
131 }
132
133 // NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w.
134 func NewEncoder(w io.Writer) io.Writer {
135 return &encoder{w: w}
136 }
137
138 func (e *encoder) Write(p []byte) (n int, err error) {
139 for len(p) > 0 && e.err == nil {
140 chunkSize := bufferSize / 2
141 if len(p) < chunkSize {
142 chunkSize = len(p)
143 }
144
145 var written int
146 encoded := Encode(e.out[:], p[:chunkSize])
147 written, e.err = e.w.Write(e.out[:encoded])
148 n += written / 2
149 p = p[chunkSize:]
150 }
151 return n, e.err
152 }
153
154 type decoder struct {
155 r io.Reader
156 err error
157 in []byte // input buffer (encoded form)
158 arr [bufferSize]byte // backing array for in
159 }
160
161 // NewDecoder returns an io.Reader that decodes hexadecimal characters from r.
162 // NewDecoder expects that r contain only an even number of hexadecimal characters.
163 func NewDecoder(r io.Reader) io.Reader {
164 return &decoder{r: r}
165 }
166
167 func (d *decoder) Read(p []byte) (n int, err error) {
168 // Fill internal buffer with sufficient bytes to decode
169 if len(d.in) < 2 && d.err == nil {
170 var numCopy, numRead int
171 numCopy = copy(d.arr[:], d.in) // Copies either 0 or 1 bytes
172 numRead, d.err = d.r.Read(d.arr[numCopy:])
173 d.in = d.arr[:numCopy+numRead]
174 if d.err == io.EOF && len(d.in)%2 != 0 {
175 if _, ok := fromHexChar(d.in[len(d.in)-1]); !ok {
176 d.err = InvalidByteError(d.in[len(d.in)-1])
177 } else {
178 d.err = io.ErrUnexpectedEOF
179 }
180 }
181 }
182
183 // Decode internal buffer into output buffer
184 if numAvail := len(d.in) / 2; len(p) > numAvail {
185 p = p[:numAvail]
186 }
187 numDec, err := Decode(p, d.in[:len(p)*2])
188 d.in = d.in[2*numDec:]
189 if err != nil {
190 d.in, d.err = nil, err // Decode error; discard input remainder
191 }
192
193 if len(d.in) < 2 {
194 return numDec, d.err // Only expose errors when buffer fully consumed
195 }
196 return numDec, nil
197 }
198
199 // Dumper returns a WriteCloser that writes a hex dump of all written data to
200 // w. The format of the dump matches the output of `hexdump -C` on the command
201 // line.
202 func Dumper(w io.Writer) io.WriteCloser {
203 return &dumper{w: w}
204 }
205
206 type dumper struct {
207 w io.Writer
208 rightChars [18]byte
209 buf [14]byte
210 used int // number of bytes in the current line
211 n uint // number of bytes, total
212 closed bool
213 }
214
215 func toChar(b byte) byte {
216 if b < 32 || b > 126 {
217 return '.'
218 }
219 return b
220 }
221
222 func (h *dumper) Write(data []byte) (n int, err error) {
223 if h.closed {
224 return 0, fmt.Errorf("encoding/hex: dumper closed")
225 }
226
227 // Output lines look like:
228 // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=|
229 // ^ offset ^ extra space ^ ASCII of line.
230 for i := range data {
231 if h.used == 0 {
232 // At the beginning of a line we print the current
233 // offset in hex.
234 h.buf[0] = byte(h.n >> 24)
235 h.buf[1] = byte(h.n >> 16)
236 h.buf[2] = byte(h.n >> 8)
237 h.buf[3] = byte(h.n)
238 Encode(h.buf[4:], h.buf[:4])
239 h.buf[12] = ' '
240 h.buf[13] = ' '
241 _, err = h.w.Write(h.buf[4:])
242 if err != nil {
243 return
244 }
245 }
246 Encode(h.buf[:], data[i:i+1])
247 h.buf[2] = ' '
248 l := 3
249 if h.used == 7 {
250 // There's an additional space after the 8th byte.
251 h.buf[3] = ' '
252 l = 4
253 } else if h.used == 15 {
254 // At the end of the line there's an extra space and
255 // the bar for the right column.
256 h.buf[3] = ' '
257 h.buf[4] = '|'
258 l = 5
259 }
260 _, err = h.w.Write(h.buf[:l])
261 if err != nil {
262 return
263 }
264 n++
265 h.rightChars[h.used] = toChar(data[i])
266 h.used++
267 h.n++
268 if h.used == 16 {
269 h.rightChars[16] = '|'
270 h.rightChars[17] = '\n'
271 _, err = h.w.Write(h.rightChars[:])
272 if err != nil {
273 return
274 }
275 h.used = 0
276 }
277 }
278 return
279 }
280
281 func (h *dumper) Close() (err error) {
282 // See the comments in Write() for the details of this format.
283 if h.closed {
284 return
285 }
286 h.closed = true
287 if h.used == 0 {
288 return
289 }
290 h.buf[0] = ' '
291 h.buf[1] = ' '
292 h.buf[2] = ' '
293 h.buf[3] = ' '
294 h.buf[4] = '|'
295 nBytes := h.used
296 for h.used < 16 {
297 l := 3
298 if h.used == 7 {
299 l = 4
300 } else if h.used == 15 {
301 l = 5
302 }
303 _, err = h.w.Write(h.buf[:l])
304 if err != nil {
305 return
306 }
307 h.used++
308 }
309 h.rightChars[nBytes] = '|'
310 h.rightChars[nBytes+1] = '\n'
311 _, err = h.w.Write(h.rightChars[:nBytes+2])
312 return
313 }
0 package resolver
1
2 import (
3 "bytes"
4 "compress/gzip"
5 "io"
6 "io/ioutil"
7 "os"
8 "strings"
9 "sync"
10
11 "github.com/gobuffalo/packr/v2/file/resolver/encoding/hex"
12 "github.com/gobuffalo/packr/v2/plog"
13
14 "github.com/gobuffalo/packr/v2/file"
15 )
16
17 var _ Resolver = &HexGzip{}
18
19 type HexGzip struct {
20 packed map[string]string
21 unpacked map[string]string
22 moot *sync.RWMutex
23 }
24
25 func (hg HexGzip) String() string {
26 return String(&hg)
27 }
28
29 var _ file.FileMappable = &HexGzip{}
30
31 func (hg *HexGzip) FileMap() map[string]file.File {
32 hg.moot.RLock()
33 var names []string
34 for k := range hg.packed {
35 names = append(names, k)
36 }
37 hg.moot.RUnlock()
38 m := map[string]file.File{}
39 for _, n := range names {
40 if f, err := hg.Resolve("", n); err == nil {
41 m[n] = f
42 }
43 }
44 return m
45 }
46
47 func (hg *HexGzip) Resolve(box string, name string) (file.File, error) {
48 plog.Debug(hg, "Resolve", "box", box, "name", name)
49 hg.moot.Lock()
50 defer hg.moot.Unlock()
51
52 if s, ok := hg.unpacked[name]; ok {
53 return file.NewFile(name, []byte(s))
54 }
55 packed, ok := hg.packed[name]
56 if !ok {
57 return nil, os.ErrNotExist
58 }
59
60 unpacked, err := UnHexGzipString(packed)
61 if err != nil {
62 return nil, err
63 }
64
65 f, err := file.NewFile(OsPath(name), []byte(unpacked))
66 if err != nil {
67 return nil, err
68 }
69 hg.unpacked[name] = f.String()
70 return f, nil
71 }
72
73 func NewHexGzip(files map[string]string) (*HexGzip, error) {
74 if files == nil {
75 files = map[string]string{}
76 }
77
78 hg := &HexGzip{
79 packed: files,
80 unpacked: map[string]string{},
81 moot: &sync.RWMutex{},
82 }
83
84 return hg, nil
85 }
86
87 func HexGzipString(s string) (string, error) {
88 bb := &bytes.Buffer{}
89 enc := hex.NewEncoder(bb)
90 zw := gzip.NewWriter(enc)
91 io.Copy(zw, strings.NewReader(s))
92 zw.Close()
93
94 return bb.String(), nil
95 }
96
97 func UnHexGzipString(packed string) (string, error) {
98 br := bytes.NewBufferString(packed)
99 dec := hex.NewDecoder(br)
100 zr, err := gzip.NewReader(dec)
101 if err != nil {
102 return "", err
103 }
104 defer zr.Close()
105
106 b, err := ioutil.ReadAll(zr)
107 if err != nil {
108 return "", err
109 }
110 return string(b), nil
111 }
0 package resolver
1
2 import (
3 "io/ioutil"
4 "strings"
5 "testing"
6
7 "github.com/stretchr/testify/require"
8 )
9
10 func Test_HexGzip_Find(t *testing.T) {
11 r := require.New(t)
12
13 x, err := HexGzipString("foo!")
14 r.NoError(err)
15 files := map[string]string{
16 "foo.txt": x,
17 }
18 d, err := NewHexGzip(files)
19 r.NoError(err)
20
21 f, err := d.Resolve("", "foo.txt")
22 r.NoError(err)
23
24 fi, err := f.FileInfo()
25 r.NoError(err)
26 r.Equal("foo.txt", fi.Name())
27
28 b, err := ioutil.ReadAll(f)
29 r.NoError(err)
30 r.Equal("foo!", strings.TrimSpace(string(b)))
31 }
32
33 func Test_fo(t *testing.T) {
34 r := require.New(t)
35 x := "1f8b08000000000000ff9c575f6fe3b8117fd7a798ea490e6c0a7d2b5ce4806c76b3b9c29718916f53e0b04818696cb34b715892b2e306feeec5905262a7ebddb6010249e4f037bff9c399b195f537b942907550647c96a9d6920b506400f94a8575f7246a6acb153d75cba5d454a2d9ecf293bbfd930596e46af45e9f906cb7934182a5ad74b2d5b45aa13b7de040e83d85ce38d21a9bd263dd39ccb30ce0e505d41204d9e0c5bd0aeb3959d8eff9e0cb4b5afd8d1ad47efe6db5dfffd4a689255bf6ffed364ff8681a98ecf7efb55df87b7c8a1b00b577cbd326f12e63a93fffc59c96e2ddd3043988ee67842ee6bff6840e419c2f6b72fe34f673e9d17bce0d96a9c9043421ec2cfec0a437a177a446595696f0e9e60b280f9dc70602c11ab505bf55a15e83c7109459797892bc4b06b66b7408618d7c525aab552d395519e109955981eb8c808fb8949d0ebc9a37b8414db6451372916da48b1acf8133577cc650e49f6f1f3edd7cc9c7c7b2a3282bad85b3de1a71616df6fdb8b2e802ce383062e1a4f15a0672596f2c07a02ce1c25a66946c905a83a32ea007691a6855d368dc4a877c53a0d7c8a7fc9a3addc01342834b65b011b0582bcf48618d60d06d106a34011dd01276d4b977ce115959f2d21d75eccef181b231ac1c75d68f01432d840026d060ada5c30616b77398fc021f6fef6f1823e96d511acf3ed85107b269401e920f048fd2da473893cb80eeac07e3c8488688eac610d632a477d82aade1e676016bb9c1b461707b80c9f62278d9c6a0b3d9ae4336d5a1a7ced503e168ab07e9618b5a0f46ff1a406a4f3ded083fb8dd21d46bacbf6103ca4467926bd0f1dbeec811d1f8c78a3d7da534fa476621e1f26271793db998cd12e2183c810a43c0a4deca1d67251fb65ad6d880963e0cbae29923ea63e6ae42f28875b8413390658cd7b044cfb2602030b841c7c9514bae77225b76a6e64c2b4647790b2f5c5596319fcfcfc1281d57202d0cf9266e705b0cefb736b24a62009fcc66ca5767dc7f9faa27fc57a5225105723885a164889b4eeb97fd003077782f1dfa29fcf175d0d9af0d3ab9c4382ffaeb5c8cc4b5348d463740ec0fc80c55e588c18d6c710af9c350e1f95b700cf7fb879e569e30f6a32c3ef99e76815a1914bb74070e1be5b08edeaeaad9e034f1bbc722b6acaa9a15a3b7d3335a81c37f76e8436a6318d07928964ac717be98bb9138c239e864623e9c99c5ef1ef8b4b7cb122a0c29a57ab57dc985589803c1dfaadb9b237d073559545c020faa45f90f4f261f8db203bfa60e72baa94516734781fd245752191fe0b2babb021982acbf7901eb10ac9f96e576bb15b495de0a72ab5299069f855ddbf2d291f7934a057cb84b663c5c915ba1db3d148c341ad4dc614b9b6856a3bc7cd25c33943ff627b751cee59f1a71340744f87b27ad0794f5fad59dca8084c0553dcd456290855a7c91bac3220fcff948146796acb8246330cafd4f94e318917a47d252b4711a111f3ffc1fb1a83074363696ce63e2ae5391991e693ddc29beaf87453f7f5a1479998fe19a5aecefe07713f390061f7cab99e9bcf41e83ff40cf2366e963ef5af2362c1db531896df7a4550de9d291db65ff71bf233187a173869564fbec44572ecb23d35361d5241bd0544bddab1ef39c019d8ddac36bf386c77e0a168bc771eca8a6490883ea777d2f7a9a123e43d5e462dd1874918b69c5507d66c5bec2eb2d39046596e4da4875fa7a5d5e4729a178d82e1baa7d1911d5bfa2682af8c7717c2de7bfbd12bc62292eab3ca9a08bffe4524f588ce3ca799c3a630b882324bf7da0e722172269449f8fc690a399fc5ee5a3bfc6437f7ad74b4415c816e8dc2806ea354e8b032ec528dbbf1b8d8642fa030773e7ee77fb822c0d2853531bc7bee4d138212cb9372a0f86025c2f16f34a40cefe9c96253ecbd66ae4293587f35fd2ba7fb77130ebbce96f083d9c9d190a67678026dee2aa9a89183f1eba8e262e581034144933d8966b734d6d8bf146c66908aca3e7dd4f221d65fe8b2c39f9cba74cf9f1d6a87e941bbddf871f6287214b68c7334155cdeefa584cd388c083f539e4d651d3c5cbd337d7aa9acdd9926b940d3a3f8556da3f7ce0b1f06b7abce47f9f5c91db4ad76033e15642f9b40f4f1edbfc9eb3e6df010000ffffa0d4ca87a10e0000"
36 y, err := UnHexGzipString(x)
37 r.NoError(err)
38 r.NotEqual("", y)
39 }
0 package resolver
1
2 import (
3 "path/filepath"
4 "runtime"
5 "strings"
6 )
7
8 func Key(s string) string {
9 s = strings.Replace(s, "\\", "/", -1)
10 return s
11 }
12
13 func OsPath(s string) string {
14 if runtime.GOOS == "windows" {
15 s = strings.Replace(s, "/", string(filepath.Separator), -1)
16 } else {
17 s = strings.Replace(s, "\\", string(filepath.Separator), -1)
18 }
19 return s
20 }
0 package resolver
1
2 import (
3 "runtime"
4 "testing"
5
6 "github.com/stretchr/testify/require"
7 )
8
9 func Test_Ident_OsPath(t *testing.T) {
10 table := map[string]string{
11 "foo/bar/baz": "foo/bar/baz",
12 "foo\\bar\\baz": "foo/bar/baz",
13 }
14
15 if runtime.GOOS == "windows" {
16 table = ident_OsPath_Windows_Table()
17 }
18
19 for in, out := range table {
20 t.Run(in, func(st *testing.T) {
21 r := require.New(st)
22 r.Equal(out, OsPath(in))
23 })
24 }
25 }
26
27 func ident_OsPath_Windows_Table() map[string]string {
28 return map[string]string{
29 "foo/bar/baz": "foo\\bar\\baz",
30 "foo\\bar\\baz": "foo\\bar\\baz",
31 }
32 }
0 package resolver
1
2 import (
3 "io/ioutil"
4
5 "github.com/gobuffalo/packd"
6 "github.com/gobuffalo/packr/v2/file"
7 "github.com/gobuffalo/packr/v2/plog"
8 )
9
10 var _ Resolver = &InMemory{}
11
12 type InMemory struct {
13 *packd.MemoryBox
14 }
15
16 func (d InMemory) String() string {
17 return String(&d)
18 }
19
20 func (d *InMemory) Resolve(box string, name string) (file.File, error) {
21 b, err := d.MemoryBox.Find(name)
22 if err != nil {
23 return nil, err
24 }
25 return file.NewFile(name, b)
26 }
27
28 func (d *InMemory) Pack(name string, f file.File) error {
29 plog.Debug(d, "Pack", "name", name)
30 b, err := ioutil.ReadAll(f)
31 if err != nil {
32 return err
33 }
34 d.AddBytes(name, b)
35 return nil
36 }
37
38 func (d *InMemory) FileMap() map[string]file.File {
39 m := map[string]file.File{}
40 d.Walk(func(path string, file file.File) error {
41 m[path] = file
42 return nil
43 })
44 return m
45 }
46
47 func NewInMemory(files map[string]file.File) *InMemory {
48 if files == nil {
49 files = map[string]file.File{}
50 }
51 box := packd.NewMemoryBox()
52
53 for p, f := range files {
54 if b, err := ioutil.ReadAll(f); err == nil {
55 box.AddBytes(p, b)
56 }
57 }
58
59 return &InMemory{
60 MemoryBox: box,
61 }
62 }
0 package resolver
1
2 import (
3 "io/ioutil"
4 "strings"
5 "testing"
6
7 "github.com/gobuffalo/packr/v2/file"
8 "github.com/stretchr/testify/require"
9 )
10
11 func Test_inMemory_Find(t *testing.T) {
12 r := require.New(t)
13
14 files := map[string]file.File{
15 "foo.txt": qfile("foo.txt", "foo!"),
16 }
17 d := NewInMemory(files)
18
19 f, err := d.Resolve("", "foo.txt")
20 r.NoError(err)
21
22 fi, err := f.FileInfo()
23 r.NoError(err)
24 r.Equal("foo.txt", fi.Name())
25
26 b, err := ioutil.ReadAll(f)
27 r.NoError(err)
28 r.Equal("foo!", strings.TrimSpace(string(b)))
29 }
0 package resolver
1
2 import "github.com/gobuffalo/packr/v2/file"
3
4 type Packable interface {
5 Pack(name string, f file.File) error
6 }
0 package resolver
1
2 import (
3 "encoding/json"
4 "fmt"
5 "os"
6
7 "github.com/gobuffalo/packr/v2/file"
8 )
9
10 type Resolver interface {
11 Resolve(string, string) (file.File, error)
12 }
13
14 func defaultResolver() Resolver {
15 pwd, _ := os.Getwd()
16 return &Disk{
17 Root: pwd,
18 }
19 }
20
21 var DefaultResolver = defaultResolver()
22
23 func String(r Resolver) string {
24 m := map[string]interface{}{
25 "name": fmt.Sprintf("%T", r),
26 }
27 if fm, ok := r.(file.FileMappable); ok {
28 m["files"] = fm
29 }
30 b, _ := json.Marshal(m)
31 return string(b)
32 }
0 package resolver
1
2 import "github.com/gobuffalo/packr/v2/file"
3
4 func qfile(name string, body string) file.File {
5 f, err := file.NewFile(name, []byte(body))
6 if err != nil {
7 panic(err)
8 }
9 return f
10 }
0 module github.com/gobuffalo/packr/v2
1
2 go 1.12
3
4 require (
5 github.com/gobuffalo/envy v1.7.0
6 github.com/gobuffalo/logger v1.0.0
7 github.com/gobuffalo/packd v0.3.0
8 github.com/karrick/godirwalk v1.10.12
9 github.com/rogpeppe/go-internal v1.3.0
10 github.com/sirupsen/logrus v1.4.2
11 github.com/spf13/cobra v0.0.5
12 github.com/stretchr/testify v1.3.0
13 golang.org/x/sync v0.0.0-20190423024810-112230192c58
14 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c
15 )
0 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
1 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
2 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
3 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
4 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
5 github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
6 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
8 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
10 github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
11 github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
12 github.com/gobuffalo/logger v1.0.0 h1:xw9Ko9EcC5iAFprrjJ6oZco9UpzS5MQ4jAwghsLHdy4=
13 github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
14 github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
15 github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
16 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
17 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
18 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
19 github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
20 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
21 github.com/karrick/godirwalk v1.10.12 h1:BqUm+LuJcXjGv1d2mj3gBiQyrQ57a0rYoAmhvJQ7RDU=
22 github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
23 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
24 github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
25 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
26 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
27 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
28 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
29 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
30 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
31 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
32 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
33 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
34 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
35 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
36 github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
37 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
38 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
39 github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
40 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
41 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
42 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
43 github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
44 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
45 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
46 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
47 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
48 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
49 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
50 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
51 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
52 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
53 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
54 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
55 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
56 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
57 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
58 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
59 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
60 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
61 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
62 golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
63 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
64 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
65 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
66 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
67 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
68 golang.org/x/sys v0.0.0-20190515120540-06a5c4944438 h1:khxRGsvPk4n2y8I/mLLjp7e5dMTJmH75wvqS6nMwUtY=
69 golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
70 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
71 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c h1:KfpJVdWhuRqNk4XVXzjXf2KAV4TBEP77SYdFGjeGuIE=
72 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
73 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
74 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
75 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
76 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
0 package packr
1
2 import (
3 "os"
4 "path/filepath"
5 "runtime"
6 "strings"
7
8 "github.com/gobuffalo/envy"
9 "github.com/gobuffalo/packr/v2/plog"
10 )
11
12 func construct(name string, path string) *Box {
13 return &Box{
14 Path: path,
15 Name: name,
16 ResolutionDir: resolutionDir(path),
17 resolvers: resolversMap{},
18 dirs: dirsMap{},
19 }
20 }
21
22 func resolutionDirTestFilename(filename, og string) (string, bool) {
23 ng := filepath.Join(filepath.Dir(filename), og)
24
25 // // this little hack courtesy of the `-cover` flag!!
26 cov := filepath.Join("_test", "_obj_test")
27 ng = strings.Replace(ng, string(filepath.Separator)+cov, "", 1)
28
29 if resolutionDirExists(ng, og) {
30 return ng, true
31 }
32
33 ng = filepath.Join(envy.GoPath(), "src", ng)
34 if resolutionDirExists(ng, og) {
35 return ng, true
36 }
37
38 return og, false
39 }
40
41 func resolutionDirExists(s, og string) bool {
42 _, err := os.Stat(s)
43 if err != nil {
44 return false
45 }
46 plog.Debug("packr", "resolutionDir", "original", og, "resolved", s)
47 return true
48 }
49
50 func resolutionDir(og string) string {
51 ng, _ := filepath.Abs(og)
52
53 if resolutionDirExists(ng, og) {
54 return ng
55 }
56
57 // packr.New
58 _, filename, _, _ := runtime.Caller(3)
59 ng, ok := resolutionDirTestFilename(filename, og)
60 if ok {
61 return ng
62 }
63
64 // packr.NewBox (deprecated)
65 _, filename, _, _ = runtime.Caller(4)
66 ng, ok = resolutionDirTestFilename(filename, og)
67 if ok {
68 return ng
69 }
70
71 return og
72 }
0 package packr
1
2 import (
3 "net/http"
4 "net/http/httptest"
5 "strings"
6 "testing"
7
8 "github.com/gobuffalo/packd"
9 "github.com/gobuffalo/packr/v2/file/resolver"
10 "github.com/stretchr/testify/require"
11 )
12
13 var httpBox = func() packd.Box {
14 box := New("http box", "")
15
16 ind, err := resolver.HexGzipString("<h1>Index!</h1>")
17 if err != nil {
18 panic(err)
19 }
20
21 hello, err := resolver.HexGzipString("hello world!")
22 if err != nil {
23 panic(err)
24 }
25
26 hg, err := resolver.NewHexGzip(map[string]string{
27 "index.html": ind,
28 "hello.txt": hello,
29 })
30 if err != nil {
31 panic(err)
32 }
33
34 box.DefaultResolver = hg
35 return box
36 }()
37
38 func Test_HTTPBox(t *testing.T) {
39 r := require.New(t)
40
41 mux := http.NewServeMux()
42 mux.Handle("/", http.FileServer(httpBox))
43
44 req, err := http.NewRequest("GET", "/hello.txt", nil)
45 r.NoError(err)
46
47 res := httptest.NewRecorder()
48
49 mux.ServeHTTP(res, req)
50
51 r.Equal(200, res.Code)
52 r.Equal("hello world!", strings.TrimSpace(res.Body.String()))
53 }
54
55 func Test_HTTPBox_NotFound(t *testing.T) {
56 r := require.New(t)
57
58 mux := http.NewServeMux()
59 mux.Handle("/", http.FileServer(httpBox))
60
61 req, err := http.NewRequest("GET", "/notInBox.txt", nil)
62 r.NoError(err)
63
64 res := httptest.NewRecorder()
65
66 mux.ServeHTTP(res, req)
67
68 r.Equal(404, res.Code)
69 }
70
71 func Test_HTTPBox_Handles_IndexHTML_Nested(t *testing.T) {
72 r := require.New(t)
73
74 box := New("Test_HTTPBox_Handles_IndexHTML_Nested", "!")
75 box.AddString("foo/index.html", "foo")
76
77 mux := http.NewServeMux()
78 mux.Handle("/", http.FileServer(box))
79
80 req, err := http.NewRequest("GET", "/foo", nil)
81 r.NoError(err)
82
83 res := httptest.NewRecorder()
84
85 mux.ServeHTTP(res, req)
86
87 r.Equal(200, res.Code)
88
89 r.Equal("foo", strings.TrimSpace(res.Body.String()))
90 }
91
92 func Test_HTTPBox_Handles_IndexHTML(t *testing.T) {
93 r := require.New(t)
94
95 mux := http.NewServeMux()
96 mux.Handle("/", http.FileServer(httpBox))
97
98 req, err := http.NewRequest("GET", "/", nil)
99 r.NoError(err)
100
101 res := httptest.NewRecorder()
102
103 mux.ServeHTTP(res, req)
104
105 r.Equal(200, res.Code)
106
107 r.Equal("<h1>Index!</h1>", strings.TrimSpace(res.Body.String()))
108 }
109
110 func Test_HTTPBox_CaseInsensitive(t *testing.T) {
111 mux := http.NewServeMux()
112 httpBox.AddString("myfile.txt", "this is my file")
113 mux.Handle("/", http.FileServer(httpBox))
114
115 for _, path := range []string{"/MyFile.txt", "/myfile.txt", "/Myfile.txt"} {
116 t.Run(path, func(st *testing.T) {
117 r := require.New(st)
118
119 req, err := http.NewRequest("GET", path, nil)
120 r.NoError(err)
121
122 res := httptest.NewRecorder()
123
124 mux.ServeHTTP(res, req)
125
126 r.Equal(200, res.Code)
127 r.Equal("this is my file", strings.TrimSpace(res.Body.String()))
128 })
129 }
130 }
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
28 .idea/
0 The MIT License (MIT)
1
2 Copyright (c) 2019 Mark Bates
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
0 TAGS ?= ""
1 GO_BIN ?= "go"
2
3 install:
4 $(GO_BIN) install -tags ${TAGS} -v .
5 make tidy
6
7 tidy:
8 ifeq ($(GO111MODULE),on)
9 $(GO_BIN) mod tidy
10 else
11 echo skipping go mod tidy
12 endif
13
14 deps:
15 $(GO_BIN) get -tags ${TAGS} -t ./...
16 make tidy
17
18 build:
19 $(GO_BIN) build -v .
20 make tidy
21
22 test:
23 $(GO_BIN) test -cover -tags ${TAGS} ./...
24 make tidy
25
26 ci-deps:
27 $(GO_BIN) get -tags ${TAGS} -t ./...
28
29 ci-test:
30 $(GO_BIN) test -tags ${TAGS} -race ./...
31
32 lint:
33 go get github.com/golangci/golangci-lint/cmd/golangci-lint
34 golangci-lint run --enable-all
35 make tidy
36
37 update:
38 ifeq ($(GO111MODULE),on)
39 rm go.*
40 $(GO_BIN) mod init
41 $(GO_BIN) mod tidy
42 else
43 $(GO_BIN) get -u -tags ${TAGS}
44 endif
45 make test
46 make install
47 make tidy
48
49 release-test:
50 $(GO_BIN) test -tags ${TAGS} -race ./...
51 make tidy
52
53 release:
54 $(GO_BIN) get github.com/gobuffalo/release
55 make tidy
56 release -y -f version.go --skip-packr
57 make tidy
58
59
60
0 # github.com/markbates/errx Stands on the Shoulders of Giants
1
2 github.com/markbates/errx does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants, this project would not be possible. Please make sure to check them out and thank them for all of their hard work.
3
4 Thank you to the following **GIANTS**:
5
0 variables:
1 GOBIN: "$(GOPATH)/bin" # Go binaries path
2 GOPATH: "$(system.defaultWorkingDirectory)/gopath" # Go workspace path
3 modulePath: "$(GOPATH)/src/github.com/$(build.repository.name)" # Path to the module"s code
4
5 jobs:
6 - job: Windows
7 pool:
8 vmImage: "vs2017-win2016"
9 strategy:
10 matrix:
11 go 1.10:
12 go_version: "1.10"
13 go 1.11 (on):
14 go_version: "1.11.5"
15 GO111MODULE: "on"
16 go 1.11 (off):
17 go_version: "1.11.5"
18 GO111MODULE: "off"
19 go 1.12 (on):
20 go_version: "1.12"
21 GO111MODULE: "on"
22 go 1.12 (off):
23 go_version: "1.12"
24 GO111MODULE: "off"
25 steps:
26 - template: azure-tests.yml
27
28 - job: macOS
29 pool:
30 vmImage: "macOS-10.13"
31 strategy:
32 matrix:
33 go 1.10:
34 go_version: "1.10"
35 go 1.11 (on):
36 go_version: "1.11.5"
37 GO111MODULE: "on"
38 go 1.11 (off):
39 go_version: "1.11.5"
40 GO111MODULE: "off"
41 go 1.12 (on):
42 go_version: "1.12"
43 GO111MODULE: "on"
44 go 1.12 (off):
45 go_version: "1.12"
46 GO111MODULE: "off"
47 steps:
48 - template: azure-tests.yml
49
50 - job: Linux
51 pool:
52 vmImage: "ubuntu-16.04"
53 strategy:
54 matrix:
55 go 1.10:
56 go_version: "1.10"
57 go 1.11 (on):
58 go_version: "1.11.5"
59 GO111MODULE: "on"
60 go 1.11 (off):
61 go_version: "1.11.5"
62 GO111MODULE: "off"
63 go 1.12 (on):
64 go_version: "1.12"
65 GO111MODULE: "on"
66 go 1.12 (off):
67 go_version: "1.12"
68 GO111MODULE: "off"
69 steps:
70 - template: azure-tests.yml
0 steps:
1 - task: GoTool@0
2 inputs:
3 version: $(go_version)
4 - task: Bash@3
5 inputs:
6 targetType: inline
7 script: |
8 mkdir -p "$(GOBIN)"
9 mkdir -p "$(GOPATH)/pkg"
10 mkdir -p "$(modulePath)"
11 shopt -s extglob
12 mv !(gopath) "$(modulePath)"
13 displayName: "Setup Go Workspace"
14 - script: |
15 go get -t -v ./...
16 go test -race ./...
17 workingDirectory: "$(modulePath)"
18 displayName: "Tests"
0 package errx
1
2 // go2 errors
3 type Wrapper interface {
4 Unwrap() error
5 }
6
7 // pkg/errors
8 type Causer interface {
9 Cause() error
10 }
11
12 func Unwrap(err error) error {
13 switch e := err.(type) {
14 case Wrapper:
15 return e.Unwrap()
16 case Causer:
17 return e.Cause()
18 }
19 return err
20 }
21
22 var Cause = Unwrap
0 package errx
1
2 // Version of errx
3 const Version = "v1.0.0"
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
28 .idea/
0 The MIT License (MIT)
1
2 Copyright (c) 2018 Mark Bates
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
0 TAGS ?= "sqlite"
1 GO_BIN ?= go
2
3 install:
4 packr
5 $(GO_BIN) install -v .
6
7 deps:
8 $(GO_BIN) get github.com/gobuffalo/release
9 $(GO_BIN) get github.com/gobuffalo/packr/packr
10 $(GO_BIN) get -tags ${TAGS} -t ./...
11 $(GO_BIN) mod tidy
12
13 build:
14 packr
15 $(GO_BIN) build -v .
16
17 test:
18 packr
19 $(GO_BIN) test -tags ${TAGS} ./...
20
21 ci-test: deps
22 $(GO_BIN) test -tags ${TAGS} -race ./...
23
24 lint:
25 gometalinter --vendor ./... --deadline=1m --skip=internal
26
27 update:
28 $(GO_BIN) get -u -tags ${TAGS}
29 $(GO_BIN) mod tidy
30 packr
31 make test
32 make install
33 $(GO_BIN) mod tidy
34
35 release-test:
36 $(GO_BIN) test -tags ${TAGS} -race ./...
37
38 release:
39 release -y -f version.go
0 package oncer
1
2 import (
3 "fmt"
4 "io"
5 "os"
6 )
7
8 const deprecated = "DEPRECATED"
9
10 var deprecationWriter io.Writer = os.Stdout
11
12 func Deprecate(depth int, name string, msg string) {
13 Do(deprecated+name, func() {
14 fmt.Fprintf(deprecationWriter, "[%s] %s has been deprecated.\n", deprecated, name)
15 if len(msg) > 0 {
16 fmt.Fprintf(deprecationWriter, "\t%s\n", msg)
17 }
18 })
19 }
0 //+build !debug
1
2 package oncer
3
4 func log(name string, fn func()) func() {
5 return fn
6 }
0 //+build debug
1
2 package oncer
3
4 import (
5 "fmt"
6 "time"
7 )
8
9 func log(name string, fn func()) func() {
10 return func() {
11 start := time.Now()
12 if len(name) > 80 {
13 name = name[(len(name) - 80):]
14 }
15 defer fmt.Println(name, time.Now().Sub(start))
16 fn()
17 }
18 }
0 package oncer
1
2 import (
3 "sync"
4 )
5
6 var onces = &sync.Map{}
7
8 func Do(name string, fn func()) {
9 o, _ := onces.LoadOrStore(name, &sync.Once{})
10 if once, ok := o.(*sync.Once); ok {
11 once.Do(log(name, fn))
12 }
13 }
14
15 func Reset(names ...string) {
16 if len(names) == 0 {
17 onces = &sync.Map{}
18 return
19 }
20
21 for _, n := range names {
22 onces.Delete(n)
23 onces.Delete(deprecated + n)
24 }
25 }
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
28 .idea/
0 {
1 "Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"]
2 }
0 language: go
1
2 sudo: false
3
4 matrix:
5 include:
6 - go: "1.9.x"
7 - go: "1.10.x"
8 - go: "1.11.x"
9 env:
10 - GO111MODULE=off
11 - go: "1.11.x"
12 env:
13 - GO111MODULE=on
14 - go: "tip"
15 env:
16 - GO111MODULE=off
17 - go: "tip"
18 env:
19 - GO111MODULE=on
20 allow_failures:
21 - go: "tip"
22
23 install: make deps
24
25 script: make ci-test
0 The MIT License (MIT)
1
2 Copyright (c) 2018 Mark Bates
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
0 TAGS ?= "sqlite"
1 GO_BIN ?= go
2
3 install:
4 packr
5 $(GO_BIN) install -tags ${TAGS} -v .
6 make tidy
7
8 tidy:
9 ifeq ($(GO111MODULE),on)
10 $(GO_BIN) mod tidy
11 else
12 echo skipping go mod tidy
13 endif
14
15 deps:
16 $(GO_BIN) get github.com/gobuffalo/release
17 $(GO_BIN) get github.com/gobuffalo/packr/packr
18 $(GO_BIN) get -tags ${TAGS} -t ./...
19 make tidy
20
21 build:
22 packr
23 $(GO_BIN) build -v .
24 make tidy
25
26 test:
27 packr
28 $(GO_BIN) test -tags ${TAGS} ./...
29 make tidy
30
31 ci-test:
32 $(GO_BIN) test -tags ${TAGS} -race ./...
33 make tidy
34
35 lint:
36 gometalinter --vendor ./... --deadline=1m --skip=internal
37 make tidy
38
39 update:
40 $(GO_BIN) get -u -tags ${TAGS}
41 make tidy
42 packr
43 make test
44 make install
45 make tidy
46
47 release-test:
48 $(GO_BIN) test -tags ${TAGS} -race ./...
49 make tidy
50
51 release:
52 make tidy
53 release -y -f version.go
54 make tidy
0 package safe
1
2 import (
3 "errors"
4 "fmt"
5 )
6
7 // Run the function safely knowing that if it panics
8 // the panic will be caught and returned as an error
9 func Run(fn func()) (err error) {
10 return RunE(func() error {
11 fn()
12 return nil
13 })
14 }
15
16 // Run the function safely knowing that if it panics
17 // the panic will be caught and returned as an error
18 func RunE(fn func() error) (err error) {
19 defer func() {
20 if err != nil {
21 return
22 }
23 if ex := recover(); ex != nil {
24 if e, ok := ex.(error); ok {
25 err = e
26 return
27 }
28 err = errors.New(fmt.Sprint(ex))
29 }
30 }()
31 return fn()
32 }
0 # github.com/markbates/safe Stands on the Shoulders of Giants
1
2 github.com/markbates/safe does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants this project would not be possible. Please make sure to check them out and thank them for all of their hard work.
3
4 Thank you to the following **GIANTS**:
5
6
7 * [github.com/markbates/safe](https://godoc.org/github.com/markbates/safe)
0 package safe
1
2 const Version = "v1.0.1"
0 package jam
1
2 import (
3 "context"
4 "encoding/json"
5 "io"
6 "os"
7 "os/exec"
8 "time"
9
10 "github.com/gobuffalo/packr/v2/jam/parser"
11 "github.com/gobuffalo/packr/v2/jam/store"
12 "github.com/gobuffalo/packr/v2/plog"
13 )
14
15 // PackOptions ...
16 type PackOptions struct {
17 IgnoreImports bool
18 Legacy bool
19 StoreCmd string
20 Roots []string
21 RootsOptions *parser.RootsOptions
22 }
23
24 // Pack the roots given + PWD
25 func Pack(opts PackOptions) error {
26 pwd, err := os.Getwd()
27 if err != nil {
28 return err
29 }
30
31 opts.Roots = append(opts.Roots, pwd)
32 if err := Clean(opts.Roots...); err != nil {
33 return err
34 }
35
36 if opts.RootsOptions == nil {
37 opts.RootsOptions = &parser.RootsOptions{}
38 }
39
40 if opts.IgnoreImports {
41 opts.RootsOptions.IgnoreImports = true
42 }
43
44 p, err := parser.NewFromRoots(opts.Roots, opts.RootsOptions)
45 if err != nil {
46 return err
47 }
48 boxes, err := p.Run()
49 if err != nil {
50 return err
51 }
52
53 // reduce boxes - remove ones we don't want
54 // MB: current assumption is we want all these
55 // boxes, just adding a comment suggesting they're
56 // might be a reason to exclude some
57
58 plog.Logger.Debugf("found %d boxes", len(boxes))
59
60 if len(opts.StoreCmd) != 0 {
61 return ShellPack(opts, boxes)
62 }
63
64 var st store.Store = store.NewDisk("", "")
65
66 if opts.Legacy {
67 st = store.NewLegacy()
68 }
69
70 for _, b := range boxes {
71 if b.Name == store.DISK_GLOBAL_KEY {
72 continue
73 }
74 if err := st.Pack(b); err != nil {
75 return err
76 }
77 }
78 if cl, ok := st.(io.Closer); ok {
79 return cl.Close()
80 }
81 return nil
82 }
83
84 // ShellPack ...
85 func ShellPack(opts PackOptions, boxes parser.Boxes) error {
86 b, err := json.Marshal(boxes)
87 if err != nil {
88 return err
89 }
90 ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
91 defer cancel()
92 c := exec.CommandContext(ctx, opts.StoreCmd, string(b))
93 c.Stdout = os.Stdout
94 c.Stderr = os.Stderr
95 return c.Run()
96
97 }
98
99 // Clean ...
100 func Clean(args ...string) error {
101 pwd, err := os.Getwd()
102 if err != nil {
103 return err
104 }
105 args = append(args, pwd)
106 for _, root := range args {
107 if err := store.Clean(root); err != nil {
108 return err
109 }
110 }
111 return nil
112 }
0 package q
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("bob", "dylan")
6 }
0 package q
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("tom", "petty")
6 packr.NewBox("./heartbreakers")
7 }
0 package q
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("aretha", "franklin")
6 }
0 package main
1
2 func main() {
3
4 }
0 package parser
1
2 import (
3 "encoding/json"
4 "fmt"
5 )
6
7 // FromArgs is useful when writing packr store-cmd binaries.
8 /*
9 package main
10
11 import (
12 "log"
13 "os"
14
15 "github.com/gobuffalo/packr/v2/jam/parser"
16 "github.com/markbates/s3packr/s3packr"
17 )
18
19 func main() {
20 err := parser.FromArgs(os.Args[1:], func(boxes parser.Boxes) error {
21 for _, box := range boxes {
22 s3 := s3packr.New(box)
23 if err := s3.Pack(box); err != nil {
24 return err
25 }
26 }
27 return nil
28 })
29
30 if err != nil {
31 log.Fatal(err)
32 }
33 }
34 */
35 func FromArgs(args []string, fn func(Boxes) error) error {
36 if len(args) == 0 {
37 return fmt.Errorf("you must supply a payload")
38 }
39 payload := args[0]
40 if len(payload) == 0 {
41 return fmt.Errorf("you must supply a payload")
42 }
43
44 var boxes Boxes
45 err := json.Unmarshal([]byte(payload), &boxes)
46 if err != nil {
47 return err
48 }
49
50 return fn(boxes)
51 }
0 package parser
1
2 import (
3 "encoding/json"
4 "os"
5 "strings"
6 )
7
8 // Box found while parsing a file
9 type Box struct {
10 Name string // name of the box
11 Path string // relative path of folder NewBox("./templates")
12 AbsPath string // absolute path of Path
13 Package string // the package name the box was found in
14 PWD string // the PWD when the parser was run
15 PackageDir string // the absolute path of the package where the box was found
16 }
17
18 type Boxes []*Box
19
20 // String - json returned
21 func (b Box) String() string {
22 x, _ := json.Marshal(b)
23 return string(x)
24 }
25
26 // NewBox stub from the name and the path provided
27 func NewBox(name string, path string) *Box {
28 if len(name) == 0 {
29 name = path
30 }
31 name = strings.Replace(name, "\"", "", -1)
32 pwd, _ := os.Getwd()
33 box := &Box{
34 Name: name,
35 Path: path,
36 PWD: pwd,
37 }
38 return box
39 }
0 package parser
1
2 import (
3 "bytes"
4 "io"
5 "io/ioutil"
6 "path/filepath"
7 )
8
9 // File that is to be parsed
10 type File struct {
11 io.Reader
12 Path string
13 AbsPath string
14 }
15
16 // Name of the file "app.go"
17 func (f File) Name() string {
18 return f.Path
19 }
20
21 // String returns the contents of the reader
22 func (f *File) String() string {
23 src, _ := ioutil.ReadAll(f)
24 f.Reader = bytes.NewReader(src)
25 return string(src)
26 }
27
28 func (s *File) Write(p []byte) (int, error) {
29 bb := &bytes.Buffer{}
30 i, err := bb.Write(p)
31 s.Reader = bb
32 return i, err
33 }
34
35 // NewFile takes the name of the file you want to
36 // write to and a reader to reader from
37 func NewFile(path string, r io.Reader) *File {
38 if r == nil {
39 r = &bytes.Buffer{}
40 }
41 if seek, ok := r.(io.Seeker); ok {
42 seek.Seek(0, 0)
43 }
44 abs := path
45 if !filepath.IsAbs(path) {
46 abs, _ = filepath.Abs(path)
47 }
48 return &File{
49 Reader: r,
50 Path: path,
51 AbsPath: abs,
52 }
53 }
0 package parser
1
2 import (
3 "fmt"
4 "go/build"
5 "path/filepath"
6 "strings"
7 "time"
8
9 "github.com/gobuffalo/packr/v2/plog"
10 "github.com/karrick/godirwalk"
11 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/errx"
12 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/oncer"
13 )
14
15 type finder struct {
16 id time.Time
17 }
18
19 func (fd *finder) key(m, dir string) string {
20 return fmt.Sprintf("%s-*parser.finder#%s-%s", fd.id, m, dir)
21 }
22
23 // findAllGoFiles *.go files for a given diretory
24 func (fd *finder) findAllGoFiles(dir string) ([]string, error) {
25 var err error
26 var names []string
27 oncer.Do(fd.key("findAllGoFiles", dir), func() {
28 plog.Debug(fd, "findAllGoFiles", "dir", dir)
29
30 callback := func(path string, do *godirwalk.Dirent) error {
31 ext := filepath.Ext(path)
32 if ext != ".go" {
33 return nil
34 }
35 names = append(names, path)
36 return nil
37 }
38 err = godirwalk.Walk(dir, &godirwalk.Options{
39 FollowSymbolicLinks: true,
40 Callback: callback,
41 })
42 })
43
44 return names, err
45 }
46
47 func (fd *finder) findAllGoFilesImports(dir string) ([]string, error) {
48 var err error
49 var names []string
50 oncer.Do(fd.key("findAllGoFilesImports", dir), func() {
51 ctx := build.Default
52
53 if len(ctx.SrcDirs()) == 0 {
54 err = fmt.Errorf("no src directories found")
55 return
56 }
57
58 pkg, err := ctx.ImportDir(dir, 0)
59 if strings.HasPrefix(pkg.ImportPath, "github.com/gobuffalo/packr") {
60 return
61 }
62
63 if err != nil {
64 if !strings.Contains(err.Error(), "cannot find package") {
65 if _, ok := errx.Unwrap(err).(*build.NoGoError); !ok {
66 err = err
67 return
68 }
69 }
70 }
71
72 if pkg.Goroot {
73 return
74 }
75 if len(pkg.GoFiles) <= 0 {
76 return
77 }
78
79 plog.Debug(fd, "findAllGoFilesImports", "dir", dir)
80
81 names, _ = fd.findAllGoFiles(dir)
82 for _, n := range pkg.GoFiles {
83 names = append(names, filepath.Join(pkg.Dir, n))
84 }
85 for _, imp := range pkg.Imports {
86 if len(ctx.SrcDirs()) == 0 {
87 continue
88 }
89 d := ctx.SrcDirs()[len(ctx.SrcDirs())-1]
90 ip := filepath.Join(d, imp)
91 n, err := fd.findAllGoFilesImports(ip)
92 if err != nil && len(n) != 0 {
93 names = n
94 return
95 }
96 names = append(names, n...)
97 }
98 })
99 return names, err
100 }
0 package parser
1
2 import (
3 "go/ast"
4 "go/parser"
5 "go/token"
6 "io"
7 "strings"
8
9 "github.com/gobuffalo/packd"
10 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/errx"
11 )
12
13 // ParsedFile ...
14 type ParsedFile struct {
15 File packd.SimpleFile
16 FileSet *token.FileSet
17 Ast *ast.File
18 Lines []string
19 }
20
21 // ParseFileMode ...
22 func ParseFileMode(gf packd.SimpleFile, mode parser.Mode) (ParsedFile, error) {
23 pf := ParsedFile{
24 FileSet: token.NewFileSet(),
25 File: gf,
26 }
27
28 src := gf.String()
29 f, err := parser.ParseFile(pf.FileSet, gf.Name(), src, mode)
30 if err != nil && errx.Unwrap(err) != io.EOF {
31 return pf, err
32 }
33 pf.Ast = f
34
35 pf.Lines = strings.Split(src, "\n")
36 return pf, nil
37 }
38
39 // ParseFile ...
40 func ParseFile(gf packd.SimpleFile) (ParsedFile, error) {
41 return ParseFileMode(gf, 0)
42 }
0 package parser
1
2 import (
3 "os"
4 "sort"
5 "strings"
6
7 "github.com/gobuffalo/packr/v2/plog"
8 )
9
10 // Parser to find boxes
11 type Parser struct {
12 Prospects []*File // a list of files to check for boxes
13 IgnoreImports bool
14 }
15
16 // Run the parser and run any boxes found
17 func (p *Parser) Run() (Boxes, error) {
18 var boxes Boxes
19 for _, pros := range p.Prospects {
20 plog.Debug(p, "Run", "parsing", pros.Name())
21 v := NewVisitor(pros)
22 pbr, err := v.Run()
23 if err != nil {
24 return boxes, err
25 }
26 for _, b := range pbr {
27 plog.Debug(p, "Run", "file", pros.Name(), "box", b.Name)
28 boxes = append(boxes, b)
29 }
30 }
31
32 pwd, _ := os.Getwd()
33 sort.Slice(boxes, func(a, b int) bool {
34 b1 := boxes[a]
35 return !strings.HasPrefix(b1.AbsPath, pwd)
36 })
37 return boxes, nil
38 }
39
40 // New Parser from a list of File
41 func New(prospects ...*File) *Parser {
42 return &Parser{
43 Prospects: prospects,
44 }
45 }
0 package parser_test
1
2 import (
3 "fmt"
4 "strings"
5 "testing"
6
7 "github.com/gobuffalo/packr/v2/jam/parser"
8 "github.com/gobuffalo/packr/v2/jam/store"
9 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/oncer"
10 "github.com/stretchr/testify/require"
11 )
12
13 func init() {
14 parser.DefaultIgnoredFolders = []string{"vendor", ".git", "node_modules", ".idea"}
15 }
16
17 func Test_Parser_Run(t *testing.T) {
18 r := require.New(t)
19
20 f1 := parser.NewFile("a/a.x", strings.NewReader(fmt.Sprintf(basicGoTmpl, "a")))
21 f2 := parser.NewFile("b/b.x", strings.NewReader(fmt.Sprintf(basicGoTmpl, "b")))
22
23 p := parser.New(f1, f2)
24 boxes, err := p.Run()
25 r.NoError(err)
26
27 r.Len(boxes, 4)
28 }
29
30 func Test_NewFrom_Roots_Imports(t *testing.T) {
31 r := require.New(t)
32 store.Clean("./_fixtures")
33 p, err := parser.NewFromRoots([]string{"./_fixtures/new_from_roots"}, &parser.RootsOptions{})
34 r.NoError(err)
35
36 boxes, err := p.Run()
37 r.NoError(err)
38 r.Len(boxes, 3)
39 }
40
41 func Test_NewFrom_Roots_Disk(t *testing.T) {
42 r := require.New(t)
43 oncer.Reset()
44 store.Clean("./_fixtures")
45 p, err := parser.NewFromRoots([]string{"./_fixtures/new_from_roots"}, &parser.RootsOptions{
46 IgnoreImports: true,
47 })
48 r.NoError(err)
49
50 boxes, err := p.Run()
51 r.NoError(err)
52 r.Len(boxes, 3)
53 }
54
55 const basicGoTmpl = `package %s
56
57 import "github.com/gobuffalo/packr/v2"
58
59 func init() {
60 packr.New("elvis", "./presley")
61 packr.NewBox("./buddy-holly")
62 }
63 `
0 package parser
1
2 import (
3 "os"
4 "path/filepath"
5 "strings"
6
7 "github.com/gobuffalo/packr/v2/file/resolver"
8 "github.com/gobuffalo/packr/v2/plog"
9 )
10
11 var DefaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "_fixtures", "testdata"}
12
13 func IsProspect(path string, ignore ...string) (status bool) {
14 // plog.Debug("parser", "IsProspect", "path", path, "ignore", ignore)
15 defer func() {
16 if status {
17 plog.Debug("parser", "IsProspect (TRUE)", "path", path, "status", status)
18 }
19 }()
20 if path == "." {
21 return true
22 }
23
24 ext := filepath.Ext(path)
25 dir := filepath.Dir(path)
26
27 fi, _ := os.Stat(path)
28 if fi != nil {
29 if fi.IsDir() {
30 dir = filepath.Base(path)
31 } else {
32 if len(ext) > 0 {
33 dir = filepath.Base(filepath.Dir(path))
34 }
35 }
36 }
37
38 path = strings.ToLower(path)
39 dir = strings.ToLower(dir)
40
41 if strings.HasSuffix(path, "-packr.go") {
42 return false
43 }
44
45 if strings.HasSuffix(path, "_test.go") {
46 return false
47 }
48
49 ignore = append(ignore, DefaultIgnoredFolders...)
50 for i, x := range ignore {
51 ignore[i] = strings.TrimSpace(strings.ToLower(x))
52 }
53
54 parts := strings.Split(resolver.OsPath(path), string(filepath.Separator))
55 if len(parts) == 0 {
56 return false
57 }
58
59 for _, i := range ignore {
60 for _, p := range parts {
61 if strings.HasPrefix(p, i) {
62 return false
63 }
64 }
65 }
66
67 un := filepath.Base(path)
68 if len(ext) != 0 {
69 un = filepath.Base(filepath.Dir(path))
70 }
71 if strings.HasPrefix(un, "_") {
72 return false
73 }
74
75 return ext == ".go"
76 }
0 package parser
1
2 import (
3 "testing"
4
5 "github.com/stretchr/testify/require"
6 )
7
8 func Test_IsProspect(t *testing.T) {
9 table := []struct {
10 path string
11 pass bool
12 }{
13 {"foo/.git/config", false},
14 {"foo/.git/baz.go", false},
15 {"a.go", true},
16 {".", true},
17 {"a/b.go", true},
18 {"a/b_test.go", false},
19 {"a/b-packr.go", false},
20 {"a/vendor/b.go", false},
21 {"a/_c/c.go", false},
22 {"a/_c/e/fe/f/c.go", false},
23 {"a/d/_d.go", false},
24 {"a/d/", false},
25 }
26
27 for _, tt := range table {
28 t.Run(tt.path, func(st *testing.T) {
29 r := require.New(st)
30 if tt.pass {
31 r.True(IsProspect(tt.path, ".", "_"))
32 } else {
33 r.False(IsProspect(tt.path, ".", "_"))
34 }
35 })
36 }
37 }
0 package parser
1
2 import (
3 "bytes"
4 "encoding/json"
5 "io/ioutil"
6 "os"
7 "path/filepath"
8 "time"
9
10 "github.com/gobuffalo/packr/v2/plog"
11 "github.com/karrick/godirwalk"
12 )
13
14 type RootsOptions struct {
15 IgnoreImports bool
16 Ignores []string
17 }
18
19 func (r RootsOptions) String() string {
20 x, _ := json.Marshal(r)
21 return string(x)
22 }
23
24 // NewFromRoots scans the file roots provided and returns a
25 // new Parser containing the prospects
26 func NewFromRoots(roots []string, opts *RootsOptions) (*Parser, error) {
27 if opts == nil {
28 opts = &RootsOptions{}
29 }
30
31 if len(roots) == 0 {
32 pwd, _ := os.Getwd()
33 roots = append(roots, pwd)
34 }
35 p := New()
36 plog.Debug(p, "NewFromRoots", "roots", roots, "options", opts)
37 callback := func(path string, de *godirwalk.Dirent) error {
38 if IsProspect(path, opts.Ignores...) {
39 if de.IsDir() {
40 return nil
41 }
42 roots = append(roots, path)
43 return nil
44 }
45 if de.IsDir() {
46 return filepath.SkipDir
47 }
48 return nil
49 }
50 wopts := &godirwalk.Options{
51 FollowSymbolicLinks: true,
52 Callback: callback,
53 }
54 for _, root := range roots {
55 plog.Debug(p, "NewFromRoots", "walking", root)
56 err := godirwalk.Walk(root, wopts)
57 if err != nil {
58 return p, err
59 }
60 }
61
62 dd := map[string]string{}
63 fd := &finder{id: time.Now()}
64 for _, r := range roots {
65 var names []string
66 if opts.IgnoreImports {
67 names, _ = fd.findAllGoFiles(r)
68 } else {
69 names, _ = fd.findAllGoFilesImports(r)
70 }
71 for _, n := range names {
72 if IsProspect(n) {
73 plog.Debug(p, "NewFromRoots", "mapping", n)
74 dd[n] = n
75 }
76 }
77 }
78 for path := range dd {
79 plog.Debug(p, "NewFromRoots", "reading file", path)
80 b, err := ioutil.ReadFile(path)
81 if err != nil {
82 return nil, err
83 }
84 p.Prospects = append(p.Prospects, NewFile(path, bytes.NewReader(b)))
85 }
86 plog.Debug(p, "NewFromRoots", "found prospects", len(p.Prospects))
87 return p, nil
88 }
0 package parser
1
2 import (
3 "fmt"
4 "go/ast"
5 "os"
6 "path/filepath"
7 "sort"
8 "strings"
9
10 "github.com/gobuffalo/packd"
11 )
12
13 type Visitor struct {
14 File packd.SimpleFile
15 Package string
16 boxes map[string]*Box
17 errors []error
18 }
19
20 func NewVisitor(f *File) *Visitor {
21 return &Visitor{
22 File: f,
23 boxes: map[string]*Box{},
24 errors: []error{},
25 }
26 }
27
28 func (v *Visitor) Run() (Boxes, error) {
29 var boxes Boxes
30 pf, err := ParseFile(v.File)
31 if err != nil {
32 return boxes, err
33 }
34
35 v.Package = pf.Ast.Name.Name
36 ast.Walk(v, pf.Ast)
37
38 for _, vb := range v.boxes {
39 boxes = append(boxes, vb)
40 }
41
42 sort.Slice(boxes, func(i, j int) bool {
43 return boxes[i].Name < boxes[j].Name
44 })
45
46 if len(v.errors) > 0 {
47 s := make([]string, len(v.errors))
48 for i, e := range v.errors {
49 s[i] = e.Error()
50 }
51 return boxes, err
52 }
53 return boxes, nil
54 }
55
56 func (v *Visitor) Visit(node ast.Node) ast.Visitor {
57 if node == nil {
58 return v
59 }
60 if err := v.eval(node); err != nil {
61 v.errors = append(v.errors, err)
62 }
63
64 return v
65 }
66
67 func (v *Visitor) eval(node ast.Node) error {
68 switch t := node.(type) {
69 case *ast.CallExpr:
70 return v.evalExpr(t)
71 case *ast.Ident:
72 return v.evalIdent(t)
73 case *ast.GenDecl:
74 for _, n := range t.Specs {
75 if err := v.eval(n); err != nil {
76 return err
77 }
78 }
79 case *ast.FuncDecl:
80 if t.Body == nil {
81 return nil
82 }
83 for _, b := range t.Body.List {
84 if err := v.evalStmt(b); err != nil {
85 return err
86 }
87 }
88 return nil
89 case *ast.ValueSpec:
90 for _, e := range t.Values {
91 if err := v.evalExpr(e); err != nil {
92 return err
93 }
94 }
95 }
96 return nil
97 }
98
99 func (v *Visitor) evalStmt(stmt ast.Stmt) error {
100 switch t := stmt.(type) {
101 case *ast.ExprStmt:
102 return v.evalExpr(t.X)
103 case *ast.AssignStmt:
104 for _, e := range t.Rhs {
105 if err := v.evalArgs(e); err != nil {
106 return err
107 }
108 }
109 }
110 return nil
111 }
112
113 func (v *Visitor) evalExpr(expr ast.Expr) error {
114 switch t := expr.(type) {
115 case *ast.CallExpr:
116 if t.Fun == nil {
117 return nil
118 }
119 for _, a := range t.Args {
120 switch at := a.(type) {
121 case *ast.CallExpr:
122 if sel, ok := t.Fun.(*ast.SelectorExpr); ok {
123 return v.evalSelector(at, sel)
124 }
125
126 if err := v.evalArgs(at); err != nil {
127 return err
128 }
129 case *ast.CompositeLit:
130 for _, e := range at.Elts {
131 if err := v.evalExpr(e); err != nil {
132 return err
133 }
134 }
135 }
136 }
137 if ft, ok := t.Fun.(*ast.SelectorExpr); ok {
138 return v.evalSelector(t, ft)
139 }
140 case *ast.KeyValueExpr:
141 return v.evalExpr(t.Value)
142 }
143 return nil
144 }
145
146 func (v *Visitor) evalArgs(expr ast.Expr) error {
147 switch at := expr.(type) {
148 case *ast.CompositeLit:
149 for _, e := range at.Elts {
150 if err := v.evalExpr(e); err != nil {
151 return err
152 }
153 }
154 case *ast.CallExpr:
155 if at.Fun == nil {
156 return nil
157 }
158 switch st := at.Fun.(type) {
159 case *ast.SelectorExpr:
160 if err := v.evalSelector(at, st); err != nil {
161 return err
162 }
163 case *ast.Ident:
164 return v.evalIdent(st)
165 }
166 for _, a := range at.Args {
167 if err := v.evalArgs(a); err != nil {
168 return err
169 }
170 }
171 }
172 return nil
173 }
174
175 func (v *Visitor) evalSelector(expr *ast.CallExpr, sel *ast.SelectorExpr) error {
176 x, ok := sel.X.(*ast.Ident)
177 if !ok {
178 return nil
179 }
180 if x.Name == "packr" {
181 switch sel.Sel.Name {
182 case "New":
183 if len(expr.Args) != 2 {
184 return fmt.Errorf("`New` requires two arguments")
185 }
186
187 zz := func(e ast.Expr) (string, error) {
188 switch at := e.(type) {
189 case *ast.Ident:
190 switch at.Obj.Kind {
191 case ast.Var:
192 if as, ok := at.Obj.Decl.(*ast.AssignStmt); ok {
193 return v.fromVariable(as)
194 }
195 case ast.Con:
196 if vs, ok := at.Obj.Decl.(*ast.ValueSpec); ok {
197 return v.fromConstant(vs)
198 }
199 }
200 return "", v.evalIdent(at)
201 case *ast.BasicLit:
202 return at.Value, nil
203 case *ast.CallExpr:
204 return "", v.evalExpr(at)
205 }
206 return "", fmt.Errorf("can't handle %T", e)
207 }
208
209 k1, err := zz(expr.Args[0])
210 if err != nil {
211 return err
212 }
213 k2, err := zz(expr.Args[1])
214 if err != nil {
215 return err
216 }
217 v.addBox(k1, k2)
218
219 return nil
220 case "NewBox":
221 for _, e := range expr.Args {
222 switch at := e.(type) {
223 case *ast.Ident:
224 switch at.Obj.Kind {
225 case ast.Var:
226 if as, ok := at.Obj.Decl.(*ast.AssignStmt); ok {
227 v.addVariable("", as)
228 }
229 case ast.Con:
230 if vs, ok := at.Obj.Decl.(*ast.ValueSpec); ok {
231 v.addConstant("", vs)
232 }
233 }
234 return v.evalIdent(at)
235 case *ast.BasicLit:
236 v.addBox("", at.Value)
237 case *ast.CallExpr:
238 return v.evalExpr(at)
239 }
240 }
241 }
242 }
243
244 return nil
245 }
246
247 func (v *Visitor) evalIdent(i *ast.Ident) error {
248 if i.Obj == nil {
249 return nil
250 }
251 if s, ok := i.Obj.Decl.(*ast.AssignStmt); ok {
252 return v.evalStmt(s)
253 }
254 return nil
255 }
256
257 func (v *Visitor) addBox(name string, path string) {
258 if len(name) == 0 {
259 name = path
260 }
261 name = strings.Replace(name, "\"", "", -1)
262 path = strings.Replace(path, "\"", "", -1)
263 abs := path
264 if _, ok := v.boxes[name]; !ok {
265 box := NewBox(name, path)
266 box.Package = v.Package
267
268 pd := filepath.Dir(v.File.Name())
269 pwd, _ := os.Getwd()
270 if !filepath.IsAbs(pd) {
271 pd = filepath.Join(pwd, pd)
272 }
273 box.PackageDir = pd
274
275 if !filepath.IsAbs(abs) {
276 abs = filepath.Join(pd, abs)
277 }
278 box.AbsPath = abs
279 v.boxes[name] = box
280 }
281 }
282 func (v *Visitor) fromVariable(as *ast.AssignStmt) (string, error) {
283 if len(as.Rhs) == 1 {
284 if bs, ok := as.Rhs[0].(*ast.BasicLit); ok {
285 return bs.Value, nil
286 }
287 }
288 return "", fmt.Errorf("unable to find value from variable %v", as)
289 }
290
291 func (v *Visitor) addVariable(bn string, as *ast.AssignStmt) error {
292 bv, err := v.fromVariable(as)
293 if err != nil {
294 return nil
295 }
296 if len(bn) == 0 {
297 bn = bv
298 }
299 v.addBox(bn, bv)
300 return nil
301 }
302
303 func (v *Visitor) fromConstant(vs *ast.ValueSpec) (string, error) {
304 if len(vs.Values) == 1 {
305 if bs, ok := vs.Values[0].(*ast.BasicLit); ok {
306 return bs.Value, nil
307 }
308 }
309 return "", fmt.Errorf("unable to find value from constant %v", vs)
310 }
311
312 func (v *Visitor) addConstant(bn string, vs *ast.ValueSpec) error {
313 if len(vs.Values) == 1 {
314 if bs, ok := vs.Values[0].(*ast.BasicLit); ok {
315 bv := bs.Value
316 if len(bn) == 0 {
317 bn = bv
318 }
319 v.addBox(bn, bv)
320 }
321 }
322 return nil
323 }
0 package parser
1
2 import (
3 "strings"
4 "testing"
5
6 "github.com/stretchr/testify/require"
7 )
8
9 func Test_Visitor(t *testing.T) {
10 r := require.New(t)
11 v := NewVisitor(NewFile("example/example.go", strings.NewReader(example)))
12
13 boxes, err := v.Run()
14 r.NoError(err)
15
16 r.Equal("example", v.Package)
17 r.Len(v.errors, 0)
18
19 var act []string
20 for _, b := range boxes {
21 act = append(act, b.Name)
22 }
23
24 exp := []string{"./assets", "./bar", "./constant", "./foo", "./sf", "./templates", "./variable", "beatles"}
25 r.Len(act, len(exp))
26 r.Equal(exp, act)
27 }
28
29 const example = `package example
30
31 import (
32 "github.com/gobuffalo/packr/v2"
33 )
34
35 var a = packr.NewBox("./foo")
36 var pw = packr.New("beatles", "./paperback-writer")
37
38 const constString = "./constant"
39
40 type S struct{}
41
42 func (S) f(packr.Box) {}
43
44 func init() {
45 // packr.NewBox("../idontexists")
46
47 b := "./variable"
48 packr.NewBox(b)
49
50 packr.New("beatles", "./day-tripper")
51
52 packr.NewBox(constString)
53
54 // Cannot work from a function
55 packr.NewBox(strFromFunc())
56
57 // This variable should not be added
58 fromFunc := strFromFunc()
59 packr.NewBox(fromFunc)
60
61 foo("/templates", packr.NewBox("./templates"))
62 packr.NewBox("./assets")
63
64 packr.NewBox("./bar")
65
66 s := S{}
67 s.f(packr.NewBox("./sf"))
68 }
69
70 func strFromFunc() string {
71 return "./fromFunc"
72 }
73
74 func foo(s string, box packr.Box) {}
75 `
0 package q
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("bob", "dylan")
6 }
0 package q
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("tom", "./petty")
6 packr.NewBox("../e/heartbreakers")
7 }
0 package q
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("aretha", "./franklin")
6 }
0 package main
1
2 func main() {
3
4 }
0 package a
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("a-box", "../c")
6 }
0 package b
1
2 import "github.com/gobuffalo/packr/v2"
3
4 func init() {
5 packr.New("b-box", "../c")
6 packr.New("cb-box", "../c")
7 }
0 module foo
1
2 require (
3 github.com/gobuffalo/packr/v2 v2.0.0-rc.2 // indirect
4 golang.org/x/tools v0.0.0-20181116193547-e77c06808af6 // indirect
5 )
0 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
1 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2 github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
3 github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
4 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
5 github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
6 github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
7 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
10 github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
11 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
12 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
13 github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
14 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
15 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
16 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
17 github.com/gobuffalo/buffalo v0.12.8-0.20181004233540-fac9bb505aa8/go.mod h1:sLyT7/dceRXJUxSsE813JTQtA3Eb1vjxWfo/N//vXIY=
18 github.com/gobuffalo/buffalo v0.13.0/go.mod h1:Mjn1Ba9wpIbpbrD+lIDMy99pQ0H0LiddMIIDGse7qT4=
19 github.com/gobuffalo/buffalo-plugins v1.0.2/go.mod h1:pOp/uF7X3IShFHyobahTkTLZaeUXwb0GrUTb9ngJWTs=
20 github.com/gobuffalo/buffalo-plugins v1.0.4/go.mod h1:pWS1vjtQ6uD17MVFWf7i3zfThrEKWlI5+PYLw/NaDB4=
21 github.com/gobuffalo/buffalo-plugins v1.4.3/go.mod h1:uCzTY0woez4nDMdQjkcOYKanngeUVRO2HZi7ezmAjWY=
22 github.com/gobuffalo/buffalo-plugins v1.5.1/go.mod h1:jbmwSZK5+PiAP9cC09VQOrGMZFCa/P0UMlIS3O12r5w=
23 github.com/gobuffalo/buffalo-plugins v1.6.4/go.mod h1:/+N1aophkA2jZ1ifB2O3Y9yGwu6gKOVMtUmJnbg+OZI=
24 github.com/gobuffalo/buffalo-plugins v1.6.5/go.mod h1:0HVkbgrVs/MnPZ/FOseDMVanCTm2RNcdM0PuXcL1NNI=
25 github.com/gobuffalo/buffalo-plugins v1.6.7/go.mod h1:ZGZRkzz2PiKWHs0z7QsPBOTo2EpcGRArMEym6ghKYgk=
26 github.com/gobuffalo/buffalo-plugins v1.6.9 h1:Z4WSEWPSxHMxrxVwCdy9x0QVZjirywhGpZaB9yeCwdc=
27 github.com/gobuffalo/buffalo-plugins v1.6.9/go.mod h1:yYlYTrPdMCz+6/+UaXg5Jm4gN3xhsvsQ2ygVatZV5vw=
28 github.com/gobuffalo/buffalo-pop v1.0.5/go.mod h1:Fw/LfFDnSmB/vvQXPvcXEjzP98Tc+AudyNWUBWKCwQ8=
29 github.com/gobuffalo/envy v1.6.4/go.mod h1:Abh+Jfw475/NWtYMEt+hnJWRiC8INKWibIMyNt1w2Mc=
30 github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
31 github.com/gobuffalo/envy v1.6.6/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
32 github.com/gobuffalo/envy v1.6.7/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
33 github.com/gobuffalo/envy v1.6.8/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
34 github.com/gobuffalo/envy v1.6.9 h1:ShEJ/fUg/wr5qIYmTTOnUQ0sy1yGo+4uYQJNgg753S8=
35 github.com/gobuffalo/envy v1.6.9/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
36 github.com/gobuffalo/events v1.0.3/go.mod h1:Txo8WmqScapa7zimEQIwgiJBvMECMe9gJjsKNPN3uZw=
37 github.com/gobuffalo/events v1.0.7/go.mod h1:z8txf6H9jWhQ5Scr7YPLWg/cgXBRj8Q4uYI+rsVCCSQ=
38 github.com/gobuffalo/events v1.0.8/go.mod h1:A5KyqT1sA+3GJiBE4QKZibse9mtOcI9nw8gGrDdqYGs=
39 github.com/gobuffalo/events v1.1.3/go.mod h1:9yPGWYv11GENtzrIRApwQRMYSbUgCsZ1w6R503fCfrk=
40 github.com/gobuffalo/events v1.1.4/go.mod h1:09/YRRgZHEOts5Isov+g9X2xajxdvOAcUuAHIX/O//A=
41 github.com/gobuffalo/events v1.1.5/go.mod h1:3YUSzgHfYctSjEjLCWbkXP6djH2M+MLaVRzb4ymbAK0=
42 github.com/gobuffalo/events v1.1.7 h1:X+wjuT7c1rZNKqhfevIA30oFCgO5JBlnW6hvAJcv1Vg=
43 github.com/gobuffalo/events v1.1.7/go.mod h1:6fGqxH2ing5XMb3EYRq9LEkVlyPGs4oO/eLzh+S8CxY=
44 github.com/gobuffalo/fizz v1.0.12/go.mod h1:C0sltPxpYK8Ftvf64kbsQa2yiCZY4RZviurNxXdAKwc=
45 github.com/gobuffalo/flect v0.0.0-20180907193754-dc14d8acaf9f/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
46 github.com/gobuffalo/flect v0.0.0-20181002182613-4571df4b1daf/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
47 github.com/gobuffalo/flect v0.0.0-20181007231023-ae7ed6bfe683/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
48 github.com/gobuffalo/flect v0.0.0-20181018182602-fd24a256709f/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
49 github.com/gobuffalo/flect v0.0.0-20181019110701-3d6f0b585514/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
50 github.com/gobuffalo/flect v0.0.0-20181024204909-8f6be1a8c6c2/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
51 github.com/gobuffalo/flect v0.0.0-20181104133451-1f6e9779237a/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
52 github.com/gobuffalo/flect v0.0.0-20181114183036-47375f6d8328 h1:nvA0/snr4wQeCwBYmrbftniJun/kxOjK/Pz3ivb7wis=
53 github.com/gobuffalo/flect v0.0.0-20181114183036-47375f6d8328/go.mod h1:0HvNbHdfh+WOvDSIASqJOSxTOWSxCCUF++k/Y53v9rI=
54 github.com/gobuffalo/genny v0.0.0-20180924032338-7af3a40f2252/go.mod h1:tUTQOogrr7tAQnhajMSH6rv1BVev34H2sa1xNHMy94g=
55 github.com/gobuffalo/genny v0.0.0-20181003150629-3786a0744c5d/go.mod h1:WAd8HmjMVrnkAZbmfgH5dLBUchsZfqzp/WS5sQz+uTM=
56 github.com/gobuffalo/genny v0.0.0-20181005145118-318a41a134cc/go.mod h1:WAd8HmjMVrnkAZbmfgH5dLBUchsZfqzp/WS5sQz+uTM=
57 github.com/gobuffalo/genny v0.0.0-20181007153042-b8de7d566757/go.mod h1:+oG5Ljrw04czAHbPXREwaFojJbpUvcIy4DiOnbEJFTA=
58 github.com/gobuffalo/genny v0.0.0-20181012161047-33e5f43d83a6/go.mod h1:+oG5Ljrw04czAHbPXREwaFojJbpUvcIy4DiOnbEJFTA=
59 github.com/gobuffalo/genny v0.0.0-20181017160347-90a774534246/go.mod h1:+oG5Ljrw04czAHbPXREwaFojJbpUvcIy4DiOnbEJFTA=
60 github.com/gobuffalo/genny v0.0.0-20181024195656-51392254bf53/go.mod h1:o9GEH5gn5sCKLVB5rHFC4tq40rQ3VRUzmx6WwmaqISE=
61 github.com/gobuffalo/genny v0.0.0-20181025145300-af3f81d526b8/go.mod h1:uZ1fFYvdcP8mu0B/Ynarf6dsGvp7QFIpk/QACUuFUVI=
62 github.com/gobuffalo/genny v0.0.0-20181027191429-94d6cfb5c7fc/go.mod h1:x7SkrQQBx204Y+O9EwRXeszLJDTaWN0GnEasxgLrQTA=
63 github.com/gobuffalo/genny v0.0.0-20181027195209-3887b7171c4f/go.mod h1:JbKx8HSWICu5zyqWOa0dVV1pbbXOHusrSzQUprW6g+w=
64 github.com/gobuffalo/genny v0.0.0-20181106193839-7dcb0924caf1/go.mod h1:x61yHxvbDCgQ/7cOAbJCacZQuHgB0KMSzoYcw5debjU=
65 github.com/gobuffalo/genny v0.0.0-20181114215459-0a4decd77f5d h1:mznfLmbY1+EhkTIWhk19fZHuxoOLqZ/wzFUcKr5OGY8=
66 github.com/gobuffalo/genny v0.0.0-20181114215459-0a4decd77f5d/go.mod h1:kN2KZ8VgXF9VIIOj/GM0Eo7YK+un4Q3tTreKOf0q1ng=
67 github.com/gobuffalo/github_flavored_markdown v1.0.4/go.mod h1:uRowCdK+q8d/RF0Kt3/DSalaIXbb0De/dmTqMQdkQ4I=
68 github.com/gobuffalo/github_flavored_markdown v1.0.5/go.mod h1:U0643QShPF+OF2tJvYNiYDLDGDuQmJZXsf/bHOJPsMY=
69 github.com/gobuffalo/github_flavored_markdown v1.0.7/go.mod h1:w93Pd9Lz6LvyQXEG6DktTPHkOtCbr+arAD5mkwMzXLI=
70 github.com/gobuffalo/httptest v1.0.2/go.mod h1:7T1IbSrg60ankme0aDLVnEY0h056g9M1/ZvpVThtB7E=
71 github.com/gobuffalo/licenser v0.0.0-20180924033006-eae28e638a42/go.mod h1:Ubo90Np8gpsSZqNScZZkVXXAo5DGhTb+WYFIjlnog8w=
72 github.com/gobuffalo/licenser v0.0.0-20181025145548-437d89de4f75/go.mod h1:x3lEpYxkRG/XtGCUNkio+6RZ/dlOvLzTI9M1auIwFcw=
73 github.com/gobuffalo/licenser v0.0.0-20181027200154-58051a75da95/go.mod h1:BzhaaxGd1tq1+OLKObzgdCV9kqVhbTulxOpYbvMQWS0=
74 github.com/gobuffalo/logger v0.0.0-20181022175615-46cfb361fc27/go.mod h1:8sQkgyhWipz1mIctHF4jTxmJh1Vxhp7mP8IqbljgJZo=
75 github.com/gobuffalo/logger v0.0.0-20181027144941-73d08d2bb969/go.mod h1:7uGg2duHKpWnN4+YmyKBdLXfhopkAdVM6H3nKbyFbz8=
76 github.com/gobuffalo/logger v0.0.0-20181027193913-9cf4dd0efe46/go.mod h1:7uGg2duHKpWnN4+YmyKBdLXfhopkAdVM6H3nKbyFbz8=
77 github.com/gobuffalo/logger v0.0.0-20181109185836-3feeab578c17 h1:DnrA/oPJXI+mdlhX8LS8Gwj3uiTQhKOZCDAAcWSCYk0=
78 github.com/gobuffalo/logger v0.0.0-20181109185836-3feeab578c17/go.mod h1:oNErH0xLe+utO+OW8ptXMSA5DkiSEDW1u3zGIt8F9Ew=
79 github.com/gobuffalo/makr v1.1.5/go.mod h1:Y+o0btAH1kYAMDJW/TX3+oAXEu0bmSLLoC9mIFxtzOw=
80 github.com/gobuffalo/mapi v1.0.0/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
81 github.com/gobuffalo/mapi v1.0.1 h1:JRuTiZzDEZhBHkFiHTxJkYRT6CbYuL0K/rn+1byJoEA=
82 github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
83 github.com/gobuffalo/meta v0.0.0-20181018155829-df62557efcd3/go.mod h1:XTTOhwMNryif3x9LkTTBO/Llrveezd71u3quLd0u7CM=
84 github.com/gobuffalo/meta v0.0.0-20181018192820-8c6cef77dab3/go.mod h1:E94EPzx9NERGCY69UWlcj6Hipf2uK/vnfrF4QD0plVE=
85 github.com/gobuffalo/meta v0.0.0-20181025145500-3a985a084b0a h1:kROH1vRfBoxH1QIQjINB4qi4TmQTdg2Z/yzrKq1f2qM=
86 github.com/gobuffalo/meta v0.0.0-20181025145500-3a985a084b0a/go.mod h1:YDAKBud2FP7NZdruCSlmTmDOZbVSa6bpK7LJ/A/nlKg=
87 github.com/gobuffalo/mw-basicauth v1.0.3/go.mod h1:dg7+ilMZOKnQFHDefUzUHufNyTswVUviCBgF244C1+0=
88 github.com/gobuffalo/mw-contenttype v0.0.0-20180802152300-74f5a47f4d56/go.mod h1:7EvcmzBbeCvFtQm5GqF9ys6QnCxz2UM1x0moiWLq1No=
89 github.com/gobuffalo/mw-csrf v0.0.0-20180802151833-446ff26e108b/go.mod h1:sbGtb8DmDZuDUQoxjr8hG1ZbLtZboD9xsn6p77ppcHo=
90 github.com/gobuffalo/mw-forcessl v0.0.0-20180802152810-73921ae7a130/go.mod h1:JvNHRj7bYNAMUr/5XMkZaDcw3jZhUZpsmzhd//FFWmQ=
91 github.com/gobuffalo/mw-i18n v0.0.0-20180802152014-e3060b7e13d6/go.mod h1:91AQfukc52A6hdfIfkxzyr+kpVYDodgAeT5cjX1UIj4=
92 github.com/gobuffalo/mw-paramlogger v0.0.0-20181005191442-d6ee392ec72e/go.mod h1:6OJr6VwSzgJMqWMj7TYmRUqzNe2LXu/W1rRW4MAz/ME=
93 github.com/gobuffalo/mw-tokenauth v0.0.0-20181001105134-8545f626c189/go.mod h1:UqBF00IfKvd39ni5+yI5MLMjAf4gX7cDKN/26zDOD6c=
94 github.com/gobuffalo/packd v0.0.0-20181027182251-01ad393492c8/go.mod h1:SmdBdhj6uhOsg1Ui4SFAyrhuc7U4VCildosO5IDJ3lc=
95 github.com/gobuffalo/packd v0.0.0-20181027190505-aafc0d02c411/go.mod h1:SmdBdhj6uhOsg1Ui4SFAyrhuc7U4VCildosO5IDJ3lc=
96 github.com/gobuffalo/packd v0.0.0-20181027194105-7ae579e6d213/go.mod h1:SmdBdhj6uhOsg1Ui4SFAyrhuc7U4VCildosO5IDJ3lc=
97 github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI=
98 github.com/gobuffalo/packd v0.0.0-20181104210303-d376b15f8e96/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI=
99 github.com/gobuffalo/packd v0.0.0-20181111195323-b2e760a5f0ff/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI=
100 github.com/gobuffalo/packd v0.0.0-20181114190715-f25c5d2471d7 h1:7AZMyDyRxIm2cbSXRvUEUJrankvMV1xcAOrrWUWp7yE=
101 github.com/gobuffalo/packd v0.0.0-20181114190715-f25c5d2471d7/go.mod h1:Yf2toFaISlyQrr5TfO3h6DB9pl9mZRmyvBGQb/aQ/pI=
102 github.com/gobuffalo/packr v1.13.7/go.mod h1:KkinLIn/n6+3tVXMwg6KkNvWwVsrRAz4ph+jgpk3Z24=
103 github.com/gobuffalo/packr v1.15.0/go.mod h1:t5gXzEhIviQwVlNx/+3SfS07GS+cZ2hn76WLzPp6MGI=
104 github.com/gobuffalo/packr v1.15.1/go.mod h1:IeqicJ7jm8182yrVmNbM6PR4g79SjN9tZLH8KduZZwE=
105 github.com/gobuffalo/packr v1.19.0/go.mod h1:MstrNkfCQhd5o+Ct4IJ0skWlxN8emOq8DsoT1G98VIU=
106 github.com/gobuffalo/packr v1.20.0 h1:XDHu3L931kHjr0v80vJ9hAxOMavbSpzuwAXDONsMYcM=
107 github.com/gobuffalo/packr v1.20.0/go.mod h1:JDytk1t2gP+my1ig7iI4NcVaXr886+N0ecUga6884zw=
108 github.com/gobuffalo/packr/v2 v2.0.0-rc.2 h1:22PapDc3YjlxFvfJ5ukc47/CwmwSQgZhma2wGf05eC8=
109 github.com/gobuffalo/packr/v2 v2.0.0-rc.2/go.mod h1:4Xjr6aIxzyYQN6TBp/oJZ4L+X17DGfq3dy0DCidBebw=
110 github.com/gobuffalo/plush v3.7.16+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI=
111 github.com/gobuffalo/plush v3.7.20+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI=
112 github.com/gobuffalo/plush v3.7.21+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI=
113 github.com/gobuffalo/plush v3.7.22+incompatible/go.mod h1:rQ4zdtUUyZNqULlc6bqd5scsPfLKfT0+TGMChgduDvI=
114 github.com/gobuffalo/pop v4.8.2+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg=
115 github.com/gobuffalo/pop v4.8.3+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg=
116 github.com/gobuffalo/pop v4.8.4+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg=
117 github.com/gobuffalo/release v1.0.35/go.mod h1:VtHFAKs61vO3wboCec5xr9JPTjYyWYcvaM3lclkc4x4=
118 github.com/gobuffalo/release v1.0.38/go.mod h1:VtHFAKs61vO3wboCec5xr9JPTjYyWYcvaM3lclkc4x4=
119 github.com/gobuffalo/release v1.0.42/go.mod h1:RPs7EtafH4oylgetOJpGP0yCZZUiO4vqHfTHJjSdpug=
120 github.com/gobuffalo/release v1.0.52/go.mod h1:RPs7EtafH4oylgetOJpGP0yCZZUiO4vqHfTHJjSdpug=
121 github.com/gobuffalo/release v1.0.53/go.mod h1:FdF257nd8rqhNaqtDWFGhxdJ/Ig4J7VcS3KL7n/a+aA=
122 github.com/gobuffalo/release v1.0.54/go.mod h1:Pe5/RxRa/BE8whDpGfRqSI7D1a0evGK1T4JDm339tJc=
123 github.com/gobuffalo/release v1.0.61/go.mod h1:mfIO38ujUNVDlBziIYqXquYfBF+8FDHUjKZgYC1Hj24=
124 github.com/gobuffalo/shoulders v1.0.1/go.mod h1:V33CcVmaQ4gRUmHKwq1fiTXuf8Gp/qjQBUL5tHPmvbA=
125 github.com/gobuffalo/tags v2.0.11+incompatible/go.mod h1:9XmhOkyaB7UzvuY4UoZO4s67q8/xRMVJEaakauVQYeY=
126 github.com/gobuffalo/uuid v2.0.3+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw4cVi1RtSpnwYrxuvkfE=
127 github.com/gobuffalo/uuid v2.0.4+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw4cVi1RtSpnwYrxuvkfE=
128 github.com/gobuffalo/uuid v2.0.5+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw4cVi1RtSpnwYrxuvkfE=
129 github.com/gobuffalo/validate v2.0.3+incompatible/go.mod h1:N+EtDe0J8252BgfzQUChBgfd6L93m9weay53EWFVsMM=
130 github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOreDJznWevcn8NTmQEW5STSBgIkpkjzqXc=
131 github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY=
132 github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
133 github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
134 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
135 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
136 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
137 github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
138 github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
139 github.com/gorilla/sessions v1.1.2/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
140 github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
141 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
142 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
143 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
144 github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
145 github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
146 github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
147 github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
148 github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
149 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
150 github.com/karrick/godirwalk v1.7.5 h1:JQFiMR65pT543bkWP46+k194gS999qo/OYccos9cOXg=
151 github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
152 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
153 github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
154 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
155 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
156 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
157 github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
158 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
159 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
160 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
161 github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
162 github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
163 github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c=
164 github.com/markbates/grift v1.0.4/go.mod h1:wbmtW74veyx+cgfwFhlnnMWqhoz55rnHR47oMXzsyVs=
165 github.com/markbates/hmax v1.0.0/go.mod h1:cOkR9dktiESxIMu+65oc/r/bdY4bE8zZw3OLhLx0X2c=
166 github.com/markbates/inflect v1.0.0/go.mod h1:oTeZL2KHA7CUX6X+fovmK9OvIOFuqu0TwdQrZjLTh88=
167 github.com/markbates/inflect v1.0.1/go.mod h1:uv3UVNBe5qBIfCm8O8Q+DW+S1EopeyINj+Ikhc7rnCk=
168 github.com/markbates/inflect v1.0.3/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs=
169 github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs=
170 github.com/markbates/oncer v0.0.0-20180924031910-e862a676800b/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
171 github.com/markbates/oncer v0.0.0-20180924034138-723ad0170a46/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
172 github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4 h1:Mlji5gkcpzkqTROyE4ZxZ8hN7osunMb2RuGVrbvMvCc=
173 github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
174 github.com/markbates/refresh v1.4.10/go.mod h1:NDPHvotuZmTmesXxr95C9bjlw1/0frJwtME2dzcVKhc=
175 github.com/markbates/safe v1.0.0/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
176 github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
177 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
178 github.com/markbates/sigtx v1.0.0/go.mod h1:QF1Hv6Ic6Ca6W+T+DL0Y/ypborFKyvUY9HmuCD4VeTc=
179 github.com/markbates/willie v1.0.9/go.mod h1:fsrFVWl91+gXpx/6dv715j7i11fYPfZ9ZGfH0DQzY7w=
180 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
181 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
182 github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
183 github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
184 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
185 github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
186 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
187 github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
188 github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
189 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
190 github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
191 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
192 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
193 errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
194 errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
195 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
196 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
197 github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
198 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
199 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
200 github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
201 github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
202 github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
203 github.com/shurcooL/highlight_go v0.0.0-20170515013102-78fb10f4a5f8/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
204 github.com/shurcooL/octicon v0.0.0-20180602230221-c42b0e3b24d9/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
205 github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
206 github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
207 github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
208 github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
209 github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
210 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
211 github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
212 github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
213 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
214 github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
215 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
216 github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
217 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
218 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
219 github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
220 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
221 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
222 github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
223 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
224 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
225 github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
226 github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
227 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
228 golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
229 golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
230 golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
231 golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
232 golang.org/x/crypto v0.0.0-20181024171144-74cb1d3d52f4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
233 golang.org/x/crypto v0.0.0-20181025113841-85e1b3f9139a/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
234 golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
235 golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd h1:VtIkGDhk0ph3t+THbvXHfMZ8QHgsBO39Nh52+74pq7w=
236 golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
237 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
238 golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
239 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
240 golang.org/x/net v0.0.0-20180921000356-2f5d2388922f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
241 golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
242 golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
243 golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
244 golang.org/x/net v0.0.0-20181017193950-04a2e542c03f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
245 golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
246 golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
247 golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
248 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
249 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
250 golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
251 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
252 golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
253 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
254 golang.org/x/sys v0.0.0-20180921163948-d47a0f339242/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
255 golang.org/x/sys v0.0.0-20180927150500-dad3d9fb7b6e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
256 golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
257 golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
258 golang.org/x/sys v0.0.0-20181022134430-8a28ead16f52/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
259 golang.org/x/sys v0.0.0-20181024145615-5cd93ef61a7c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
260 golang.org/x/sys v0.0.0-20181025063200-d989b31c8746/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
261 golang.org/x/sys v0.0.0-20181026064943-731415f00dce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
262 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
263 golang.org/x/sys v0.0.0-20181106135930-3a76605856fd h1:5lx5yH6109ClL0rlBzOj++ZkX/njUT+RVgTO2RMbmZo=
264 golang.org/x/sys v0.0.0-20181106135930-3a76605856fd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
265 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
266 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
267 golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
268 golang.org/x/tools v0.0.0-20181006002542-f60d9635b16a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
269 golang.org/x/tools v0.0.0-20181008205924-a2b3f7f249e9/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
270 golang.org/x/tools v0.0.0-20181013182035-5e66757b835f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
271 golang.org/x/tools v0.0.0-20181017214349-06f26fdaaa28/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
272 golang.org/x/tools v0.0.0-20181024171208-a2dc47679d30/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
273 golang.org/x/tools v0.0.0-20181026183834-f60e5f99f081/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
274 golang.org/x/tools v0.0.0-20181105230042-78dc5bac0cac/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
275 golang.org/x/tools v0.0.0-20181114190951-94339b83286c/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
276 golang.org/x/tools v0.0.0-20181115011154-2a3f5192be2e h1:C6Dd9cORPM5l1agULNKGE7TsHE1f4fKb6u/C03xjFxo=
277 golang.org/x/tools v0.0.0-20181115011154-2a3f5192be2e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
278 golang.org/x/tools v0.0.0-20181116193547-e77c06808af6 h1:eiQyQ1ZGSmM3I3XUf/clCROlBlOlmAUmTJ9l2GjX2GE=
279 golang.org/x/tools v0.0.0-20181116193547-e77c06808af6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
280 google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
281 gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
282 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
283 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
284 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
285 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
286 gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
287 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
288 gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
289 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
290 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
0 package store
1
2 import (
3 "os"
4 "path/filepath"
5 "strings"
6
7 "github.com/gobuffalo/packr/v2/jam/parser"
8 )
9
10 func Clean(root string) error {
11 defer func() {
12 packd := filepath.Join(root, "packrd")
13 os.RemoveAll(packd)
14 }()
15
16 p, err := parser.NewFromRoots([]string{root}, &parser.RootsOptions{})
17 if err != nil {
18 return err
19 }
20
21 boxes, err := p.Run()
22 if err != nil {
23 return err
24 }
25
26 d := NewDisk("", "")
27 for _, box := range boxes {
28 if err := d.Clean(box); err != nil {
29 return err
30 }
31 }
32 return nil
33 }
34
35 func clean(root string) error {
36 if len(root) == 0 {
37 pwd, err := os.Getwd()
38 if err != nil {
39 return err
40 }
41 root = pwd
42 }
43 if _, err := os.Stat(root); err != nil {
44 return nil
45 }
46 defer func() {
47 packd := filepath.Join(root, "packrd")
48 os.RemoveAll(packd)
49 }()
50
51 err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
52 if err != nil {
53 return err
54 }
55 if info.IsDir() {
56 if filepath.Base(path) == "packrd" {
57 os.RemoveAll(path)
58 return filepath.SkipDir
59 }
60 }
61 if strings.HasSuffix(path, "-packr.go") {
62 err := os.RemoveAll(path)
63 if err != nil {
64 return err
65 }
66 }
67 return nil
68 })
69 if err != nil {
70 return err
71 }
72
73 return nil
74 }
0 package store
1
2 import (
3 "bytes"
4 "compress/gzip"
5 "crypto/md5"
6 "fmt"
7 "go/build"
8 "html/template"
9 "io"
10 "io/ioutil"
11 "os"
12 "os/exec"
13 "path"
14 "path/filepath"
15 "sort"
16 "strings"
17 "sync"
18
19 "github.com/gobuffalo/envy"
20 "github.com/gobuffalo/packr/v2/file/resolver/encoding/hex"
21 "github.com/gobuffalo/packr/v2/plog"
22 "github.com/rogpeppe/go-internal/modfile"
23
24 "github.com/gobuffalo/packr/v2/jam/parser"
25 "github.com/karrick/godirwalk"
26 "golang.org/x/sync/errgroup"
27 )
28
29 var _ Store = &Disk{}
30
31 const DISK_GLOBAL_KEY = "__packr_global__"
32
33 type Disk struct {
34 DBPath string
35 DBPackage string
36 global map[string]string
37 boxes map[string]*parser.Box
38 moot *sync.RWMutex
39 }
40
41 func NewDisk(path string, pkg string) *Disk {
42 if len(path) == 0 {
43 path = "packrd"
44 }
45 if len(pkg) == 0 {
46 pkg = "packrd"
47 }
48 if !filepath.IsAbs(path) {
49 path, _ = filepath.Abs(path)
50 }
51 return &Disk{
52 DBPath: path,
53 DBPackage: pkg,
54 global: map[string]string{},
55 boxes: map[string]*parser.Box{},
56 moot: &sync.RWMutex{},
57 }
58 }
59
60 func (d *Disk) FileNames(box *parser.Box) ([]string, error) {
61 path := box.AbsPath
62 if len(box.AbsPath) == 0 {
63 path = box.Path
64 }
65 var names []string
66 if _, err := os.Stat(path); err != nil {
67 return names, nil
68 }
69 err := godirwalk.Walk(path, &godirwalk.Options{
70 FollowSymbolicLinks: true,
71 Callback: func(path string, de *godirwalk.Dirent) error {
72 if !de.IsRegular() {
73 return nil
74 }
75 names = append(names, path)
76 return nil
77 },
78 })
79 return names, err
80 }
81
82 func (d *Disk) Files(box *parser.Box) ([]*parser.File, error) {
83 var files []*parser.File
84 names, err := d.FileNames(box)
85 if err != nil {
86 return files, err
87 }
88 for _, n := range names {
89 b, err := ioutil.ReadFile(n)
90 if err != nil {
91 return files, err
92 }
93 f := parser.NewFile(n, bytes.NewReader(b))
94 files = append(files, f)
95 }
96 return files, nil
97 }
98
99 func (d *Disk) Pack(box *parser.Box) error {
100 plog.Debug(d, "Pack", "box", box.Name)
101 d.boxes[box.Name] = box
102 names, err := d.FileNames(box)
103 if err != nil {
104 return err
105 }
106 for _, n := range names {
107 _, ok := d.global[n]
108 if ok {
109 continue
110 }
111 k := makeKey(box, n)
112 // not in the global, so add it!
113 d.global[n] = k
114 }
115 return nil
116 }
117
118 func (d *Disk) Clean(box *parser.Box) error {
119 root := box.PackageDir
120 if len(root) == 0 {
121 return fmt.Errorf("can't clean an empty box.PackageDir")
122 }
123 plog.Debug(d, "Clean", "box", box.Name, "root", root)
124 return clean(root)
125 }
126
127 type options struct {
128 Package string
129 GlobalFiles map[string]string
130 Boxes []optsBox
131 GK string
132 }
133
134 type optsBox struct {
135 Name string
136 Path string
137 }
138
139 // Close ...
140 func (d *Disk) Close() error {
141 if len(d.boxes) == 0 {
142 return nil
143 }
144
145 xb := &parser.Box{Name: DISK_GLOBAL_KEY}
146 opts := options{
147 Package: d.DBPackage,
148 GlobalFiles: map[string]string{},
149 GK: makeKey(xb, d.DBPath),
150 }
151
152 wg := errgroup.Group{}
153 for k, v := range d.global {
154 func(k, v string) {
155 wg.Go(func() error {
156 bb := &bytes.Buffer{}
157 enc := hex.NewEncoder(bb)
158 zw := gzip.NewWriter(enc)
159 f, err := os.Open(k)
160 if err != nil {
161 return err
162 }
163 defer f.Close()
164 io.Copy(zw, f)
165 if err := zw.Close(); err != nil {
166 return err
167 }
168 d.moot.Lock()
169 opts.GlobalFiles[makeKey(xb, k)] = bb.String()
170 d.moot.Unlock()
171 return nil
172 })
173 }(k, v)
174 }
175
176 if err := wg.Wait(); err != nil {
177 return err
178 }
179
180 for _, b := range d.boxes {
181 ob := optsBox{
182 Name: b.Name,
183 }
184 opts.Boxes = append(opts.Boxes, ob)
185 }
186
187 sort.Slice(opts.Boxes, func(a, b int) bool {
188 return opts.Boxes[a].Name < opts.Boxes[b].Name
189 })
190
191 fm := template.FuncMap{
192 "printBox": func(ob optsBox) (template.HTML, error) {
193 box := d.boxes[ob.Name]
194 if box == nil {
195 return "", fmt.Errorf("could not find box %s", ob.Name)
196 }
197 fn, err := d.FileNames(box)
198 if err != nil {
199 return "", err
200 }
201 if len(fn) == 0 {
202 return "", nil
203 }
204
205 type file struct {
206 Resolver string
207 ForwardPath string
208 }
209
210 tmpl, err := template.New("box.go").Parse(diskGlobalBoxTmpl)
211 if err != nil {
212 return "", err
213 }
214
215 var files []file
216 for _, s := range fn {
217 p := strings.TrimPrefix(s, box.AbsPath)
218 p = strings.TrimPrefix(p, string(filepath.Separator))
219 files = append(files, file{
220 Resolver: strings.Replace(p, "\\", "/", -1),
221 ForwardPath: makeKey(box, s),
222 })
223 }
224 opts := map[string]interface{}{
225 "Box": box,
226 "Files": files,
227 }
228
229 bb := &bytes.Buffer{}
230 if err := tmpl.Execute(bb, opts); err != nil {
231 return "", err
232 }
233 return template.HTML(bb.String()), nil
234 },
235 }
236
237 os.MkdirAll(d.DBPath, 0755)
238 fp := filepath.Join(d.DBPath, "packed-packr.go")
239 global, err := os.Create(fp)
240 if err != nil {
241 return err
242 }
243 defer global.Close()
244
245 tmpl := template.New(fp).Funcs(fm)
246 tmpl, err = tmpl.Parse(diskGlobalTmpl)
247 if err != nil {
248 return err
249 }
250
251 if err := tmpl.Execute(global, opts); err != nil {
252 return err
253 }
254
255 var ip string
256 if envy.Mods() {
257 // Starting in 1.12, we can rely on Go's method for
258 // resolving where go.mod resides. Prior versions will
259 // simply return an empty string.
260 cmd := exec.Command("go", "env", "GOMOD")
261 out, err := cmd.Output()
262 if err != nil {
263 return fmt.Errorf("go.mod cannot be read or does not exist while go module is enabled")
264 }
265 mp := strings.TrimSpace(string(out))
266 if mp == "" {
267 // We are on a prior version of Go; try and do
268 // the resolution ourselves.
269 mp = filepath.Join(filepath.Dir(d.DBPath), "go.mod")
270 if _, err := os.Stat(mp); err != nil {
271 mp = filepath.Join(d.DBPath, "go.mod")
272 }
273 }
274
275 moddata, err := ioutil.ReadFile(mp)
276 if err != nil {
277 return fmt.Errorf("go.mod cannot be read or does not exist while go module is enabled")
278 }
279 ip = modfile.ModulePath(moddata)
280 if ip == "" {
281 return fmt.Errorf("go.mod is malformed")
282 }
283 ip = filepath.Join(ip, strings.TrimPrefix(filepath.Dir(d.DBPath), filepath.Dir(mp)))
284 ip = strings.Replace(ip, "\\", "/", -1)
285 } else {
286 ip = filepath.Dir(d.DBPath)
287 srcs := envy.GoPaths()
288 srcs = append(srcs, build.Default.SrcDirs()...)
289 for _, x := range srcs {
290 ip = strings.TrimPrefix(ip, "/private")
291 ip = strings.TrimPrefix(ip, x)
292 }
293 ip = strings.TrimPrefix(ip, string(filepath.Separator))
294 ip = strings.TrimPrefix(ip, "src")
295 ip = strings.TrimPrefix(ip, string(filepath.Separator))
296
297 ip = strings.Replace(ip, "\\", "/", -1)
298 }
299 ip = path.Join(ip, d.DBPackage)
300
301 for _, n := range opts.Boxes {
302 b := d.boxes[n.Name]
303 if b == nil {
304 continue
305 }
306 p := filepath.Join(b.PackageDir, b.Package+"-packr.go")
307 f, err := os.Create(p)
308 if err != nil {
309 return err
310 }
311 defer f.Close()
312
313 o := struct {
314 Package string
315 Import string
316 }{
317 Package: b.Package,
318 Import: ip,
319 }
320
321 tmpl, err := template.New(p).Parse(diskImportTmpl)
322 if err != nil {
323 return err
324 }
325 if err := tmpl.Execute(f, o); err != nil {
326 return err
327 }
328
329 }
330
331 return nil
332 }
333
334 // resolve file paths (only) for the boxes
335 // compile "global" db
336 // resolve files for boxes to point at global db
337 // write global db to disk (default internal/packr)
338 // write boxes db to disk (default internal/packr)
339 // write -packr.go files in each package (1 per package) that init the global db
340
341 func makeKey(box *parser.Box, path string) string {
342 w := md5.New()
343 fmt.Fprint(w, path)
344 h := hex.EncodeToString(w.Sum(nil))
345 return h
346 }
0 package store
1
2 import (
3 "github.com/gobuffalo/packr/v2"
4 "github.com/gobuffalo/packr/v2/file/resolver"
5 )
6
7 var _ = func() error {
8 const gk = DISK_GLOBAL_KEY
9 g := packr.New(gk, "")
10
11 hgr, err := resolver.NewHexGzip(map[string]string{
12 "4abf3a9b652ecec6b347eb6acb7ce363": "1f8b08000000000000fff2750c72775508cecc2d28cecfe302040000fffffb1d273b0e000000",
13 "5cfc8f95f98237a10affc14a76e3e20b": "1f8b08000000000000fff2757477f7745508cecc2d28cecfe302040000ffffb09167470f000000",
14 "6d8be986fa35821e7e869fbb118e51ba": "1f8b08000000000000fff2f0f7750d5208cecc2d28cecfe302040000fffffb2ef0a60e000000",
15 "99e5497ae5f5988fafafbcd15ed74d22": "1f8b08000000000000fff2f10c765408cecc2d28cecfe302040000ffffab9bc93e0d000000",
16 "bb006aa6261a80f6c52c640f713659c1": "1f8b08000000000000ff72720c0a5108cecc2d28cecfe302040000ffff89742ac20d000000",
17 })
18 if err != nil {
19 return err
20 }
21 g.DefaultResolver = hgr
22 func() {
23 b := packr.New("simpsons", "")
24 b.SetResolver("kids/bart.txt", packr.Pointer{ForwardBox: gk, ForwardPath: "bb006aa6261a80f6c52c640f713659c1"})
25 b.SetResolver("kids/lisa.txt", packr.Pointer{ForwardBox: gk, ForwardPath: "99e5497ae5f5988fafafbcd15ed74d22"})
26 b.SetResolver("kids/maggie.txt", packr.Pointer{ForwardBox: gk, ForwardPath: "5cfc8f95f98237a10affc14a76e3e20b"})
27 b.SetResolver("parents/homer.txt", packr.Pointer{ForwardBox: gk, ForwardPath: "6d8be986fa35821e7e869fbb118e51ba"})
28 b.SetResolver("parents/marge.txt", packr.Pointer{ForwardBox: gk, ForwardPath: "4abf3a9b652ecec6b347eb6acb7ce363"})
29 }()
30 return nil
31 }()
0 package store
1
2 //
3 // import (
4 // "path/filepath"
5 // "strings"
6 // "testing"
7 //
8 // "github.com/gobuffalo/envy"
9 // "github.com/gobuffalo/genny/gentest"
10 // "github.com/gobuffalo/gogen/gomods"
11 // "github.com/gobuffalo/packr/v2"
12 // "github.com/gobuffalo/packr/v2/jam/parser"
13 // "github.com/markbates/oncer"
14 // "github.com/stretchr/testify/require"
15 // )
16 //
17 // func init() {
18 // parser.DefaultIgnoredFolders = []string{"vendor", ".git", "node_modules", ".idea"}
19 // }
20 //
21 // func Test_Disk_Generator(t *testing.T) {
22 // gomods.Disable(func() error {
23 //
24 // r := require.New(t)
25 //
26 // p, err := parser.NewFromRoots([]string{"./_fixtures/disk-pack"}, &parser.RootsOptions{
27 // IgnoreImports: true,
28 // })
29 // r.NoError(err)
30 //
31 // boxes, err := p.Run()
32 // r.NoError(err)
33 //
34 // d := NewDisk(".", "")
35 // for _, b := range boxes {
36 // r.NoError(d.Pack(b))
37 // }
38 //
39 // r.NoError(d.Close())
40 //
41 // res := run.Results()
42 // r.Len(res.Files, 3)
43 //
44 // f := res.Files[0]
45 // r.Equal("a-packr.go", filepath.Base(f.Name()))
46 // r.Contains(f.String(), `import _ "github.com/gobuffalo/packr/v2/jam/packrd"`)
47 // return nil
48 // })
49 // }
50 //
51 // func Test_Disk_Generator_GoMod(t *testing.T) {
52 // oe := envy.Get(gomods.ENV, "off")
53 // _ = envy.MustSet(gomods.ENV, "on")
54 // defer envy.MustSet(gomods.ENV, oe)
55 //
56 // r := require.New(t)
57 //
58 // p, err := parser.NewFromRoots([]string{"./_fixtures/disk-pack"}, &parser.RootsOptions{
59 // IgnoreImports: true,
60 // })
61 // r.NoError(err)
62 //
63 // boxes, err := p.Run()
64 // r.NoError(err)
65 //
66 // d := NewDisk(".", "")
67 // for _, b := range boxes {
68 // r.NoError(d.Pack(b))
69 // }
70 //
71 // run := gentest.NewRunner()
72 // run.WithNew(d.Generator())
73 // r.NoError(run.Run())
74 //
75 // res := run.Results()
76 // r.Len(res.Files, 3)
77 //
78 // f := res.Files[0]
79 // r.Equal("a-packr.go", filepath.Base(f.Name()))
80 // r.Contains(f.String(), `import _ "github.com/gobuffalo/packr/v2/jam/packrd"`)
81 // }
82 //
83 // func Test_Disk_FileNames(t *testing.T) {
84 // r := require.New(t)
85 //
86 // d := &Disk{}
87 //
88 // box := parser.NewBox("Test_Disk_FileNames", "./_fixtures/disk/franklin")
89 // names, err := d.FileNames(box)
90 // r.NoError(err)
91 // r.Len(names, 2)
92 //
93 // r.Equal("aretha.txt", filepath.Base(names[0]))
94 // r.Equal("think.txt", filepath.Base(names[1]))
95 // }
96 //
97 // func Test_Disk_Files(t *testing.T) {
98 // r := require.New(t)
99 //
100 // d := &Disk{}
101 //
102 // box := parser.NewBox("Test_Disk_Files", "./_fixtures/disk/franklin")
103 // files, err := d.Files(box)
104 // r.NoError(err)
105 // r.Len(files, 2)
106 //
107 // f := files[0]
108 // r.Equal("aretha.txt", filepath.Base(f.Name()))
109 // r.Equal("RESPECT!", strings.TrimSpace(f.String()))
110 //
111 // f = files[1]
112 // r.Equal("think.txt", filepath.Base(f.Name()))
113 // r.Equal("THINK!", strings.TrimSpace(f.String()))
114 // }
115 //
116 // func Test_Disk_Pack(t *testing.T) {
117 // oncer.Reset()
118 // r := require.New(t)
119 //
120 // d := NewDisk("", "")
121 //
122 // p, err := parser.NewFromRoots([]string{"./_fixtures/disk-pack"}, &parser.RootsOptions{
123 // IgnoreImports: true,
124 // })
125 // r.NoError(err)
126 // boxes, err := p.Run()
127 // r.NoError(err)
128 //
129 // for _, b := range boxes {
130 // r.NoError(d.Pack(b))
131 // }
132 //
133 // global := d.global
134 // r.Len(global, 3)
135 //
136 // r.Len(d.boxes, 3)
137 //
138 // }
139 //
140 // func Test_Disk_Packed_Test(t *testing.T) {
141 // r := require.New(t)
142 //
143 // b := packr.NewBox("simpsons")
144 //
145 // s, err := b.FindString("parents/homer.txt")
146 // r.NoError(err)
147 // r.Equal("HOMER Simpson", strings.TrimSpace(s))
148 //
149 // s, err = b.FindString("parents/marge.txt")
150 // r.NoError(err)
151 // r.Equal("MARGE Simpson", strings.TrimSpace(s))
152 //
153 // _, err = b.FindString("idontexist")
154 // r.Error(err)
155 // }
156 //
157 // func Test_Disk_Close(t *testing.T) {
158 // gomods.Disable(func() error {
159 // r := require.New(t)
160 //
161 // p, err := parser.NewFromRoots([]string{"./_fixtures/disk-pack"}, nil)
162 // r.NoError(err)
163 // boxes, err := p.Run()
164 // r.NoError(err)
165 //
166 // d := NewDisk("./_fixtures/disk-pack", "")
167 // for _, b := range boxes {
168 // r.NoError(d.Pack(b))
169 // }
170 // r.NoError(d.Close())
171 // return nil
172 // })
173 // }
174 //
175 // func Test_Disk_Generator_NoFiles(t *testing.T) {
176 // gomods.Disable(func() error {
177 //
178 // r := require.New(t)
179 //
180 // d := NewDisk(".", "")
181 // r.Len(d.boxes, 0)
182 //
183 // run := gentest.NewRunner()
184 // run.WithNew(d.Generator())
185 // r.NoError(run.Run())
186 //
187 // res := run.Results()
188 // r.Len(res.Files, 0)
189 //
190 // return nil
191 // })
192 // }
0 package store
1
2 const diskGlobalTmpl = `// +build !skippackr
3 // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.
4
5 // You can use the "packr2 clean" command to clean up this,
6 // and any other packr generated files.
7 package {{.Package}}
8
9 import (
10 "github.com/gobuffalo/packr/v2"
11 "github.com/gobuffalo/packr/v2/file/resolver"
12 )
13
14 var _ = func() error {
15 const gk = "{{.GK}}"
16 g := packr.New(gk, "")
17 hgr, err := resolver.NewHexGzip(map[string]string{
18 {{- range $k, $v := .GlobalFiles }}
19 "{{$k}}": "{{$v}}",
20 {{- end }}
21 })
22 if err != nil {
23 panic(err)
24 }
25 g.DefaultResolver = hgr
26
27 {{- range $box := .Boxes}}
28 {{ printBox $box -}}
29 {{ end }}
30 return nil
31 }()
32 `
33
34 const diskImportTmpl = `// +build !skippackr
35 // Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.
36
37 // You can use the "packr clean" command to clean up this,
38 // and any other packr generated files.
39 package {{.Package}}
40
41 import _ "{{.Import}}"
42 `
43
44 const diskGlobalBoxTmpl = `
45 func() {
46 b := packr.New("{{.Box.Name}}", "{{.Box.Path}}")
47 {{ range $file := .Files -}}
48 b.SetResolver("{{$file.Resolver}}", packr.Pointer{ForwardBox: gk, ForwardPath: "{{$file.ForwardPath}}"})
49 {{ end -}}
50 }()
51 `
0 package store
1
2 import (
3 "os"
4 "os/exec"
5 "path/filepath"
6 "strings"
7 "sync"
8 )
9
10 var goPath = filepath.Join(os.Getenv("HOME"), "go")
11
12 func init() {
13 var once sync.Once
14 once.Do(func() {
15 cmd := exec.Command("go", "env", "GOPATH")
16 b, err := cmd.CombinedOutput()
17 if err != nil {
18 return
19 }
20 goPath = strings.TrimSpace(string(b))
21 })
22 }
23
24 // GoPath returns the current GOPATH env var
25 // or if it's missing, the default.
26 func GoPath() string {
27 return goPath
28 }
29
30 // GoBin returns the current GO_BIN env var
31 // or if it's missing, a default of "go"
32 func GoBin() string {
33 go_bin := os.Getenv("GO_BIN")
34 if go_bin == "" {
35 return "go"
36 }
37 return go_bin
38 }
0 package store
1
2 import (
3 "fmt"
4
5 "github.com/gobuffalo/packr/v2/jam/parser"
6 )
7
8 var _ Store = &FnStore{}
9
10 type FnStore struct {
11 FileNamesFn func(*parser.Box) ([]string, error)
12 FilesFn func(*parser.Box) ([]*parser.File, error)
13 PackFn func(*parser.Box) error
14 CleanFn func(*parser.Box) error
15 }
16
17 func (f *FnStore) FileNames(box *parser.Box) ([]string, error) {
18 if f.FileNamesFn == nil {
19 return []string{}, fmt.Errorf("FileNames not implemented")
20 }
21 return f.FileNames(box)
22 }
23
24 func (f *FnStore) Files(box *parser.Box) ([]*parser.File, error) {
25 if f.FilesFn == nil {
26 return []*parser.File{}, fmt.Errorf("Files not implemented")
27 }
28 return f.FilesFn(box)
29 }
30
31 func (f *FnStore) Pack(box *parser.Box) error {
32 if f.PackFn == nil {
33 return fmt.Errorf("Pack not implemented")
34 }
35 return f.PackFn(box)
36 }
37
38 func (f *FnStore) Clean(box *parser.Box) error {
39 if f.CleanFn == nil {
40 return fmt.Errorf("Clean not implemented")
41 }
42 return f.Clean(box)
43 }
0 package store
1
2 import (
3 "bytes"
4 "encoding/json"
5 "html/template"
6 "io"
7 "os"
8 "path/filepath"
9 "sort"
10 "strings"
11
12 "github.com/gobuffalo/packr/v2/jam/parser"
13 )
14
15 var _ Store = &Legacy{}
16
17 type Legacy struct {
18 *Disk
19 boxes map[string][]legacyBox
20 }
21
22 func NewLegacy() *Legacy {
23 return &Legacy{
24 Disk: NewDisk("", ""),
25 boxes: map[string][]legacyBox{},
26 }
27 }
28
29 func (l *Legacy) Pack(box *parser.Box) error {
30 files, err := l.Files(box)
31 if err != nil {
32 return err
33 }
34
35 var fcs []legacyFile
36
37 for _, f := range files {
38 n := strings.TrimPrefix(f.Name(), box.AbsPath+string(filepath.Separator))
39 c, err := l.prepFile(f)
40 if err != nil {
41 return err
42 }
43 fcs = append(fcs, legacyFile{Name: n, Contents: c})
44 }
45
46 sort.Slice(fcs, func(a, b int) bool {
47 return fcs[a].Name < fcs[b].Name
48 })
49
50 lbs := l.boxes[box.PackageDir]
51 lbs = append(lbs, legacyBox{
52 Box: box,
53 Files: fcs,
54 })
55 l.boxes[box.PackageDir] = lbs
56 return nil
57 }
58
59 func (l *Legacy) prepFile(r io.Reader) (string, error) {
60 bb := &bytes.Buffer{}
61 if _, err := io.Copy(bb, r); err != nil {
62 return "", err
63 }
64 b, err := json.Marshal(bb.Bytes())
65 if err != nil {
66 return "", err
67 }
68 return strings.Replace(string(b), "\"", "\\\"", -1), nil
69 }
70
71 // Close ...
72 func (l *Legacy) Close() error {
73 for _, b := range l.boxes {
74 if len(b) == 0 {
75 continue
76 }
77 bx := b[0].Box
78 pkg := bx.Package
79 opts := map[string]interface{}{
80 "Package": pkg,
81 "Boxes": b,
82 }
83 p := filepath.Join(bx.PackageDir, "a_"+bx.Package+"-packr.go.tmpl")
84 tmpl, err := template.New(p).Parse(legacyTmpl)
85
86 if err != nil {
87 return err
88 }
89
90 f, err := os.Create(p)
91 if err != nil {
92 return err
93 }
94
95 if err := tmpl.Execute(f, opts); err != nil {
96 return err
97 }
98
99 }
100 return nil
101 }
102
103 type legacyBox struct {
104 Box *parser.Box
105 Files []legacyFile
106 }
107
108 type legacyFile struct {
109 Name string
110 Contents string
111 }
112
113 var legacyTmpl = `// Code generated by github.com/gobuffalo/packr. DO NOT EDIT.
114
115 package {{.Package}}
116
117 import "github.com/gobuffalo/packr"
118
119 // You can use the "packr clean" command to clean up this,
120 // and any other packr generated files.
121 func init() {
122 {{- range $box := .Boxes }}
123 {{- range $box.Files }}
124 packr.PackJSONBytes("{{$box.Box.Name}}", "{{.Name}}", "{{.Contents}}")
125 {{- end }}
126 {{- end }}
127 }
128 `
0 package store
1
2 // func Test_Legacy_Pack(t *testing.T) {
3 // r := require.New(t)
4 //
5 // d := NewLegacy()
6 //
7 // p, err := parser.NewFromRoots([]string{"./_fixtures/disk"}, &parser.RootsOptions{
8 // IgnoreImports: true,
9 // })
10 // r.NoError(err)
11 // boxes, err := p.Run()
12 // r.NoError(err)
13 //
14 // for _, b := range boxes {
15 // r.NoError(d.Pack(b))
16 // }
17 //
18 // db := d.boxes
19 // r.Len(db, 2)
20 // for k, v := range db {
21 // switch filepath.Base(k) {
22 // case "disk":
23 // r.Len(v, 1)
24 // case "e":
25 // r.Len(v, 2)
26 // default:
27 // r.Fail(k)
28 // }
29 // }
30 // }
31 //
32 // func Test_Legacy_Close(t *testing.T) {
33 // oncer.Reset()
34 // r := require.New(t)
35 //
36 // d := NewLegacy()
37 //
38 // p, err := parser.NewFromRoots([]string{"./_fixtures/disk"}, &parser.RootsOptions{
39 // IgnoreImports: true,
40 // })
41 // r.NoError(err)
42 // boxes, err := p.Run()
43 // r.NoError(err)
44 //
45 // for _, b := range boxes {
46 // r.NoError(d.Pack(b))
47 // }
48 // r.Len(d.boxes, 2)
49 //
50 // run := gentest.NewRunner()
51 // r.NoError(run.WithNew(d.Generator()))
52 // r.NoError(run.Run())
53 //
54 // res := run.Results()
55 // r.Len(res.Files, 2)
56 // }
0 package store
1
2 import (
3 "github.com/gobuffalo/packr/v2/jam/parser"
4 )
5
6 type Store interface {
7 FileNames(*parser.Box) ([]string, error)
8 Files(*parser.Box) ([]*parser.File, error)
9 Pack(*parser.Box) error
10 Clean(*parser.Box) error
11 }
0 package packr
1
2 import (
3 "fmt"
4
5 "github.com/gobuffalo/packr/v2/file/resolver"
6 "github.com/gobuffalo/packr/v2/internal/takeon/github.com/markbates/safe"
7 "github.com/gobuffalo/packr/v2/jam/parser"
8 "github.com/gobuffalo/packr/v2/plog"
9 )
10
11 var boxes = &boxMap{}
12
13 var _ = safe.Run(func() {
14 p, err := parser.NewFromRoots([]string{}, nil)
15 if err != nil {
16 plog.Logger.Error(err)
17 return
18 }
19 boxes, err := p.Run()
20 if err != nil {
21 plog.Logger.Error(err)
22 return
23 }
24 for _, box := range boxes {
25 b := construct(box.Name, box.AbsPath)
26 _, err = placeBox(b)
27 if err != nil {
28 plog.Logger.Error(err)
29 return
30 }
31 }
32
33 })
34
35 func findBox(name string) (*Box, error) {
36 key := resolver.Key(name)
37 plog.Debug("packr", "findBox", "name", name, "key", key)
38
39 b, ok := boxes.Load(key)
40 if !ok {
41 plog.Debug("packr", "findBox", "name", name, "key", key, "found", ok)
42 return nil, fmt.Errorf("could not find box %s", name)
43 }
44
45 plog.Debug(b, "found", "box", b)
46 return b, nil
47 }
48
49 func placeBox(b *Box) (*Box, error) {
50 key := resolver.Key(b.Name)
51 eb, _ := boxes.LoadOrStore(key, b)
52
53 plog.Debug("packr", "placeBox", "name", eb.Name, "path", eb.Path, "resolution directory", eb.ResolutionDir)
54 return eb, nil
55 }
0 The MIT License (MIT)
1
2 Copyright © 2018 Mark Bates
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
0 package cmd
1
2 import (
3 "fmt"
4
5 "github.com/gobuffalo/packr/v2/jam"
6 "github.com/spf13/cobra"
7 )
8
9 var buildCmd = &cobra.Command{
10 Use: "build",
11 Short: "Wraps the go build command with packr",
12 DisableFlagParsing: true,
13 RunE: func(cmd *cobra.Command, args []string) error {
14 cargs := parseArgs(args)
15 if globalOptions.Verbose {
16 fmt.Println(dont)
17 }
18 if err := jam.Pack(globalOptions.PackOptions); err != nil {
19 return err
20 }
21 return goCmd("build", cargs...)
22 },
23 }
24
25 func init() {
26 rootCmd.AddCommand(buildCmd)
27 }
0 package cmd
1
2 import (
3 "github.com/gobuffalo/packr/v2/jam"
4 "github.com/spf13/cobra"
5 )
6
7 var cleanCmd = &cobra.Command{
8 Use: "clean",
9 Short: "removes any *-packr.go files",
10 RunE: func(cmd *cobra.Command, args []string) error {
11 return jam.Clean(args...)
12 },
13 }
14
15 func init() {
16 rootCmd.AddCommand(cleanCmd)
17 }
0 package fix
1
2 import (
3 "bufio"
4 "fmt"
5 "os"
6 "strings"
7
8 "github.com/gobuffalo/envy"
9 "github.com/gobuffalo/packr/v2/jam/store"
10 )
11
12 var modsOn = (strings.TrimSpace(envy.Get("GO111MODULE", "off")) == "on")
13
14 //YesToAll will be used by the command to skip the questions
15 var YesToAll bool
16
17 var replace = map[string]string{
18 "github.com/gobuffalo/packr": "github.com/gobuffalo/packr/v2",
19 }
20
21 var ic = ImportConverter{
22 Data: replace,
23 }
24
25 var checks = []Check{
26 // packrClean,
27 ic.Process,
28 }
29
30 func packrClean(r *Runner) error {
31 pwd, err := os.Getwd()
32 if err != nil {
33 return err
34 }
35 store.Clean(pwd)
36 return nil
37 }
38
39 func ask(q string) bool {
40 if YesToAll {
41 return true
42 }
43
44 fmt.Printf("? %s [y/n]\n", q)
45
46 reader := bufio.NewReader(os.Stdin)
47 text, _ := reader.ReadString('\n')
48
49 text = strings.ToLower(strings.TrimSpace(text))
50 return text == "y" || text == "yes"
51 }
0 package fix
1
2 import (
3 "bytes"
4 "fmt"
5 "go/ast"
6 "go/parser"
7 "go/printer"
8 "go/token"
9 "io/ioutil"
10 "os"
11 "path/filepath"
12 "strconv"
13 "strings"
14
15 "golang.org/x/tools/go/ast/astutil"
16 )
17
18 // ImportConverter will changes imports from a -> b
19 type ImportConverter struct {
20 Data map[string]string
21 }
22
23 // Process will walk all the .go files in an application, excluding ./vendor.
24 // It will then attempt to convert any old import paths to any new import paths
25 // used by this version Buffalo.
26 func (c ImportConverter) Process(r *Runner) error {
27 fmt.Println("~~~ Rewriting Imports ~~~")
28
29 err := filepath.Walk(".", c.processFile)
30 if err != nil {
31 return err
32 }
33
34 if _, err := os.Stat("Gopkg.toml"); err != nil {
35 return nil
36 }
37
38 b, err := ioutil.ReadFile("Gopkg.toml")
39 if err != nil {
40 return err
41 }
42
43 for k := range c.Data {
44 if bytes.Contains(b, []byte(k)) {
45 r.Warnings = append(r.Warnings, fmt.Sprintf("Your Gopkg.toml contains the following import that need to be changed MANUALLY: %s", k))
46 }
47 }
48
49 return nil
50 }
51
52 func (c ImportConverter) processFile(p string, info os.FileInfo, err error) error {
53 er := onlyRelevantFiles(p, info, err, func(p string) error {
54 err := c.rewriteFile(p)
55 if err != nil {
56 err = err
57 }
58
59 return err
60 })
61
62 return er
63 }
64
65 func (c ImportConverter) rewriteFile(name string) error {
66 // create an empty fileset.
67 fset := token.NewFileSet()
68
69 // parse the .go file.
70 // we are parsing the entire file with comments, so we don't lose anything
71 // if we need to write it back out.
72 f, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
73 if err != nil {
74 e := err.Error()
75 msg := "expected 'package', found 'EOF'"
76 if e[len(e)-len(msg):] == msg {
77 return nil
78 }
79 return err
80 }
81
82 changed := false
83 funcs := []*ast.FuncDecl{}
84 for _, d := range f.Decls {
85 if fn, isFn := d.(*ast.FuncDecl); isFn {
86 funcs = append(funcs, fn)
87 }
88 }
89
90 for _, fun := range funcs {
91 ast.Inspect(fun, func(node ast.Node) bool {
92 switch n := node.(type) {
93 case *ast.CallExpr:
94 fn, ok := n.Fun.(*ast.SelectorExpr)
95 if !ok || fn.Sel == nil {
96 return true
97 }
98
99 sel := fn.Sel
100 i, ok := fn.X.(*ast.Ident)
101 if !ok {
102 return true
103 }
104 if i.Name != "packr" {
105 return true
106 }
107 if sel.Name == "NewBox" {
108 sel.Name = "New"
109 n.Args = append(n.Args, n.Args[0])
110 changed = true
111 }
112 if sel.Name == "MustBytes" {
113 sel.Name = "Find"
114 changed = true
115 }
116 if sel.Name == "MustBytes" {
117 sel.Name = "Find"
118 changed = true
119 }
120 }
121 return true
122 })
123 }
124
125 for key, value := range c.Data {
126 if !astutil.DeleteImport(fset, f, key) {
127 continue
128 }
129
130 astutil.AddImport(fset, f, value)
131 changed = true
132 }
133
134 commentsChanged, err := c.handleFileComments(f)
135 if err != nil {
136 return err
137 }
138
139 changed = changed || commentsChanged
140
141 // if no change occurred, then we don't need to write to disk, just return.
142 if !changed {
143 return nil
144 }
145
146 // since the imports changed, resort them.
147 ast.SortImports(fset, f)
148
149 // create a temporary file, this easily avoids conflicts.
150 temp, err := writeTempResult(name, fset, f)
151 if err != nil {
152 return err
153 }
154
155 // rename the .temp to .go
156 return os.Rename(temp, name)
157 }
158
159 func (c ImportConverter) handleFileComments(f *ast.File) (bool, error) {
160 change := false
161
162 for _, cg := range f.Comments {
163 for _, cl := range cg.List {
164 if !strings.HasPrefix(cl.Text, "// import \"") {
165 continue
166 }
167
168 // trim off extra comment stuff
169 ctext := cl.Text
170 ctext = strings.TrimPrefix(ctext, "// import")
171 ctext = strings.TrimSpace(ctext)
172
173 // unquote the comment import path value
174 ctext, err := strconv.Unquote(ctext)
175 if err != nil {
176 return false, err
177 }
178
179 // match the comment import path with the given replacement map
180 if ctext, ok := c.match(ctext); ok {
181 cl.Text = "// import " + strconv.Quote(ctext)
182 change = true
183 }
184
185 }
186 }
187
188 return change, nil
189 }
190
191 // match takes an import path and replacement map.
192 func (c ImportConverter) match(importpath string) (string, bool) {
193 for key, value := range c.Data {
194 if !strings.HasPrefix(importpath, key) {
195 continue
196 }
197
198 result := strings.Replace(importpath, key, value, 1)
199 return result, true
200 }
201
202 return importpath, false
203 }
204
205 //onlyRelevantFiles processes only .go files excluding folders like node_modules and vendor.
206 func onlyRelevantFiles(p string, fi os.FileInfo, err error, fn func(p string) error) error {
207 if err != nil {
208 return err
209 }
210
211 if fi.IsDir() && p != "." {
212 for _, n := range []string{"_", ".", "vendor", "node_modules", ".git"} {
213 base := filepath.Base(p)
214 if strings.HasPrefix(base, n) {
215 return filepath.SkipDir
216 }
217 }
218
219 return nil
220 }
221
222 ext := filepath.Ext(p)
223 if ext != ".go" {
224 return nil
225 }
226
227 return fn(p)
228 }
229
230 func writeTempResult(name string, fset *token.FileSet, f *ast.File) (string, error) {
231 temp := name + ".temp"
232 w, err := os.Create(temp)
233 if err != nil {
234 return "", err
235 }
236
237 // write changes to .temp file, and include proper formatting.
238 err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(w, fset, f)
239 if err != nil {
240 return "", err
241 }
242
243 // close the writer
244 err = w.Close()
245 if err != nil {
246 return "", err
247 }
248
249 return temp, nil
250 }
0 package fix
1
2 import (
3 "fmt"
4
5 packr "github.com/gobuffalo/packr/v2"
6 )
7
8 // Check interface for runnable checker functions
9 type Check func(*Runner) error
10
11 // Runner will run all compatible checks
12 type Runner struct {
13 Warnings []string
14 }
15
16 // Run all compatible checks
17 func Run() error {
18 fmt.Printf("! This updater will attempt to update your application to packr version: %s\n", packr.Version)
19 if !ask("Do you wish to continue?") {
20 fmt.Println("~~~ cancelling update ~~~")
21 return nil
22 }
23
24 r := &Runner{
25 Warnings: []string{},
26 }
27
28 defer func() {
29 if len(r.Warnings) == 0 {
30 return
31 }
32
33 fmt.Println("\n\n----------------------------")
34 fmt.Printf("!!! (%d) Warnings Were Found !!!\n\n", len(r.Warnings))
35 for _, w := range r.Warnings {
36 fmt.Printf("[WARNING]: %s\n", w)
37 }
38 }()
39
40 for _, c := range checks {
41 if err := c(r); err != nil {
42 return err
43 }
44 }
45 return nil
46 }
0 package cmd
1
2 import (
3 "fmt"
4
5 packr "github.com/gobuffalo/packr/v2"
6 "github.com/gobuffalo/packr/v2/packr2/cmd/fix"
7 "github.com/spf13/cobra"
8 )
9
10 // fixCmd represents the info command
11 var fixCmd = &cobra.Command{
12 Use: "fix",
13 Short: fmt.Sprintf("will attempt to fix a application's API to match packr version %s", packr.Version),
14 RunE: func(cmd *cobra.Command, args []string) error {
15 return fix.Run()
16 },
17 }
18
19 func init() {
20 fixCmd.Flags().BoolVarP(&fix.YesToAll, "y", "", false, "update all without asking for confirmation")
21 rootCmd.AddCommand(fixCmd)
22 }
0 package cmd
1
2 import (
3 "io/ioutil"
4 "os"
5 "os/exec"
6 "path/filepath"
7 "strings"
8
9 "github.com/gobuffalo/envy"
10 "github.com/gobuffalo/packr/v2/plog"
11 )
12
13 func goCmd(name string, args ...string) error {
14 cargs := []string{name}
15 cargs = append(cargs, args...)
16 if len(args) > 0 {
17 err := func() error {
18 path := "."
19
20 pwd, err := os.Getwd()
21 if err != nil {
22 return err
23 }
24
25 if fi, err := os.Stat(filepath.Join(pwd, args[len(args)-1])); err == nil {
26 if fi.IsDir() {
27 return nil
28 }
29 path = fi.Name()
30 }
31
32 if filepath.Ext(path) != ".go" {
33 return nil
34 }
35
36 path, err = filepath.Abs(filepath.Dir(path))
37 if err != nil {
38 return err
39 }
40
41 files, err := ioutil.ReadDir(path)
42 if err != nil {
43 return err
44 }
45 for _, f := range files {
46 if strings.HasSuffix(f.Name(), "-packr.go") {
47 cargs = append(cargs, f.Name())
48 }
49 }
50 return nil
51 }()
52 if err != nil {
53 return err
54 }
55 }
56
57 cp := exec.Command(envy.Get("GO_BIN", "go"), cargs...)
58 plog.Logger.Debug(strings.Join(cp.Args, " "))
59 cp.Stderr = os.Stderr
60 cp.Stdin = os.Stdin
61 cp.Stdout = os.Stdout
62 return cp.Run()
63 }
0 package cmd
1
2 import (
3 "fmt"
4
5 "github.com/gobuffalo/packr/v2/jam"
6 "github.com/spf13/cobra"
7 )
8
9 const dont = `Please don't.
10 The following commands have been deprecated and should not be used:
11
12 * packr2 build
13 * packr2 install
14
15 They are, I'll be kind and say, "problematic" and cause more issues
16 than than the actually solve. Sorry about that. My bad.
17
18 It is recommended you use two commands instead:
19
20 $ packr2
21 $ go build/install
22 `
23
24 var installCmd = &cobra.Command{
25 Use: "install",
26 Short: "Don't. ru",
27 DisableFlagParsing: true,
28 RunE: func(cmd *cobra.Command, args []string) error {
29 cargs := parseArgs(args)
30 if globalOptions.Verbose {
31 fmt.Println(dont)
32 }
33 if err := jam.Pack(globalOptions.PackOptions); err != nil {
34 return err
35 }
36 return goCmd("install", cargs...)
37 },
38 }
39
40 func init() {
41 rootCmd.AddCommand(installCmd)
42 }
0 package cmd
1
2 func parseArgs(args []string) []string {
3 var cargs []string
4 for _, a := range args {
5 if a == "--legacy" {
6 globalOptions.Legacy = true
7 continue
8 }
9 if a == "--verbose" {
10 globalOptions.Verbose = true
11 continue
12 }
13 if a == "--silent" {
14 globalOptions.Silent = true
15 continue
16 }
17 if a == "--ignore-imports" {
18 globalOptions.IgnoreImports = true
19 continue
20 }
21 cargs = append(cargs, a)
22 }
23 return cargs
24 }
0 package cmd
1
2 import (
3 "os"
4 "path/filepath"
5
6 "github.com/gobuffalo/logger"
7 "github.com/gobuffalo/packr/v2/jam"
8 "github.com/gobuffalo/packr/v2/plog"
9 "github.com/spf13/cobra"
10 )
11
12 var globalOptions = struct {
13 jam.PackOptions
14 Verbose bool
15 Silent bool
16 }{
17 PackOptions: jam.PackOptions{},
18 }
19
20 var rootCmd = &cobra.Command{
21 Use: "packr2",
22 Short: "Packr is a simple solution for bundling static assets inside of Go binaries.",
23 PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
24 for _, a := range args {
25 if a == "--legacy" {
26 globalOptions.Legacy = true
27 continue
28 }
29 if a == "-v" || a == "--verbose" {
30 globalOptions.Verbose = true
31 continue
32 }
33 }
34
35 // if the last argument is a .go file or directory we should
36 // find boxes from there, not from the current directory.
37 // packr2 build -v cmd/main.go
38 if len(args) > 0 {
39 i := len(args) - 1
40 dir := args[i]
41 if _, err := os.Stat(dir); err == nil {
42 if filepath.Ext(dir) == ".go" {
43 dir = filepath.Dir(dir)
44 }
45 os.Chdir(dir)
46 args[i] = filepath.Base(args[i])
47 }
48 }
49
50 if globalOptions.Verbose {
51 plog.Logger = logger.New(logger.DebugLevel)
52 }
53 if globalOptions.Silent {
54 plog.Logger = logger.New(logger.FatalLevel)
55 }
56 return nil
57 },
58 RunE: func(cmd *cobra.Command, args []string) error {
59 opts := globalOptions.PackOptions
60 roots := opts.Roots
61 roots = append(roots, args...)
62 opts.Roots = roots
63 return jam.Pack(opts)
64 },
65 }
66
67 // Execute adds all child commands to the root command and sets flags appropriately.
68 // This is called by main.main(). It only needs to happen once to the rootCmd.
69 func Execute() {
70 if err := rootCmd.Execute(); err != nil {
71 os.Exit(1)
72 }
73 }
74
75 func init() {
76 rootCmd.PersistentFlags().BoolVarP(&globalOptions.Verbose, "verbose", "v", false, "enables verbose logging")
77 rootCmd.PersistentFlags().BoolVar(&globalOptions.Legacy, "legacy", false, "uses the legacy resolution and packing system (assumes first arg || pwd for input path)")
78 rootCmd.PersistentFlags().BoolVar(&globalOptions.Silent, "silent", false, "silences all output")
79 rootCmd.PersistentFlags().BoolVar(&globalOptions.IgnoreImports, "ignore-imports", false, "when set to true packr won't resolve imports for boxes")
80 rootCmd.PersistentFlags().StringVar(&globalOptions.StoreCmd, "store-cmd", "", "sub command to use for packing")
81 }
0 package cmd
1
2 import (
3 "fmt"
4
5 packr "github.com/gobuffalo/packr/v2"
6 "github.com/spf13/cobra"
7 )
8
9 var versionCmd = &cobra.Command{
10 Use: "version",
11 Short: "shows packr version",
12 RunE: func(cmd *cobra.Command, args []string) error {
13 fmt.Print(packr.Version)
14 return nil
15 },
16 }
17
18 func init() {
19 rootCmd.AddCommand(versionCmd)
20 }
0 package main
1
2 import "github.com/gobuffalo/packr/v2/packr2/cmd"
3
4 func main() {
5 cmd.Execute()
6 }
0 package packr
1
2 import "github.com/gobuffalo/packr/v2/file"
3
4 func qfile(name string, body string) File {
5 f, err := file.NewFile(name, []byte(body))
6 if err != nil {
7 panic(err)
8 }
9 return f
10 }
0 package plog
1
2 import (
3 "encoding/json"
4 "fmt"
5
6 "github.com/gobuffalo/logger"
7 "github.com/sirupsen/logrus"
8 )
9
10 var Logger = logger.New(logger.ErrorLevel)
11
12 func Debug(t interface{}, m string, args ...interface{}) {
13 if len(args)%2 == 1 {
14 args = append(args, "")
15 }
16 f := logrus.Fields{}
17 for i := 0; i < len(args); i += 2 {
18 k := fmt.Sprint(args[i])
19 v := args[i+1]
20 if s, ok := v.(fmt.Stringer); ok {
21 f[k] = s.String()
22 continue
23 }
24 if s, ok := v.(string); ok {
25 f[k] = s
26 continue
27 }
28 if b, err := json.Marshal(v); err == nil {
29 f[k] = string(b)
30 continue
31 }
32 f[k] = v
33 }
34 e := Logger.WithFields(f)
35 if s, ok := t.(string); ok {
36 e.Debugf("%s#%s", s, m)
37 return
38 }
39 e.Debugf("%T#%s", t, m)
40 }
0 package packr
1
2 import (
3 "github.com/gobuffalo/packr/v2/file"
4 "github.com/gobuffalo/packr/v2/file/resolver"
5 "github.com/gobuffalo/packr/v2/plog"
6 )
7
8 // Pointer is a resolvr which resolves
9 // a file from a different box.
10 type Pointer struct {
11 ForwardBox string
12 ForwardPath string
13 }
14
15 var _ resolver.Resolver = Pointer{}
16
17 // Resolve attempts to find the file in the specific box
18 // with the specified key
19 func (p Pointer) Resolve(box string, path string) (file.File, error) {
20 plog.Debug(p, "Resolve", "box", box, "path", path, "forward-box", p.ForwardBox, "forward-path", p.ForwardPath)
21 b, err := findBox(p.ForwardBox)
22 if err != nil {
23 return nil, err
24 }
25 f, err := b.Resolve(p.ForwardPath)
26 if err != nil {
27 return f, err
28 }
29 plog.Debug(p, "Resolve", "box", box, "path", path, "file", f)
30 return file.NewFileR(path, f)
31 }
0 package packr
1
2 import (
3 "testing"
4
5 "github.com/gobuffalo/packr/v2/file/resolver"
6 "github.com/stretchr/testify/require"
7 )
8
9 func Test_Pointer_Find(t *testing.T) {
10 r := require.New(t)
11
12 b1 := New("b1", "")
13 r.NoError(b1.AddString("foo.txt", "FOO!"))
14
15 b2 := New("b2", "")
16 b2.SetResolver("bar.txt", &Pointer{
17 ForwardBox: "b1",
18 ForwardPath: "foo.txt",
19 })
20
21 s, err := b2.FindString("bar.txt")
22 r.NoError(err)
23 r.Equal("FOO!", s)
24 }
25
26 func Test_Pointer_Find_CorrectName(t *testing.T) {
27 r := require.New(t)
28
29 gk := "0b5bab905480ad8c6d0695f615dcd644"
30 g := New(gk, "")
31 hgr, err := resolver.NewHexGzip(map[string]string{
32 "48df4e44f4202fe5f6093beee782cb10": "1f8b08000000000000ff4c8ebdaec2300c46f7fb14bed94b5606a70b3f6283a1083186c46a2225354aad56bc3d6a2304933fdbc73ac6fffd79d7dd2f07089253fb87b5006020eb97008099c4820bb68c24465dbb63b355a07f9783cd64d414697e7211058e07a1418c9aa397603c4dd151b336df4b8992a83d514a0c372ec9a3aea345af3f7e7cb07fad21e61ec6e28cd2897bde8c53af2a5a09d4f5f777000000ffffcfb8b477d3000000",
33 })
34 r.NoError(err)
35 g.DefaultResolver = hgr
36
37 b := New("my box", "./templates")
38 b.SetResolver("index.html", Pointer{ForwardBox: gk, ForwardPath: "48df4e44f4202fe5f6093beee782cb10"})
39 f, err := b.Resolve("index.html")
40 r.NoError(err)
41 fi, err := f.Stat()
42 r.NoError(err)
43 r.Equal("index.html", fi.Name())
44 }
0 //go:generate mapgen -name "resolvers" -zero "nil" -go-type "resolver.Resolver" -pkg "" -a "nil" -b "nil" -c "nil" -bb "nil" -destination "packr"
1 // Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
2
3 package packr
4
5 import (
6 "sort"
7 "sync"
8
9 "github.com/gobuffalo/packr/v2/file/resolver"
10 )
11
12 // resolversMap wraps sync.Map and uses the following types:
13 // key: string
14 // value: resolver.Resolver
15 type resolversMap struct {
16 data sync.Map
17 }
18
19 // Delete the key from the map
20 func (m *resolversMap) Delete(key string) {
21 m.data.Delete(key)
22 }
23
24 // Load the key from the map.
25 // Returns resolver.Resolver or bool.
26 // A false return indicates either the key was not found
27 // or the value is not of type resolver.Resolver
28 func (m *resolversMap) Load(key string) (resolver.Resolver, bool) {
29 i, ok := m.data.Load(key)
30 if !ok {
31 return nil, false
32 }
33 s, ok := i.(resolver.Resolver)
34 return s, ok
35 }
36
37 // LoadOrStore will return an existing key or
38 // store the value if not already in the map
39 func (m *resolversMap) LoadOrStore(key string, value resolver.Resolver) (resolver.Resolver, bool) {
40 i, _ := m.data.LoadOrStore(key, value)
41 s, ok := i.(resolver.Resolver)
42 return s, ok
43 }
44
45 // Range over the resolver.Resolver values in the map
46 func (m *resolversMap) Range(f func(key string, value resolver.Resolver) bool) {
47 m.data.Range(func(k, v interface{}) bool {
48 key, ok := k.(string)
49 if !ok {
50 return false
51 }
52 value, ok := v.(resolver.Resolver)
53 if !ok {
54 return false
55 }
56 return f(key, value)
57 })
58 }
59
60 // Store a resolver.Resolver in the map
61 func (m *resolversMap) Store(key string, value resolver.Resolver) {
62 m.data.Store(key, value)
63 }
64
65 // Keys returns a list of keys in the map
66 func (m *resolversMap) Keys() []string {
67 var keys []string
68 m.Range(func(key string, value resolver.Resolver) bool {
69 keys = append(keys, key)
70 return true
71 })
72 sort.Strings(keys)
73 return keys
74 }
0 package packr
1
2 // Version of Packr
3 const Version = "v2.5.1"
0 package packr
1
2 import (
3 "sort"
4 "strings"
5
6 "github.com/gobuffalo/packd"
7 "github.com/gobuffalo/packr/v2/file"
8 "github.com/gobuffalo/packr/v2/file/resolver"
9 "github.com/gobuffalo/packr/v2/plog"
10 )
11
12 // WalkFunc is used to walk a box
13 type WalkFunc = packd.WalkFunc
14
15 // Walk will traverse the box and call the WalkFunc for each file in the box/folder.
16 func (b *Box) Walk(wf WalkFunc) error {
17 m := map[string]file.File{}
18
19 dr := b.DefaultResolver
20 if dr == nil {
21 cd := resolver.OsPath(b.ResolutionDir)
22 dr = &resolver.Disk{Root: cd}
23 }
24 if fm, ok := dr.(file.FileMappable); ok {
25 for n, f := range fm.FileMap() {
26 m[n] = f
27 }
28 }
29 var err error
30 b.resolvers.Range(func(n string, r resolver.Resolver) bool {
31 var f file.File
32 f, err = r.Resolve("", n)
33 if err != nil {
34 return false
35 }
36 keep := true
37 for k := range m {
38 if strings.EqualFold(k, n) {
39 keep = false
40 }
41 }
42 if keep {
43 m[n] = f
44 }
45 return true
46 })
47 if err != nil {
48 return err
49 }
50
51 var keys = make([]string, 0, len(m))
52 for k := range m {
53 keys = append(keys, k)
54 }
55 sort.Strings(keys)
56
57 for _, k := range keys {
58 osPath := resolver.OsPath(k)
59 plog.Debug(b, "Walk", "path", k, "osPath", osPath)
60 if err := wf(osPath, m[k]); err != nil {
61 return err
62 }
63 }
64 return nil
65 }
66
67 // WalkPrefix will call box.Walk and call the WalkFunc when it finds paths that have a matching prefix
68 func (b *Box) WalkPrefix(prefix string, wf WalkFunc) error {
69 ipref := resolver.OsPath(prefix)
70 return b.Walk(func(path string, f File) error {
71 ipath := resolver.OsPath(path)
72 if strings.HasPrefix(ipath, ipref) {
73 if err := wf(path, f); err != nil {
74 return err
75 }
76 }
77 return nil
78 })
79 }
0 package packr
1
2 import (
3 "path/filepath"
4 "testing"
5
6 "github.com/gobuffalo/packr/v2/file"
7 "github.com/stretchr/testify/require"
8 )
9
10 func Test_Box_Walk(t *testing.T) {
11 r := require.New(t)
12
13 box := NewBox(filepath.Join("_fixtures", "list_test"))
14 r.NoError(box.AddString(filepath.Join("d", "d.txt"), "D"))
15
16 var act []string
17 r.NoError(box.Walk(func(path string, f file.File) error {
18 act = append(act, path)
19 return nil
20 }))
21 exp := []string{"a.txt", filepath.Join("b", "b.txt"), filepath.Join("b", "b2.txt"), filepath.Join("c", "c.txt"), filepath.Join("d", "d.txt")}
22 r.Equal(exp, act)
23 }
24
25 func Test_Box_WalkPrefix(t *testing.T) {
26 r := require.New(t)
27
28 box := NewBox(filepath.Join("_fixtures", "list_test"))
29 r.NoError(box.AddString(filepath.Join("d", "d.txt"), "D"))
30
31 var act []string
32 r.NoError(box.WalkPrefix("b/", func(path string, f file.File) error {
33 act = append(act, path)
34 return nil
35 }))
36 exp := []string{filepath.Join("b", "b.txt"), filepath.Join("b", "b2.txt")}
37 r.Equal(exp, act)
38 }
0 package packr
1
2 const Version = "v1.30.1"
0 package packr
1
2 import (
3 "os"
4 "path/filepath"
5 "strings"
6
7 "github.com/gobuffalo/packd"
8 )
9
10 type WalkFunc = packd.WalkFunc
11
12 // Walk will traverse the box and call the WalkFunc for each file in the box/folder.
13 func (b Box) Walk(wf WalkFunc) error {
14 if data[b.Path] == nil {
15 base, err := filepath.EvalSymlinks(filepath.Join(b.callingDir, b.Path))
16 if err != nil {
17 return err
18 }
19 return filepath.Walk(base, func(path string, info os.FileInfo, err error) error {
20 cleanName, err := filepath.Rel(base, path)
21 if err != nil {
22 cleanName = strings.TrimPrefix(path, base)
23 }
24 cleanName = filepath.ToSlash(filepath.Clean(cleanName))
25 cleanName = strings.TrimPrefix(cleanName, "/")
26 cleanName = filepath.FromSlash(cleanName)
27 if info == nil || info.IsDir() {
28 return nil
29 }
30
31 file, err := fileFor(path, cleanName)
32 if err != nil {
33 return err
34 }
35 return wf(cleanName, file)
36 })
37 }
38 for n := range data[b.Path] {
39 f, err := b.find(n)
40 if err != nil {
41 return err
42 }
43 err = wf(n, f)
44 if err != nil {
45 return err
46 }
47 }
48 return nil
49 }
50
51 // WalkPrefix will call box.Walk and call the WalkFunc when it finds paths that have a matching prefix
52 func (b Box) WalkPrefix(prefix string, wf WalkFunc) error {
53 opre := osPath(prefix)
54 return b.Walk(func(path string, f File) error {
55 if strings.HasPrefix(osPath(path), opre) {
56 if err := wf(path, f); err != nil {
57 return err
58 }
59 }
60 return nil
61 })
62 }
0 package packr
1
2 import (
3 "testing"
4
5 "github.com/stretchr/testify/require"
6 )
7
8 func Test_Box_Walk_Physical(t *testing.T) {
9 r := require.New(t)
10 count := 0
11 err := testBox.Walk(func(path string, f File) error {
12 count++
13 return nil
14 })
15 r.NoError(err)
16 r.Equal(3, count)
17 }
18
19 func Test_Box_Walk_Virtual(t *testing.T) {
20 r := require.New(t)
21 count := 0
22 err := virtualBox.Walk(func(path string, f File) error {
23 count++
24 return nil
25 })
26 r.NoError(err)
27 r.Equal(4, count)
28 }
29
30 func Test_Box_WalkPrefix_Physical(t *testing.T) {
31 r := require.New(t)
32 var files []string
33 b := NewBox("../packr/fixtures")
34 err := b.WalkPrefix("foo/", func(path string, f File) error {
35 files = append(files, path)
36 return nil
37 })
38 r.NoError(err)
39 r.Equal(2, len(files))
40 mustHave := osPaths("foo/a.txt", "foo/bar/b.txt")
41 r.Equal(mustHave, files)
42 }
43
44 func Test_Box_WalkPrefix_Virtual(t *testing.T) {
45 r := require.New(t)
46 var files []string
47 err := virtualBox.WalkPrefix("d", func(path string, f File) error {
48 files = append(files, path)
49 return nil
50 })
51 r.NoError(err)
52 r.Equal(1, len(files))
53 r.Equal([]string{"d/a"}, files)
54 }