camera's flash

This commit is contained in:
Mark Bates 2019-09-20 11:16:57 -04:00
parent 830ed679a8
commit fa998dbcb3
32 changed files with 93 additions and 1743 deletions

View File

@ -1,4 +1,5 @@
variables: variables:
GOPROXY: "https://proxy.golang.org"
GOBIN: "$(GOPATH)/bin" # Go binaries path GOBIN: "$(GOPATH)/bin" # Go binaries path
GOPATH: "$(system.defaultWorkingDirectory)/gopath" # Go workspace path GOPATH: "$(system.defaultWorkingDirectory)/gopath" # Go workspace path
modulePath: "$(GOPATH)/src/github.com/$(build.repository.name)" # Path to the module"s code modulePath: "$(GOPATH)/src/github.com/$(build.repository.name)" # Path to the module"s code
@ -9,12 +10,12 @@ jobs:
vmImage: "vs2017-win2016" vmImage: "vs2017-win2016"
strategy: strategy:
matrix: matrix:
go 1.11 (on):
go_version: "1.11.13"
GO111MODULE: "on"
go 1.12 (on): go 1.12 (on):
go_version: "1.12.9" go_version: "1.12.9"
GO111MODULE: "on" GO111MODULE: "on"
go 1.13 (on):
go_version: "1.13"
GO111MODULE: "on"
steps: steps:
- template: azure-tests.yml - template: azure-tests.yml
@ -23,12 +24,12 @@ jobs:
vmImage: "macOS-10.13" vmImage: "macOS-10.13"
strategy: strategy:
matrix: matrix:
go 1.11 (on):
go_version: "1.11.13"
GO111MODULE: "on"
go 1.12 (on): go 1.12 (on):
go_version: "1.12.9" go_version: "1.12.9"
GO111MODULE: "on" GO111MODULE: "on"
go 1.13 (on):
go_version: "1.13"
GO111MODULE: "on"
steps: steps:
- template: azure-tests.yml - template: azure-tests.yml
@ -37,11 +38,11 @@ jobs:
vmImage: "ubuntu-16.04" vmImage: "ubuntu-16.04"
strategy: strategy:
matrix: matrix:
go 1.11 (on):
go_version: "1.11.13"
GO111MODULE: "on"
go 1.12 (on): go 1.12 (on):
go_version: "1.12.9" go_version: "1.12.9"
GO111MODULE: "on" GO111MODULE: "on"
go 1.13 (on):
go_version: "1.13"
GO111MODULE: "on"
steps: steps:
- template: azure-tests.yml - template: azure-tests.yml

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"github.com/markbates/pkger" "github.com/markbates/pkger"
"github.com/markbates/pkger/pkging"
) )
type infoCmd struct { type infoCmd struct {
@ -44,12 +45,12 @@ func (f *infoCmd) Exec(args []string) error {
return err return err
} }
for _, ff := range files { for _, ff := range files {
fmt.Println(pkger.NewFileInfo(ff)) fmt.Println(pkging.NewFileInfo(ff))
} }
continue continue
} }
fmt.Println(pkger.NewFileInfo(fi)) fmt.Println(pkging.NewFileInfo(fi))
} }
return nil return nil

View File

