Skip to content
This repository was archived by the owner on Jun 25, 2022. It is now read-only.

Commit 8820c3a

Browse files
committed
Initial Commit
0 parents  commit 8820c3a

31 files changed

+760
-0
lines changed

.codeclimate.yml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
engines:
3+
golint:
4+
enabled: true
5+
checks:
6+
GoLint/Naming/MixedCaps:
7+
enabled: false
8+
govet:
9+
enabled: true
10+
gofmt:
11+
enabled: true
12+
fixme:
13+
enabled: true
14+
ratings:
15+
paths:
16+
- "**.go"
17+
exclude_paths:
18+
- "**/*_test.go"
19+
- "*_test.go"
20+
- "fixtures/"

.gitignore

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
*.log
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

.travis.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
language: go
2+
3+
sudo: false
4+
5+
go:
6+
- 1.7
7+
- 1.8
8+
- tip
9+
10+
matrix:
11+
allow_failures:
12+
- go: 'tip'

LICENSE.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
The MIT License (MIT)
2+
Copyright (c) 2016 Mark Bates
3+
4+
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:
5+
6+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7+
8+
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.

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# packr

box.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package packr
2+
3+
import (
4+
"io/ioutil"
5+
"path/filepath"
6+
"runtime"
7+
)
8+
9+
// NewBox returns a Box that can be used to
10+
// retrieve files from either disk or the embedded
11+
// binary.
12+
func NewBox(path string) Box {
13+
_, filename, _, _ := runtime.Caller(1)
14+
return Box{
15+
Path: path,
16+
callingDir: filepath.Dir(filename),
17+
}
18+
}
19+
20+
// Box represent a folder on a disk you want to
21+
// have access to in the built Go binary.
22+
type Box struct {
23+
Path string
24+
callingDir string
25+
data map[string][]byte
26+
}
27+
28+
// String of the file asked for or an empty string.
29+
func (b Box) String(name string) string {
30+
return string(b.Bytes(name))
31+
}
32+
33+
// MustString returns either the string of the requested
34+
// file or an error if it can not be found.
35+
func (b Box) MustString(name string) (string, error) {
36+
bb, err := b.MustBytes(name)
37+
return string(bb), err
38+
}
39+
40+
// Bytes of the file asked for or an empty byte slice.
41+
func (b Box) Bytes(name string) []byte {
42+
bb, _ := b.MustBytes(name)
43+
return bb
44+
}
45+
46+
// MustBytes returns either the byte slice of the requested
47+
// file or an error if it can not be found.
48+
func (b Box) MustBytes(name string) ([]byte, error) {
49+
bb, err := find(b.Path, name)
50+
if err == nil {
51+
return bb, err
52+
}
53+
p := filepath.Join(b.callingDir, b.Path, name)
54+
return ioutil.ReadFile(p)
55+
}

box_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package packr
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func Test_Box_String(t *testing.T) {
10+
r := require.New(t)
11+
s := testBox.String("hello.txt")
12+
r.Equal("hello world!\n", s)
13+
}
14+
15+
func Test_Box_MustString(t *testing.T) {
16+
r := require.New(t)
17+
_, err := testBox.MustString("idontexist.txt")
18+
r.Error(err)
19+
}
20+
21+
func Test_Box_Bytes(t *testing.T) {
22+
r := require.New(t)
23+
s := testBox.Bytes("hello.txt")
24+
r.Equal([]byte("hello world!\n"), s)
25+
}
26+
27+
func Test_Box_MustBytes(t *testing.T) {
28+
r := require.New(t)
29+
_, err := testBox.MustBytes("idontexist.txt")
30+
r.Error(err)
31+
}

builder/box.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package builder
2+
3+
import (
4+
"encoding/json"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
10+
"github.com/pkg/errors"
11+
)
12+
13+
type box struct {
14+
Name string
15+
Files []file
16+
}
17+
18+
func (b *box) Walk(root string) error {
19+
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
20+
if info == nil || info.IsDir() {
21+
return nil
22+
}
23+
f := file{
24+
Name: strings.Replace(path, root, "", 1),
25+
}
26+
27+
bb, err := ioutil.ReadFile(path)
28+
if err != nil {
29+
return errors.WithStack(err)
30+
}
31+
bb, err = json.Marshal(bb)
32+
if err != nil {
33+
return errors.WithStack(err)
34+
}
35+
f.Contents = strings.Replace(string(bb), "\"", "\\\"", -1)
36+
37+
b.Files = append(b.Files, f)
38+
return nil
39+
})
40+
}