@ -8,6 +8,7 @@ import (
"github.com/markbates/pkger" "github.com/markbates/pkger"
"github.com/markbates/pkger/parser" "github.com/markbates/pkger/parser"
"github.com/markbates/pkger/pkging"
) )
const outName = "pkged.go" const outName = "pkged.go"
@ -24,12 +25,12 @@ func (e *packCmd) Name() string {
} }
func (e *packCmd) Exec(args []string) error { func (e *packCmd) Exec(args []string) error {
info, err := pkger.Stat() info, err := pkger.Current()
if err != nil { if err != nil {
return err return err
} }
res, err := parser.Parse(info.Dir) res, err := parser.Parse(info)
if err != nil { if err != nil {
return err return err
} }
@ -116,7 +117,7 @@ func (e *packCmd) Flags() *flag.FlagSet {
return e.FlagSet return e.FlagSet
} }
func Package(out string, paths []pkger.Path) error { func Package(out string, paths []pkging.Path) error {
os.RemoveAll(out) os.RemoveAll(out)
f, err := os.Create(out) f, err := os.Create(out)
@ -124,7 +125,7 @@ func Package(out string, paths []pkger.Path) error {
return err return err
} }
c, err := pkger.Stat() c, err := pkger.Current()
if err != nil { if err != nil {
return err return err
} }
@ -132,9 +133,10 @@ func Package(out string, paths []pkger.Path) error {
fmt.Fprintf(f, "import \"github.com/markbates/pkger\"\n\n") fmt.Fprintf(f, "import \"github.com/markbates/pkger\"\n\n")
fmt.Fprintf(f, "var _ = pkger.Unpack(`") fmt.Fprintf(f, "var _ = pkger.Unpack(`")
if err := pkger.Pack(f, paths); err != nil { // TODO
return err // if err := pkger.Pack(f, paths); err != nil {
} // return err
// }
fmt.Fprintf(f, "`)\n") fmt.Fprintf(f, "`)\n")

View File

@ -48,10 +48,11 @@ func (s *serveCmd) Exec(args []string) error {
return err return err
} }
ex := append(defaultExcludes, s.excludes...) // TODO
if err := pkger.Exclude(f, ex...); err != nil { // ex := append(defaultExcludes, s.excludes...)
return err // if err := pkger.Exclude(f, ex...); err != nil {
} // return err
// }
defer f.Close() defer f.Close()
fmt.Println(f.Path()) fmt.Println(f.Path())

View File

@ -8,7 +8,10 @@ import (
) )
func walk(args []string) error { func walk(args []string) error {
err := pkger.Walk(".", func(path pkger.Path, info os.FileInfo) error { err := pkger.Walk(".", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fmt.Println(path) fmt.Println(path)
return nil return nil
}) })

View File

@ -1,36 +0,0 @@
package pkger
import (
"path/filepath"
"time"
)
func Create(name string) (*File, error) {
pt, err := Parse(name)
if err != nil {
return nil, err
}
her, err := Info(pt.Pkg)
if err != nil {
return nil, err
}
f := &File{
path: pt,
her: her,
info: &FileInfo{
name: pt.Name,
mode: 0666,
modTime: time.Now(),
virtual: true,
},
}
filesCache.Store(pt, f)
dir := filepath.Dir(pt.Name)
if err := MkdirAll(dir, 0644); err != nil {
return nil, err
}
return f, nil
}

View File

@ -1,55 +0,0 @@
package pkger
import (
"io"
"os"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func Test_Create(t *testing.T) {
r := require.New(t)
f, err := Create("/hello.txt")
r.NoError(err)
r.NotNil(f)
fi, err := f.Stat()
r.NoError(err)
r.Equal("/hello.txt", fi.Name())
r.Equal(os.FileMode(0666), fi.Mode())
r.NotZero(fi.ModTime())
her := f.her
r.NotZero(her)
r.Equal("github.com/markbates/pkger", her.ImportPath)
}
func Test_Create_Write(t *testing.T) {
r := require.New(t)
f, err := Create("/hello.txt")
r.NoError(err)
r.NotNil(f)
fi, err := f.Stat()
r.NoError(err)
r.Zero(fi.Size())
r.Equal("/hello.txt", fi.Name())
mt := fi.ModTime()
r.NotZero(mt)
sz, err := io.Copy(f, strings.NewReader(radio))
r.NoError(err)
r.Equal(int64(1381), sz)
r.NoError(f.Close())
r.Equal(int64(1381), fi.Size())
r.NotZero(fi.ModTime())
r.NotEqual(mt, fi.ModTime())
}

55
dir.go
View File

@ -1,55 +0,0 @@
package pkger
import (
"os"
"path/filepath"
"time"
)
func MkdirAll(p string, perm os.FileMode) error {
path, err := Parse(p)
if err != nil {
return err
}
root := path.Name
cur, err := Stat()
if err != nil {
return err
}
for root != "" && root != "/" && root != "\\" {
pt := Path{
Pkg: path.Pkg,
Name: root,
}
if _, ok := filesCache.Load(pt); ok {
root = filepath.Dir(root)
continue
}
f := &File{
path: pt,
her: cur,
info: &FileInfo{
name: pt.Name,
mode: 0666,
modTime: time.Now(),
virtual: true,
},
}
if err != nil {
return err
}
f.info.isDir = true
f.info.mode = perm
f.info.virtual = true
if err := f.Close(); err != nil {
return err
}
filesCache.Store(pt, f)
root = filepath.Dir(root)
}
return nil
}

View File

@ -1,5 +1,12 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -8,5 +15,7 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

179
file.go
View File

@ -1,179 +0,0 @@
package pkger
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/markbates/pkger/here"
)
const timeFmt = time.RFC3339Nano
var _ http.File = &File{}
type File struct {
info *FileInfo
her here.Info
path Path
data []byte
parent Path
writer *bytes.Buffer
reader io.Reader
excludes []string
}
func (f *File) Seek(offset int64, whence int) (int64, error) {
if sk, ok := f.reader.(io.Seeker); ok {
return sk.Seek(offset, whence)
}
return 0, nil
}
func (f *File) Close() error {
defer func() {
f.reader = nil
f.writer = nil
}()
if f.reader != nil {
if c, ok := f.reader.(io.Closer); ok {
if err := c.Close(); err != nil {
return err
}
}
}
if f.writer == nil {
return nil
}
f.data = f.writer.Bytes()
fi := f.info
fi.size = int64(len(f.data))
fi.modTime = time.Now()
f.info = fi
return nil
}
func (f *File) Read(p []byte) (int, error) {
if len(f.data) > 0 && f.reader == nil {
f.reader = bytes.NewReader(f.data)
}
if f.reader != nil {
return f.reader.Read(p)
}
of, err := f.her.Open(f.FilePath())
if err != nil {
return 0, err
}
f.reader = of
return f.reader.Read(p)
}
func (f *File) Write(b []byte) (int, error) {
if f.writer == nil {
f.writer = &bytes.Buffer{}
}
i, err := f.writer.Write(b)
return i, err
}
func (f File) Info() here.Info {
return f.her
}
func (f File) Stat() (os.FileInfo, error) {
if f.info == nil {
return nil, os.ErrNotExist
}
return f.info, nil
}
func (f File) Name() string {
return f.info.Name()
}
func (f File) FilePath() string {
return f.her.FilePath(f.Name())
}
func (f File) Path() Path {
return f.path
}
func (f File) String() string {
return f.Path().String()
}
func (f File) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
if st.Flag('+') {
b, err := json.MarshalIndent(f, "", " ")
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
fmt.Fprint(st, string(b))
return
}
fmt.Fprint(st, f.String())
case 'q':
fmt.Fprintf(st, "%q", f.String())
default:
fmt.Fprint(st, f.String())
}
}
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
var infos []os.FileInfo
err := Walk(f.Name(), func(pt Path, info os.FileInfo) error {
if count > 0 && len(infos) == count {
return io.EOF
}
for _, x := range f.excludes {
rx, err := regexp.Compile(x)
if err != nil {
return err
}
if rx.MatchString(pt.Name) {
if info.IsDir() {
return filepath.SkipDir
}
return nil
}
}
if pt.Name == f.parent.Name {
return nil
}
if f.parent.Name != "/" {
info = WithName(strings.TrimPrefix(info.Name(), f.parent.Name), info)
}
infos = append(infos, info)
return nil
})
if err != nil {
if _, ok := err.(*os.PathError); ok {
return infos, nil
}
if err != io.EOF {
return nil, err
}
}
return infos, nil
}

View File