builder/builder.go

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package builder
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"path/filepath"
9+
"regexp"
10+
"text/template"
11+
12+
"github.com/pkg/errors"
13+
)
14+
15+
var boxPattern = regexp.MustCompile(`packr.NewBox\(["` + "`" + `](.+)["` + "`" + `]\)`)
16+
var packagePattern = regexp.MustCompile(`package\s+(.+)`)
17+
var invalidFilePattern = regexp.MustCompile(`(_test|-packr).go$`)
18+
19+
// Builder scans folders/files looking for `packr.NewBox` and then compiling
20+
// the required static files into `<package-name>-packr.go` files so they can
21+
// be built into Go binaries.
22+
type Builder struct {
23+
context.Context
24+
RootPath string
25+
pkgs map[string]pkg
26+
}
27+
28+
// Run the builder.
29+
func (b *Builder) Run() error {
30+
err := filepath.Walk(b.RootPath, func(path string, info os.FileInfo, err error) error {
31+
base := filepath.Base(path)
32+
if base == ".git" || base == "vendor" || base == "node_modules" {
33+
return filepath.SkipDir
34+
}
35+
36+
if !info.IsDir() {
37+
return b.process(path)
38+
}
39+
return nil
40+
})
41+
if err != nil {
42+
return errors.WithStack(err)
43+
}
44+
return b.dump()
45+
}
46+
47+
func (b *Builder) dump() error {
48+
for _, p := range b.pkgs {
49+
name := filepath.Join(p.Dir, p.Name+"-packr.go")
50+
fmt.Printf("--> packing %s\n", name)
51+
f, err := os.Create(name)
52+
if err != nil {
53+
return errors.WithStack(err)
54+
}
55+
t, err := template.New("").Parse(tmpl)
56+
57+
if err != nil {
58+
return errors.WithStack(err)
59+
}
60+
err = t.Execute(f, p)
61+
if err != nil {
62+
return errors.WithStack(err)
63+
}
64+
}
65+
return nil
66+
}
67+
68+
func (b *Builder) process(path string) error {
69+
ext := filepath.Ext(path)
70+
if ext != ".go" || invalidFilePattern.MatchString(path) {
71+
return nil
72+
}
73+
74+
bb, err := ioutil.ReadFile(path)
75+
if err != nil {
76+
return errors.WithStack(err)
77+
}
78+
fb := string(bb)
79+
80+
matches := boxPattern.FindAllStringSubmatch(fb, -1)
81+
if len(matches) == 0 {
82+
return nil
83+
}
84+
85+
pk := pkg{
86+
Dir: filepath.Dir(path),
87+
Boxes: []box{},
88+
}
89+
pname := packagePattern.FindStringSubmatch(fb)
90+
pk.Name = pname[1]
91+
92+
for _, m := range matches {
93+
bx := &box{
94+
Name: m[1],
95+
Files: []file{},
96+
}
97+
err = bx.Walk(filepath.Join(pk.Dir, bx.Name))
98+
if err != nil {
99+
return errors.WithStack(err)
100+
}
101+
if len(bx.Files) > 0 {
102+
pk.Boxes = append(pk.Boxes, *bx)
103+
}
104+
}
105+
106+
if len(pk.Boxes) > 0 {
107+
b.addPkg(pk)
108+
}
109+
return nil
110+
}
111+
112+
func (b *Builder) addPkg(p pkg) {
113+
if _, ok := b.pkgs[p.Name]; !ok {
114+
b.pkgs[p.Name] = p
115+
return
116+
}
117+
pp := b.pkgs[p.Name]
118+
pp.Boxes = append(pp.Boxes, p.Boxes...)
119+
b.pkgs[p.Name] = pp
120+
}
121+
122+
// New Builder with a given context and path
123+
func New(ctx context.Context, path string) *Builder {
124+
return &Builder{
125+
Context: ctx,
126+
RootPath: path,
127+
pkgs: map[string]pkg{},
128+
}
129+
}

0 commit comments

Comments
 (0)