@ -1,139 +0,0 @@
package pkger
import (
"encoding/json"
"fmt"
"os"
"strings"
"time"
)
type FileInfo struct {
name string
size int64
mode os.FileMode
modTime time.Time
isDir bool
virtual bool
sys interface{}
}
func (f *FileInfo) String() string {
b, _ := json.MarshalIndent(f, "", " ")
return string(b)
}
func (f *FileInfo) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"name": f.name,
"size": f.size,
"mode": f.mode,
"modTime": f.modTime.Format(timeFmt),
"isDir": f.isDir,
"virtual": true,
"sys": f.sys,
})
}
func (f *FileInfo) UnmarshalJSON(b []byte) error {
m := map[string]interface{}{}
if err := json.Unmarshal(b, &m); err != nil {
return err
}
var ok bool
f.name, ok = m["name"].(string)
if !ok {
return fmt.Errorf("could not determine name %q", m["name"])
}
size, ok := m["size"].(float64)
if !ok {
return fmt.Errorf("could not determine size %q", m["size"])
}
f.size = int64(size)
mode, ok := m["mode"].(float64)
if !ok {
return fmt.Errorf("could not determine mode %q", m["mode"])
}
f.mode = os.FileMode(mode)
modTime, ok := m["modTime"].(string)
if !ok {
return fmt.Errorf("could not determine modTime %q", m["modTime"])
}
t, err := time.Parse(timeFmt, modTime)
if err != nil {
return err
}
f.modTime = t
f.isDir, ok = m["isDir"].(bool)
if !ok {
return fmt.Errorf("could not determine isDir %q", m["isDir"])
}
f.sys = m["sys"]
f.virtual = true
return nil
}
func (f *FileInfo) Name() string {
return f.name
}
func (f *FileInfo) Size() int64 {
return f.size
}
func (f *FileInfo) Mode() os.FileMode {
return f.mode
}
func (f *FileInfo) ModTime() time.Time {
return f.modTime
}
func (f *FileInfo) IsDir() bool {
return f.isDir
}
func (f *FileInfo) Sys() interface{} {
return f.sys
}
var _ os.FileInfo = &FileInfo{}
func NewFileInfo(info os.FileInfo) *FileInfo {
fi := &FileInfo{
name: cleanName(info.Name()),
size: info.Size(),
mode: info.Mode(),
modTime: info.ModTime(),
isDir: info.IsDir(),
sys: info.Sys(),
}
return fi
}
func WithName(name string, info os.FileInfo) *FileInfo {
if ft, ok := info.(*FileInfo); ok {
ft.name = cleanName(name)
return ft
}
fo := NewFileInfo(info)
fo.name = cleanName(name)
return fo
}
func cleanName(s string) string {
if strings.Contains(s, "\\") {
s = strings.Replace(s, "\\", "/", -1)
}
if !strings.HasPrefix(s, "/") {
s = "/" + s
}
return s
}

View File

@ -1,108 +0,0 @@
package pkger
import (
"encoding/json"
"io"
"io/ioutil"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func Test_File_Open(t *testing.T) {
r := require.New(t)
f, err := Open("/file_test.go")
r.NoError(err)
r.Equal("/file_test.go", f.Name())
b, err := ioutil.ReadAll(f)
r.NoError(err)
r.Contains(string(b), "Test_File_Open")
r.NoError(f.Close())
}
func Test_File_Open_Dir(t *testing.T) {
r := require.New(t)
f, err := Open("/cmd")
r.NoError(err)
r.Equal("/cmd", f.Name())
r.NoError(f.Close())
}
func Test_File_Read_Memory(t *testing.T) {
r := require.New(t)
f, err := Open("/file_test.go")
r.NoError(err)
f.data = []byte("hi!")
r.Equal("/file_test.go", f.Name())
b, err := ioutil.ReadAll(f)
r.NoError(err)
r.Equal(string(b), "hi!")
r.NoError(f.Close())
}
func Test_File_Write(t *testing.T) {
r := require.New(t)
f, err := Create("/hello.txt")
r.NoError(err)
r.NotNil(f)
fi, err := f.Stat()
r.NoError(err)
r.Zero(fi.Size())
r.Equal("/hello.txt", fi.Name())
mt := fi.ModTime()
r.NotZero(mt)
sz, err := io.Copy(f, strings.NewReader(radio))
r.NoError(err)
r.Equal(int64(1381), sz)
// because windows can't handle the time precisely
// enough, we have to *force* just a smidge of time
// to ensure the two ModTime's are different.
// i know, i hate it too.
time.Sleep(time.Millisecond)
r.NoError(f.Close())
r.Equal(int64(1381), fi.Size())
r.NotZero(fi.ModTime())
r.NotEqual(mt, fi.ModTime())
}
func Test_File_JSON(t *testing.T) {
r := require.New(t)
f, err := createFile("/radio.radio")
r.NoError(err)
r.NotNil(f)
bi, err := f.Stat()
r.NoError(err)
mj, err := json.Marshal(f)
r.NoError(err)
f2 := &File{}
r.NoError(json.Unmarshal(mj, f2))
ai, err := f2.Stat()
r.NoError(err)
r.Equal(bi.Size(), ai.Size())
r.Equal(string(f.data), string(f2.data))
}

View File

@ -1,144 +0,0 @@
// Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
package pkger
import (
"encoding/json"
"fmt"
"sort"
"sync"
)
// filesMap wraps sync.Map and uses the following types:
// key: Path
// value: *File
type filesMap struct {
data *sync.Map
once *sync.Once
}
func (m *filesMap) Data() *sync.Map {
if m.once == nil {
m.once = &sync.Once{}
}
m.once.Do(func() {
if m.data == nil {
m.data = &sync.Map{}
}
})
return m.data
}
func (m *filesMap) MarshalJSON() ([]byte, error) {
var err error
mm := map[string]interface{}{}
m.Data().Range(func(key, value interface{}) bool {
var b []byte
b, err = json.Marshal(key)
if err != nil {
return false
}
mm[string(b)] = value
return true
})
if err != nil {
return nil, err
}
return json.Marshal(mm)
}
func (m *filesMap) UnmarshalJSON(b []byte) error {
mm := map[string]*File{}
if err := json.Unmarshal(b, &mm); err != nil {
return err
}
for k, v := range mm {
var pt Path
if err := json.Unmarshal([]byte(k), &pt); err != nil {
return err
}
m.Store(pt, v)
}
return nil
}
// Delete the key from the map
func (m *filesMap) Delete(key Path) {
m.Data().Delete(key)
}
// Load the key from the map.
// Returns *File or bool.
// A false return indicates either the key was not found
// or the value is not of type *File
func (m *filesMap) Load(key Path) (*File, bool) {
i, ok := m.Data().Load(key)
if !ok {
return nil, false
}
s, ok := i.(*File)
return s, ok
}
// LoadOrStore will return an existing key or
// store the value if not already in the map
func (m *filesMap) LoadOrStore(key Path, value *File) (*File, bool) {
i, _ := m.Data().LoadOrStore(key, value)
s, ok := i.(*File)
return s, ok
}
// LoadOr will return an existing key or
// run the function and store the results
func (m *filesMap) LoadOr(key Path, fn func(*filesMap) (*File, bool)) (*File, bool) {
i, ok := m.Load(key)
if ok {
return i, ok
}
i, ok = fn(m)
if ok {
m.Store(key, i)
return i, ok
}
return i, false
}
// Range over the *File values in the map
func (m *filesMap) Range(f func(key Path, value *File) bool) {
m.Data().Range(func(k, v interface{}) bool {
key, ok := k.(Path)
if !ok {
return false
}
value, ok := v.(*File)
if !ok {
return false
}
return f(key, value)
})
}
// Store a *File in the map
func (m *filesMap) Store(key Path, value *File) {
m.Data().Store(key, value)
}
// Keys returns a list of keys in the map
func (m *filesMap) Keys() []Path {
var keys []Path
m.Range(func(key Path, value *File) bool {
keys = append(keys, key)
return true
})
sort.Slice(keys, func(a, b int) bool {
return keys[a].String() <= keys[b].String()
})
return keys
}
func (m *filesMap) String() string {
return fmt.Sprintf("%v", m.Keys())
}

View File

@ -1,6 +0,0 @@
package pkger
func Exclude(fl *File, excludes ...string) error {
fl.excludes = append(fl.excludes, excludes...)
return nil
}

3
go.mod
View File

@ -3,6 +3,9 @@ module github.com/markbates/pkger
go 1.13 go 1.13
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/markbates/errx v1.1.0 github.com/markbates/errx v1.1.0
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
) )

9
go.sum
View File

@ -1,5 +1,12 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -9,5 +16,7 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

17
info.go
View File

@ -1,17 +0,0 @@
package pkger
import "github.com/markbates/pkger/here"
func Info(p string) (here.Info, error) {
info, ok := infosCache.Load(p)
if ok {
return info, nil
}
info, err := here.Package(p)
if err != nil {
return info, err
}
infosCache.Store(p, info)
return info, nil
}

View File

@ -1,126 +0,0 @@
// Code generated by github.com/markbates/pkger/mapgen. DO NOT EDIT.
package pkger
import (
"encoding/json"
"fmt"
"sort"
"sync"
"github.com/markbates/pkger/here"
)
// infosMap wraps sync.Map and uses the following types:
// key: string
// value: here.Info
type infosMap struct {
data *sync.Map
once *sync.Once
}
func (m *infosMap) Data() *sync.Map {
if m.once == nil {
m.once = &sync.Once{}
}
m.once.Do(func() {
if m.data == nil {
m.data = &sync.Map{}
}
})
return m.data
}
func (m *infosMap) MarshalJSON() ([]byte, error) {
mm := map[string]interface{}{}
m.data.Range(func(key, value interface{}) bool {
mm[fmt.Sprintf("%s", key)] = value
return true
})
return json.Marshal(mm)
}
func (m *infosMap) UnmarshalJSON(b []byte) error {
mm := map[string]here.Info{}
if err := json.Unmarshal(b, &mm); err != nil {
return err
}
for k, v := range mm {
m.Store(k, v)
}
return nil
}
// Delete the key from the map
func (m *infosMap) Delete(key string) {
m.Data().Delete(key)
}
// Load the key from the map.
// Returns here.Info or bool.
// A false return indicates either the key was not found
// or the value is not of type here.Info
func (m *infosMap) Load(key string) (here.Info, bool) {
m.Data()
i, ok := m.data.Load(key)
if !ok {
return here.Info{}, false
}
s, ok := i.(here.Info)
return s, ok
}
// LoadOrStore will return an existing key or
// store the value if not already in the map
func (m *infosMap) LoadOrStore(key string, value here.Info) (here.Info, bool) {
i, _ := m.Data().LoadOrStore(key, value)
s, ok := i.(here.Info)
return s, ok
}
// LoadOr will return an existing key or
// run the function and store the results
func (m *infosMap) LoadOr(key string, fn func(*infosMap) (here.Info, bool)) (here.Info, bool) {
i, ok := m.Load(key)
if ok {
return i, ok
}
i, ok = fn(m)
if ok {
m.Store(key, i)
return i, ok
}
return i, false
}
// Range over the here.Info values in the map
func (m *infosMap) Range(f func(key string, value here.Info) bool) {
m.Data().Range(func(k, v interface{}) bool {
key, ok := k.(string)
if !ok {
return false
}
value, ok := v.(here.Info)
if !ok {
return false
}
return f(key, value)
})
}
// Store a here.Info in the map
func (m *infosMap) Store(key string, value here.Info) {
m.Data().Store(key, value)
}
// Keys returns a list of keys in the map
func (m *infosMap) Keys() []string {
var keys []string
m.Range(func(key string, value here.Info) bool {
keys = append(keys, key)
return true
})
sort.Strings(keys)
return keys
}

83
json.go
View File

@ -1,83 +0,0 @@
package pkger
import (
"encoding/json"
"fmt"
"io/ioutil"
"github.com/markbates/pkger/here"
)
type jason struct {
Files *filesMap `json:"files"`
Infos *infosMap `json:"infos"`
Paths *pathsMap `json:"paths"`
CurrentInfo here.Info `json:"current_info"`
}
func (f File) MarshalJSON() ([]byte, error) {
m := map[string]interface{}{}
m["info"] = f.info
m["her"] = f.her
m["path"] = f.path
m["data"] = f.data
m["parent"] = f.parent
if !f.info.virtual {
if len(f.data) == 0 && !f.info.IsDir() {
b, err := ioutil.ReadAll(&f)
if err != nil {
return nil, err
}
m["data"] = b
}
}
return json.Marshal(m)
}
func (f *File) UnmarshalJSON(b []byte) error {
m := map[string]json.RawMessage{}
if err := json.Unmarshal(b, &m); err != nil {
return err
}
info, ok := m["info"]
if !ok {
return fmt.Errorf("missing info")
}
f.info = &FileInfo{}
if err := json.Unmarshal(info, f.info); err != nil {
return err
}
her, ok := m["her"]
if !ok {
return fmt.Errorf("missing her")
}
if err := json.Unmarshal(her, &f.her); err != nil {
return err
}
path, ok := m["path"]
if !ok {
return fmt.Errorf("missing path")
}
if err := json.Unmarshal(path, &f.path); err != nil {
return err
}
parent, ok := m["parent"]
if !ok {
return fmt.Errorf("missing parent")
}
if err := json.Unmarshal(parent, &f.parent); err != nil {
return err
}
if err := json.Unmarshal(m["data"], &f.data); err != nil {
return err
}
return nil
}

79
open.go
View File

@ -1,79 +0,0 @@
package pkger
import (
"net/http"
"os"
"path"
"path/filepath"
"strings"
)
func (f *File) Open(name string) (http.File, error) {
pt, err := Parse(name)
if err != nil {
return nil, err
}
if pt == f.path {
return f, nil
}
pt.Name = path.Join(f.Path().Name, pt.Name)
di, err := Open(pt.String())
if err != nil {
return nil, err
}
fi, err := di.Stat()
if err != nil {
return nil, err
}
if fi.IsDir() {
di.parent = f.path
di.excludes = f.excludes
}
return di, nil
}
func Open(name string) (*File, error) {
pt, err := Parse(name)
if err != nil {
return nil, err
}
f, ok := filesCache.Load(pt)
if !ok {
return openDisk(pt)
}
nf := &File{
info: WithName(f.info.Name(), f.info),
path: f.path,
data: f.data,
her: f.her,
}
return nf, nil
}
func openDisk(pt Path) (*File, error) {
info, err := Info(pt.Pkg)
if err != nil {
return nil, err
}
fp := info.Dir
if len(pt.Name) > 0 {
fp = filepath.Join(fp, pt.Name)
}
fi, err := os.Stat(fp)
if err != nil {
return nil, err
}
f := &File{
info: WithName(strings.TrimPrefix(pt.Name, "/"), NewFileInfo(fi)),
her: info,
path: pt,
}
return f, nil
}

View File

@ -1,124 +0,0 @@
package pkger
// func Test_Open_File(t *testing.T) {
// r := require.New(t)
//
// f, err := Open(".")
// r.NoError(err)
//
// ts := httptest.NewServer(http.FileServer(f))
// defer ts.Close()
//
// res, err := http.Get(ts.URL + "/cmd/pkger/main.go")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, err := ioutil.ReadAll(res.Body)
// r.NoError(err)
// r.Contains(string(b), "does not compute")
//
// r.NoError(f.Close())
// }
//
// func Test_Open_Dir(t *testing.T) {
// r := require.New(t)
//
// f, err := Open("/")
// r.NoError(err)
//
// ts := httptest.NewServer(http.FileServer(f))
// defer ts.Close()
//
// res, err := http.Get(ts.URL + "/cmd/pkger")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, err := ioutil.ReadAll(res.Body)
// r.NoError(err)
// r.Contains(string(b), `<a href="/cmd/pkger/main.go">/cmd/pkger/main.go</a>`)
//
// r.NoError(f.Close())
// }
//
// func Test_Open_File_Memory(t *testing.T) {
// r := require.New(t)
//
// f, err := Create("/suit/case.txt")
// r.NoError(err)
// f.Write([]byte(radio))
// r.NoError(f.Close())
//
// r.Equal([]byte(radio), f.data)
// r.Contains(string(f.data), "I wanna bite the hand that feeds me")
//
// dir, err := Open("/")
// r.NoError(err)
// defer dir.Close()
//
// ts := httptest.NewServer(http.FileServer(dir))
// defer ts.Close()
//
// res, err := http.Get(ts.URL + "/suit/case.txt")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, _ := ioutil.ReadAll(res.Body)
// // r.NoError(err)
// r.Contains(string(b), "I wanna bite the hand that feeds me")
//
// }
//
// func Test_Open_Dir_StripPrefix(t *testing.T) {
// r := require.New(t)
//
// ts := httptest.NewServer(http.StripPrefix("/assets/", http.FileServer(http.Dir("./testdata/public"))))
// defer ts.Close()
//
// res, err := http.Get(ts.URL + "/assets/radio.radio")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, _ := ioutil.ReadAll(res.Body)
// // r.NoError(err)
// r.Contains(string(b), "I wanna bite the hand that feeds me")
//
// res, err = http.Get(ts.URL + "/assets/")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, _ = ioutil.ReadAll(res.Body)
// // r.NoError(err)
// r.Contains(string(b), `<a href="radio.radio">radio.radio</a>`)
// }
//
// func Test_Open_Dir_Memory_StripPrefix(t *testing.T) {
// r := require.New(t)
//
// err := MkdirAll("/testdata/public", 0755)
// r.NoError(err)
//
// dir, err := Open("/testdata/public")
// r.NoError(err)
// defer dir.Close()
//
// ts := httptest.NewServer(http.StripPrefix("/assets/", http.FileServer(dir)))
// defer ts.Close()
//
// res, err := http.Get(ts.URL + "/assets/radio.radio")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, _ := ioutil.ReadAll(res.Body)
// // r.NoError(err)
// r.Contains(string(b), "I wanna bite the hand that feeds me")
//
// res, err = http.Get(ts.URL + "/assets/")
// r.NoError(err)
// r.Equal(200, res.StatusCode)
//
// b, _ = ioutil.ReadAll(res.Body)
// // r.NoError(err)
// r.Contains(string(b), `<a href="/radio.radio">/radio.radio</a>`)
// r.NotContains(string(b), `/public`)
// r.NotContains(string(b), `//`)
// }

View File

@ -9,20 +9,15 @@ import (
"github.com/markbates/pkger" "github.com/markbates/pkger"
"github.com/markbates/pkger/here" "github.com/markbates/pkger/here"
"github.com/markbates/pkger/pkging"
) )
var DefaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "_fixtures", "testdata"} var DefaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "_fixtures", "testdata"}
func Parse(name string) (Results, error) { func Parse(cur here.Info) (Results, error) {
var r Results var r Results
c, err := pkger.Stat()
if err != nil {
return r, err
}
if name == "" { name := cur.ImportPath
name = c.ImportPath
}
pt, err := pkger.Parse(name) pt, err := pkger.Parse(name)
if err != nil { if err != nil {
@ -36,7 +31,7 @@ func Parse(name string) (Results, error) {
return r, err return r, err
} }
m := map[pkger.Path]bool{} m := map[pkging.Path]bool{}
root := r.Path.Name root := r.Path.Name
if !strings.HasPrefix(root, string(filepath.Separator)) { if !strings.HasPrefix(root, string(filepath.Separator)) {
@ -117,7 +112,7 @@ func Parse(name string) (Results, error) {
return nil return nil
}) })
var found []pkger.Path var found []pkging.Path
for k := range m { for k := range m {
if len(k.String()) == 0 { if len(k.String()) == 0 {
@ -133,8 +128,8 @@ func Parse(name string) (Results, error) {
return r, err return r, err
} }
func sourceFiles(pt pkger.Path) ([]pkger.Path, error) { func sourceFiles(pt pkging.Path) ([]pkging.Path, error) {
var res []pkger.Path var res []pkging.Path
her, err := pkger.Info(pt.Pkg) her, err := pkger.Info(pt.Pkg)
@ -177,7 +172,7 @@ func sourceFiles(pt pkger.Path) ([]pkger.Path, error) {
n := strings.TrimPrefix(p, her.Dir) n := strings.TrimPrefix(p, her.Dir)
n = strings.Replace(n, "\\", "/", -1) n = strings.Replace(n, "\\", "/", -1)
pt := pkger.Path{ pt := pkging.Path{
Name: n, Name: n,
} }
res = append(res, pt) res = append(res, pt)
@ -188,6 +183,6 @@ func sourceFiles(pt pkger.Path) ([]pkger.Path, error) {
} }
type Results struct { type Results struct {
Paths []pkger.Path Paths []pkging.Path
Path pkger.Path Path pkging.Path
} }

View File

@ -1,22 +1,23 @@
package parser package parser
import ( import (
"os"
"path/filepath" "path/filepath"
"sort" "sort"
"testing" "testing"
"github.com/markbates/pkger/here"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func Test_Parser(t *testing.T) { func Test_Parser(t *testing.T) {
r := require.New(t) r := require.New(t)
pwd, err := os.Getwd()
r.NoError(err)
r.NoError(os.Chdir(filepath.Join("..", "examples", "app")))
defer os.Chdir(pwd)
res, err := Parse("") ch := filepath.Join("..", "examples", "app")
info := here.Info{
Dir: ch,
ImportPath: "github.com/markbates/pkger/examples/app",
}
res, err := Parse(info)
r.NoError(err) r.NoError(err)

View File

@ -8,11 +8,12 @@ import (
"github.com/markbates/pkger" "github.com/markbates/pkger"
"github.com/markbates/pkger/here" "github.com/markbates/pkger/here"
"github.com/markbates/pkger/pkging"
) )
type visitor struct { type visitor struct {
File string File string
Found map[pkger.Path]bool Found map[pkging.Path]bool
info here.Info info here.Info
errors []error errors []error
} }
@ -20,12 +21,12 @@ type visitor struct {
func newVisitor(p string, info here.Info) (*visitor, error) { func newVisitor(p string, info here.Info) (*visitor, error) {
return &visitor{ return &visitor{
File: p, File: p,
Found: map[pkger.Path]bool{}, Found: map[pkging.Path]bool{},
info: info, info: info,
}, nil }, nil
} }
func (v *visitor) Run() ([]pkger.Path, error) { func (v *visitor) Run() ([]pkging.Path, error) {
pf, err := parseFile(v.File) pf, err := parseFile(v.File)
if err != nil { if err != nil {
return nil, fmt.Errorf("%s: %v", v.File, err) return nil, fmt.Errorf("%s: %v", v.File, err)
@ -33,7 +34,7 @@ func (v *visitor) Run() ([]pkger.Path, error) {
ast.Walk(v, pf.Ast) ast.Walk(v, pf.Ast)
var found []pkger.Path var found []pkging.Path
for k := range v.Found { for k := range v.Found {
found = append(found, k) found = append(found, k)

99
path.go
View File

@ -1,99 +0,0 @@
package pkger
import (
"encoding/json"
"fmt"
"os"
"regexp"
"strings"
)
type Path struct {
Pkg string `json:"pkg"`
Name string `json:"name"`
}
func Parse(p string) (Path, error) {
p = strings.Replace(p, "\\", "/", -1)
pt, ok := pathsCache.Load(p)
if ok {
return pt, nil
}
if len(p) == 0 {
return build(p, "", "")
}
res := pathrx.FindAllStringSubmatch(p, -1)
if len(res) == 0 {
return pt, fmt.Errorf("could not parse %q", p)
}
matches := res[0]
if len(matches) != 4 {
return pt, fmt.Errorf("could not parse %q", p)
}
return build(p, matches[1], matches[3])
}
func (p Path) String() string {
if p.Name == "" {
p.Name = "/"
}
return fmt.Sprintf("%s:%s", p.Pkg, p.Name)
}
func (p Path) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
if st.Flag('+') {
b, err := json.MarshalIndent(p, "", " ")
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
fmt.Fprint(st, string(b))
return
}
fmt.Fprint(st, p.String())
case 'q':
fmt.Fprintf(st, "%q", p.String())
default:
fmt.Fprint(st, p.String())
}
}
var pathrx = regexp.MustCompile("([^:]+)(:(/.+))?")
func build(p, pkg, name string) (Path, error) {
pt := Path{
Pkg: pkg,
Name: name,
}
current, err := Stat()
if err != nil {
return pt, err
}
if strings.HasPrefix(pt.Pkg, "/") || len(pt.Pkg) == 0 {
pt.Name = pt.Pkg
pt.Pkg = current.ImportPath
}
if len(pt.Name) == 0 {
pt.Name = "/"
}
if pt.Pkg == pt.Name {
pt.Pkg = current.ImportPath
pt.Name = "/"
}
if !strings.HasPrefix(pt.Name, "/") {
pt.Name = "/" + pt.Name
}
pathsCache.Store(p, pt)
return pt, nil
}

View File

@ -1,52 +0,0 @@
package pkger
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_Path_String(t *testing.T) {
table := []struct {
in Path
out string
}{
{in: Path{}, out: ":/"},
{in: Path{Pkg: curPkg}, out: curPkg + ":/"},
{in: Path{Pkg: curPkg, Name: "/foo.go"}, out: curPkg + ":/foo.go"},
{in: Path{Name: "/foo.go"}, out: ":/foo.go"},
{in: Path{Pkg: "github.com/markbates/pkger/internal/examples/app"}, out: "github.com/markbates/pkger/internal/examples/app:/"},
}
for _, tt := range table {
t.Run(tt.in.String(), func(st *testing.T) {
r := require.New(st)
r.Equal(tt.out, tt.in.String())
})
}
}
func Test_Parse(t *testing.T) {
table := []struct {
in string
out Path
}{
{in: curPkg, out: Path{Pkg: curPkg, Name: "/"}},
{in: curPkg + ":/foo.go", out: Path{Pkg: curPkg, Name: "/foo.go"}},
{in: "/paths/parse_test.go", out: Path{Pkg: curPkg, Name: "/paths/parse_test.go"}},
{in: `\windows\path.go`, out: Path{Pkg: curPkg, Name: "/windows/path.go"}},
{in: "", out: Path{Pkg: curPkg, Name: "/"}},
{in: "github.com/markbates/pkger/internal/examples/app", out: Path{Pkg: "github.com/markbates/pkger/internal/examples/app", Name: "/"}},
}
for _, tt := range table {
t.Run(tt.in, func(st *testing.T) {
r := require.New(st)
pt, err := Parse(tt.in)
r.NoError(err)
r.Equal(tt.out.Pkg, pt.Pkg)
r.Equal(tt.out.Name, pt.Name)
})
}
}

View File

@ -1,123 +0,0 @@
// Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
package pkger
import (
"encoding/json"
"fmt"
"sort"
"sync"
)
// pathsMap wraps sync.Map and uses the following types:
// key: string
// value: Path
type pathsMap struct {
data *sync.Map
once *sync.Once
}
func (m *pathsMap) Data() *sync.Map {
if m.once == nil {
m.once = &sync.Once{}
}
m.once.Do(func() {
if m.data == nil {
m.data = &sync.Map{}
}
})
return m.data
}
func (m *pathsMap) MarshalJSON() ([]byte, error) {
mm := map[string]interface{}{}
m.Data().Range(func(key, value interface{}) bool {
mm[fmt.Sprintf("%s", key)] = value
return true
})
return json.Marshal(mm)
}
func (m *pathsMap) UnmarshalJSON(b []byte) error {
mm := map[string]Path{}
if err := json.Unmarshal(b, &mm); err != nil {
return err
}
for k, v := range mm {
m.Store(k, v)
}
return nil
}
// Delete the key from the map
func (m *pathsMap) Delete(key string) {
m.Data().Delete(key)
}
// Load the key from the map.
// Returns Path or bool.
// A false return indicates either the key was not found
// or the value is not of type Path
func (m *pathsMap) Load(key string) (Path, bool) {
i, ok := m.Data().Load(key)
if !ok {
return Path{}, false
}
s, ok := i.(Path)
return s, ok
}
// LoadOrStore will return an existing key or
// store the value if not already in the map
func (m *pathsMap) LoadOrStore(key string, value Path) (Path, bool) {
i, _ := m.Data().LoadOrStore(key, value)
s, ok := i.(Path)
return s, ok
}
// LoadOr will return an existing key or
// run the function and store the results
func (m *pathsMap) LoadOr(key string, fn func(*pathsMap) (Path, bool)) (Path, bool) {
i, ok := m.Load(key)
if ok {
return i, ok
}
i, ok = fn(m)
if ok {
m.Store(key, i)
return i, ok
}
return i, false
}
// Range over the Path values in the map
func (m *pathsMap) Range(f func(key string, value Path) bool) {
m.Data().Range(func(k, v interface{}) bool {
key, ok := k.(string)
if !ok {
return false
}
value, ok := v.(Path)
if !ok {
return false
}
return f(key, value)
})
}
// Store a Path in the map
func (m *pathsMap) Store(key string, value Path) {
m.Data().Store(key, value)
}
// Keys returns a list of keys in the map
func (m *pathsMap) Keys() []string {
var keys []string
m.Range(func(key string, value Path) bool {
keys = append(keys, key)
return true
})
sort.Strings(keys)
return keys
}

126
pkger.go
View File

@ -1,117 +1,29 @@
package pkger package pkger
import ( import (
"bytes"
"compress/gzip"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log" "log"
"sync"
"github.com/markbates/pkger/here" "github.com/markbates/pkger/pkging"
"github.com/markbates/pkger/pkging/stdos"
) )
var filesCache = &filesMap{} var current = func() pkging.Pkger {
var infosCache = &infosMap{} n, err := stdos.New()
var pathsCache = &pathsMap{}
var curOnce = &sync.Once{}
var currentInfo here.Info
var packed bool
var packMU = &sync.RWMutex{}
func ReadFile(s string) ([]byte, error) {
f, err := Open(s)
if err != nil { if err != nil {
return nil, err log.Fatal(err)
}
defer f.Close()
return ioutil.ReadAll(f)
} }
return n
}()
func Unpack(ind string) error { var Abs = current.Abs
packed = true var AbsPath = current.AbsPath
packMU.Lock() var Create = current.Create
defer packMU.Unlock() var Current = current.Current
b, err := hex.DecodeString(ind) var Info = current.Info
if err != nil { var MkdirAll = current.MkdirAll
log.Fatal("hex.DecodeString", err) var Open = current.Open
return err var Parse = current.Parse
} var Remove = current.Remove
var RemoveAll = current.RemoveAll
gz, err := gzip.NewReader(bytes.NewReader(b)) var Stat = current.Stat
if err != nil { var Walk = current.Walk
log.Fatal("gzip.NewReader", err)
return err
}
defer gz.Close()
var jay jason
if err := json.NewDecoder(gz).Decode(&jay); err != nil {
return err
}
jay.Files.Range(func(key Path, value *File) bool {
filesCache.Store(key, value)
return true
})
jay.Infos.Range(func(key string, value here.Info) bool {
infosCache.Store(key, value)
return true
})
jay.Paths.Range(func(key string, value Path) bool {
pathsCache.Store(key, value)
return true
})
currentInfo = jay.CurrentInfo
return nil
}
func Pack(out io.Writer, paths []Path) error {
packMU.RLock()
defer packMU.RUnlock()
bb := &bytes.Buffer{}
gz := gzip.NewWriter(bb)
defer gz.Close()
for _, p := range paths {
f, err := Open(p.String())
if err != nil {
return err
}
fi, err := f.Stat()
if err != nil {
return err
}
if fi.IsDir() {
filesCache.Store(p, f)
f.Close()
continue
}
filesCache.Store(p, f)
f.Close()
}
jay := jason{
Files: filesCache,
Infos: infosCache,
Paths: pathsCache,
CurrentInfo: currentInfo,
}
if err := json.NewEncoder(gz).Encode(jay); err != nil {
return err
}
if err := gz.Close(); err != nil {
return err
}
s := hex.EncodeToString(bb.Bytes())
_, err := fmt.Fprint(out, s)
return err
}

View File

@ -1,75 +0,0 @@
package pkger
import (
"io"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
const curPkg = "github.com/markbates/pkger"
func Test_ReadFile(t *testing.T) {
r := require.New(t)
b, err := ReadFile("/LICENSE")
r.NoError(err)
r.Contains(string(b), "MIT")
}
func createFile(p string, body ...string) (*File, error) {
if len(body) == 0 {
body = append(body, radio)
}
f, err := Create(p)
if err != nil {
return nil, err
}
_, err = io.Copy(f, strings.NewReader(strings.Join(body, "\n\n")))
if err != nil {
return nil, err
}
if err := f.Close(); err != nil {
return nil, err
}
return f, nil
}
const radio = `I was tuning in the shine on the late night dial
Doing anything my radio advised
With every one of those late night stations
Playing songs bringing tears to my eyes
I was seriously thinking about hiding the receiver
When the switch broke 'cause it's old
They're saying things that I can hardly believe
They really think we're getting out of control
Radio is a sound salvation
Radio is cleaning up the nation
They say you better listen to the voice of reason
But they don't give you any choice 'cause they think that it's treason
So you had better do as you are told
You better listen to the radio
I wanna bite the hand that feeds me
I wanna bite that hand so badly
I want to make them wish they'd never seen me
Some of my friends sit around every evening
And they worry about the times ahead
But everybody else is overwhelmed by indifference
And the promise of an early bed
You either shut up or get cut up; they don't wanna hear about it
It's only inches on the reel-to-reel
And the radio is in the hands of such a lot of fools
Tryin' to anesthetize the way that you feel
Radio is a sound salvation
Radio is cleaning up the nation
They say you better listen to the voice of reason
But they don't give you any choice 'cause they think that it's treason
So you had better do as you are told
You better listen to the radio
Wonderful radio
Marvelous radio
Wonderful radio
Radio, radio`

14
stat.go
View File

@ -1,14 +0,0 @@
package pkger
import "github.com/markbates/pkger/here"
func Stat() (here.Info, error) {
var err error
curOnce.Do(func() {
if currentInfo.IsZero() {
currentInfo, err = here.Current()
}
})
return currentInfo, err
}

View File

@ -1,4 +0,0 @@
package pkger
// Version of pkger
const Version = "v0.0.1"

70
walk.go
View File

@ -1,70 +0,0 @@
package pkger
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/markbates/pkger/here"
)
type WalkFunc func(Path, os.FileInfo) error
func Walk(p string, wf WalkFunc) error {
pt, err := Parse(p)
if err != nil {
return err
}
filesCache.Range(func(k Path, v *File) bool {
if k.Pkg != pt.Pkg {
return true
}
if !strings.HasPrefix(k.Name, pt.Name) {
return true
}
if err = wf(k, v.info); err != nil {
if err == filepath.SkipDir {
return true
}
return false
}
return true
})
if packed {
return nil
}
var info here.Info
if pt.Pkg == "." {
info, err = Stat()
if err != nil {
return err
}
pt.Pkg = info.ImportPath
}
if info.IsZero() {
info, err = Info(pt.Pkg)
if err != nil {
return fmt.Errorf("%s: %s", pt, err)
}
}
fp := filepath.Join(info.Dir, pt.Name)
err = filepath.Walk(fp, func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
path = strings.TrimPrefix(path, info.Dir)
pt, err := Parse(fmt.Sprintf("%s:%s", pt.Pkg, path))
if err != nil {
return err
}
return wf(pt, WithName(path, NewFileInfo(fi)))
})
return err
}