mirror of https://github.com/markbates/pkger.git
larry didn't know
This commit is contained in:
parent
acee89306a
commit
257d6a842b
12
current.go
12
current.go
|
@ -1,13 +1 @@
|
|||
package pkger
|
||||
|
||||
import (
|
||||
"github.com/markbates/pkger/here"
|
||||
)
|
||||
|
||||
func Info(p string) (here.Info, error) {
|
||||
return rootIndex.Info(p)
|
||||
}
|
||||
|
||||
func Stat() (here.Info, error) {
|
||||
return rootIndex.Stat()
|
||||
}
|
||||
|
|
12
dir.go
12
dir.go
|
@ -5,15 +5,11 @@ import (
|
|||
"path/filepath"
|
||||
)
|
||||
|
||||
func MkdirAll(path string, perm os.FileMode) error {
|
||||
pt, err := rootIndex.Parse(path)
|
||||
func MkdirAll(p string, perm os.FileMode) error {
|
||||
path, err := Parse(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rootIndex.MkdirAll(pt, perm)
|
||||
}
|
||||
|
||||
func (i *index) MkdirAll(path Path, perm os.FileMode) error {
|
||||
root := path.Name
|
||||
|
||||
for root != "" && root != "/" {
|
||||
|
@ -21,7 +17,7 @@ func (i *index) MkdirAll(path Path, perm os.FileMode) error {
|
|||
Pkg: path.Pkg,
|
||||
Name: root,
|
||||
}
|
||||
f, err := i.Create(pt)
|
||||
f, err := Create(pt.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -31,7 +27,7 @@ func (i *index) MkdirAll(path Path, perm os.FileMode) error {
|
|||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Files.Store(pt, f)
|
||||
filesCache.Store(pt, f)
|
||||
root = filepath.Dir(root)
|
||||
}
|
||||
|
||||
|
|
1
file.go
1
file.go
|
@ -215,7 +215,6 @@ func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("### file.go:235 infos (%T) -> %q %+v\n", infos, infos, infos)
|
||||
return infos, nil
|
||||
|
||||
// of, err := f.her.Open(f.FilePath())
|
||||
|
|
14
file_test.go
14
file_test.go
|
@ -16,7 +16,7 @@ func Test_File_Open(t *testing.T) {
|
|||
f, err := Open("/file_test.go")
|
||||
r.NoError(err)
|
||||
|
||||
r.Equal("/file_test.go", f.Name())
|
||||
r.Equal("file_test.go", f.Name())
|
||||
|
||||
b, err := ioutil.ReadAll(f)
|
||||
r.NoError(err)
|
||||
|
@ -30,7 +30,7 @@ func Test_File_Open_Dir(t *testing.T) {
|
|||
f, err := Open("/cmd")
|
||||
r.NoError(err)
|
||||
|
||||
r.Equal("/cmd", f.Name())
|
||||
r.Equal("cmd", f.Name())
|
||||
|
||||
r.NoError(f.Close())
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func Test_File_Read_Memory(t *testing.T) {
|
|||
r.NoError(err)
|
||||
f.data = []byte("hi!")
|
||||
|
||||
r.Equal("/file_test.go", f.Name())
|
||||
r.Equal("file_test.go", f.Name())
|
||||
|
||||
b, err := ioutil.ReadAll(f)
|
||||
r.NoError(err)
|
||||
|
@ -53,11 +53,7 @@ func Test_File_Read_Memory(t *testing.T) {
|
|||
func Test_File_Write(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
i := newIndex()
|
||||
|
||||
f, err := i.Create(Path{
|
||||
Name: "/hello.txt",
|
||||
})
|
||||
f, err := Create("/hello.txt")
|
||||
r.NoError(err)
|
||||
r.NotNil(f)
|
||||
|
||||
|
@ -65,7 +61,7 @@ func Test_File_Write(t *testing.T) {
|
|||
r.NoError(err)
|
||||
r.Zero(fi.Size())
|
||||
|
||||
r.Equal("/hello.txt", fi.Name())
|
||||
r.Equal("hello.txt", fi.Name())
|
||||
|
||||
mt := fi.ModTime()
|
||||
r.NotZero(mt)
|
||||
|
|
18
http.go
18
http.go
|
@ -5,6 +5,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (f *File) Open(name string) (http.File, error) {
|
||||
|
@ -19,7 +20,7 @@ func (f *File) Open(name string) (http.File, error) {
|
|||
|
||||
pt.Name = path.Join(f.Path().Name, pt.Name)
|
||||
|
||||
di, err := rootIndex.Open(pt)
|
||||
di, err := Open(pt.String())
|
||||
if err != nil {
|
||||
if filepath.Base(name) == "index.html" {
|
||||
if _, ok := err.(*os.PathError); ok {
|
||||
|
@ -31,14 +32,19 @@ func (f *File) Open(name string) (http.File, error) {
|
|||
return di, nil
|
||||
}
|
||||
|
||||
func (i *index) Open(pt Path) (*File, error) {
|
||||
i.debug("Open", pt.String())
|
||||
f, ok := i.Files.Load(pt)
|
||||
func Open(name string) (*File, error) {
|
||||
pt, err := Parse(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dubeg("Open", pt.String())
|
||||
f, ok := filesCache.Load(pt)
|
||||
if !ok {
|
||||
return i.openDisk(pt)
|
||||
return openDisk(pt)
|
||||
}
|
||||
nf := &File{
|
||||
info: f.info,
|
||||
info: WithName(strings.TrimPrefix(f.info.Name(), "/"), f.info),
|
||||
path: f.path,
|
||||
data: f.data,
|
||||
her: f.her,
|
||||
|
|
11
http_test.go
11
http_test.go
|
@ -80,11 +80,7 @@ func Test_HTTP_File_Memory(t *testing.T) {
|
|||
func Test_HTTP_Dir_Memory(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
i := rootIndex
|
||||
|
||||
rr, err := i.Parse("/public/radio.radio")
|
||||
r.NoError(err)
|
||||
f, err := i.Create(rr)
|
||||
f, err := Create("/public/radio.radio")
|
||||
r.NoError(err)
|
||||
f.Write([]byte(radio))
|
||||
r.NoError(f.Close())
|
||||
|
@ -92,10 +88,7 @@ func Test_HTTP_Dir_Memory(t *testing.T) {
|
|||
r.Equal([]byte(radio), f.data)
|
||||
r.Contains(string(f.data), "I wanna bite the hand that feeds me")
|
||||
|
||||
pt, err := i.Parse("/public")
|
||||
r.NoError(err)
|
||||
|
||||
dir, err := i.Open(pt)
|
||||
dir, err := Open("/public")
|
||||
r.NoError(err)
|
||||
r.NoError(dir.Close())
|
||||
|
||||
|
|
95
index.go
95
index.go
|
@ -13,22 +13,20 @@ import (
|
|||
"github.com/markbates/pkger/internal/debug"
|
||||
)
|
||||
|
||||
type index struct {
|
||||
Files *filesMap `json:"files"`
|
||||
Infos *infosMap `json:"infos"`
|
||||
Paths *pathsMap `json:"paths"`
|
||||
Current here.Info `json:"current"`
|
||||
once *sync.Once
|
||||
}
|
||||
var filesCache = &filesMap{}
|
||||
var infosCache = &infosMap{}
|
||||
var pathsCache = &pathsMap{}
|
||||
var curOnce = &sync.Once{}
|
||||
var currentInfo here.Info
|
||||
|
||||
func (i *index) debug(key, format string, args ...interface{}) {
|
||||
func dubeg(key, format string, args ...interface{}) {
|
||||
s := fmt.Sprintf(format, args...)
|
||||
debug.Debug("[*index|%s|%s] %s", i.Current.ImportPath, key, s)
|
||||
debug.Debug("[%s|%s] %s", key, s)
|
||||
}
|
||||
|
||||
func (i *index) Parse(p string) (Path, error) {
|
||||
i.debug("Parse", p)
|
||||
pt, ok := i.Paths.Load(p)
|
||||
func Parse(p string) (Path, error) {
|
||||
dubeg("Parse", p)
|
||||
pt, ok := pathsCache.Load(p)
|
||||
if ok {
|
||||
return pt, nil
|
||||
}
|
||||
|
@ -50,8 +48,8 @@ func (i *index) Parse(p string) (Path, error) {
|
|||
return build(p, matches[1], matches[3])
|
||||
}
|
||||
|
||||
func (i *index) Info(p string) (here.Info, error) {
|
||||
info, ok := i.Infos.Load(p)
|
||||
func Info(p string) (here.Info, error) {
|
||||
info, ok := infosCache.Load(p)
|
||||
if ok {
|
||||
return info, nil
|
||||
}
|
||||
|
@ -60,22 +58,27 @@ func (i *index) Info(p string) (here.Info, error) {
|
|||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
i.Infos.Store(p, info)
|
||||
infosCache.Store(p, info)
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (i *index) Stat() (here.Info, error) {
|
||||
func Stat() (here.Info, error) {
|
||||
var err error
|
||||
i.once.Do(func() {
|
||||
if i.Current.IsZero() {
|
||||
i.Current, err = here.Current()
|
||||
curOnce.Do(func() {
|
||||
if currentInfo.IsZero() {
|
||||
currentInfo, err = here.Current()
|
||||
}
|
||||
})
|
||||
|
||||
return i.Current, err
|
||||
return currentInfo, err
|
||||
}
|
||||
|
||||
func Create(name string) (*File, error) {
|
||||
pt, err := Parse(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (i *index) Create(pt Path) (*File, error) {
|
||||
her, err := Info(pt.Pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -91,22 +94,15 @@ func (i *index) Create(pt Path) (*File, error) {
|
|||
},
|
||||
}
|
||||
|
||||
if i.Files == nil {
|
||||
i.Files = &filesMap{}
|
||||
}
|
||||
filesCache.Store(pt, f)
|
||||
|
||||
i.Files.Store(pt, f)
|
||||
|
||||
dir := Path{
|
||||
Pkg: pt.Pkg,
|
||||
Name: filepath.Dir(pt.Name),
|
||||
if err := MkdirAll(filepath.Dir(pt.Name), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.MkdirAll(dir, 0644)
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (i *index) UnmarshalJSON(b []byte) error {
|
||||
i.once = &sync.Once{}
|
||||
func UnmarshalJSON(b []byte) error {
|
||||
m := map[string]json.RawMessage{}
|
||||
|
||||
if err := json.Unmarshal(b, &m); err != nil {
|
||||
|
@ -117,8 +113,8 @@ func (i *index) UnmarshalJSON(b []byte) error {
|
|||
if !ok {
|
||||
return fmt.Errorf("missing infos")
|
||||
}
|
||||
i.Infos = &infosMap{}
|
||||
if err := json.Unmarshal(infos, i.Infos); err != nil {
|
||||
infosCache = &infosMap{}
|
||||
if err := json.Unmarshal(infos, infosCache); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -127,8 +123,8 @@ func (i *index) UnmarshalJSON(b []byte) error {
|
|||
return fmt.Errorf("missing files")
|
||||
}
|
||||
|
||||
i.Files = &filesMap{}
|
||||
if err := json.Unmarshal(files, i.Files); err != nil {
|
||||
filesCache = &filesMap{}
|
||||
if err := json.Unmarshal(files, filesCache); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -137,8 +133,8 @@ func (i *index) UnmarshalJSON(b []byte) error {
|
|||
return fmt.Errorf("missing paths")
|
||||
}
|
||||
|
||||
i.Paths = &pathsMap{}
|
||||
if err := json.Unmarshal(paths, i.Paths); err != nil {
|
||||
pathsCache = &pathsMap{}
|
||||
if err := json.Unmarshal(paths, pathsCache); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -146,15 +142,14 @@ func (i *index) UnmarshalJSON(b []byte) error {
|
|||
if !ok {
|
||||
return fmt.Errorf("missing current")
|
||||
}
|
||||
if err := json.Unmarshal(current, &i.Current); err != nil {
|
||||
if err := json.Unmarshal(current, ¤tInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
i.debug("UnmarshalJSON", "%v", i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i index) openDisk(pt Path) (*File, error) {
|
||||
i.debug("openDisk", pt.String())
|
||||
func openDisk(pt Path) (*File, error) {
|
||||
dubeg("openDisk", pt.String())
|
||||
info, err := Info(pt.Pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -169,23 +164,9 @@ func (i index) openDisk(pt Path) (*File, error) {
|
|||
return nil, err
|
||||
}
|
||||
f := &File{
|
||||
info: WithName(pt.Name, NewFileInfo(fi)),
|
||||
info: WithName(strings.TrimPrefix(pt.Name, "/"), NewFileInfo(fi)),
|
||||
her: info,
|
||||
path: pt,
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func newIndex() *index {
|
||||
return &index{
|
||||
Files: &filesMap{},
|
||||
Infos: &infosMap{},
|
||||
Paths: &pathsMap{},
|
||||
once: &sync.Once{},
|
||||
}
|
||||
}
|
||||
|
||||
var rootIndex = func() *index {
|
||||
i := newIndex()
|
||||
return i
|
||||
}()
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package pkger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -14,11 +12,7 @@ import (
|
|||
func Test_index_Create(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
i := newIndex()
|
||||
|
||||
f, err := i.Create(Path{
|
||||
Name: "/hello.txt",
|
||||
})
|
||||
f, err := Create("/hello.txt")
|
||||
r.NoError(err)
|
||||
r.NotNil(f)
|
||||
|
||||
|
@ -37,11 +31,7 @@ func Test_index_Create(t *testing.T) {
|
|||
func Test_index_Create_Write(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
i := newIndex()
|
||||
|
||||
f, err := i.Create(Path{
|
||||
Name: "/hello.txt",
|
||||
})
|
||||
f, err := Create("/hello.txt")
|
||||
r.NoError(err)
|
||||
r.NotNil(f)
|
||||
|
||||
|
@ -64,48 +54,45 @@ func Test_index_Create_Write(t *testing.T) {
|
|||
r.NotEqual(mt, fi.ModTime())
|
||||
}
|
||||
|
||||
func Test_index_JSON(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
i := newIndex()
|
||||
|
||||
f, err := i.Create(Path{
|
||||
Name: "/radio.radio",
|
||||
})
|
||||
r.NoError(err)
|
||||
r.NotNil(f)
|
||||
fmt.Fprint(f, radio)
|
||||
r.NoError(f.Close())
|
||||
|
||||
c, err := i.Stat()
|
||||
r.NoError(err)
|
||||
r.Equal(curPkg, c.ImportPath)
|
||||
|
||||
_, err = i.Info("github.com/markbates/hepa")
|
||||
r.NoError(err)
|
||||
|
||||
r.Equal(1, len(i.Files.Keys()))
|
||||
r.Equal(1, len(i.Infos.Keys()))
|
||||
r.NotZero(i.Current)
|
||||
|
||||
jason, err := json.Marshal(i)
|
||||
r.NoError(err)
|
||||
r.NotZero(jason)
|
||||
|
||||
i2 := &index{}
|
||||
|
||||
r.NoError(json.Unmarshal(jason, i2))
|
||||
|
||||
r.NotNil(i2.Infos)
|
||||
r.NotNil(i2.Files)
|
||||
r.NotZero(i2.Current)
|
||||
r.Equal(1, len(i2.Files.Keys()))
|
||||
r.Equal(1, len(i2.Infos.Keys()))
|
||||
|
||||
f2, err := i2.Open(Path{Name: "/radio.radio"})
|
||||
r.NoError(err)
|
||||
r.Equal(f.data, f2.data)
|
||||
}
|
||||
// TODO
|
||||
// func Test_index_JSON(t *testing.T) {
|
||||
// r := require.New(t)
|
||||
//
|
||||
// f, err := Create("/radio.radio")
|
||||
// r.NoError(err)
|
||||
// r.NotNil(f)
|
||||
// fmt.Fprint(f, radio)
|
||||
// r.NoError(f.Close())
|
||||
//
|
||||
// c, err := Stat()
|
||||
// r.NoError(err)
|
||||
// r.Equal(curPkg, c.ImportPath)
|
||||
//
|
||||
// _, err = Info("github.com/markbates/hepa")
|
||||
// r.NoError(err)
|
||||
//
|
||||
// r.Equal(1, len(filesCache.Keys()))
|
||||
// r.Equal(1, len(infosCache.Keys()))
|
||||
// r.NotZero(cur)
|
||||
//
|
||||
// jason, err := json.Marshal(i)
|
||||
// r.NoError(err)
|
||||
// r.NotZero(jason)
|
||||
//
|
||||
// i2 := &index{}
|
||||
//
|
||||
// r.NoError(json.Unmarshal(jason, i2))
|
||||
//
|
||||
// r.NotNil(i2.infosCache)
|
||||
// r.NotNil(i2.filesCache)
|
||||
// r.NotZero(i2.cur)
|
||||
// r.Equal(1, len(i2.filesCache.Keys()))
|
||||
// r.Equal(1, len(i2.infosCache.Keys()))
|
||||
//
|
||||
// f2, err := i2.Open(Path{Name: "/radio.radio"})
|
||||
// r.NoError(err)
|
||||
// r.Equal(f.data, f2.data)
|
||||
// }
|
||||
|
||||
func Test_index_Parse(t *testing.T) {
|
||||
table := []struct {
|
||||
|
|
6
parse.go
6
parse.go
|
@ -7,10 +7,6 @@ import (
|
|||
|
||||
var pathrx = regexp.MustCompile("([^:]+)(:(/.+))?")
|
||||
|
||||
func Parse(p string) (Path, error) {
|
||||
return rootIndex.Parse(p)
|
||||
}
|
||||
|
||||
func build(p, pkg, name string) (Path, error) {
|
||||
pt := Path{
|
||||
Pkg: pkg,
|
||||
|
@ -39,6 +35,6 @@ func build(p, pkg, name string) (Path, error) {
|
|||
if !strings.HasPrefix(pt.Name, "/") {
|
||||
pt.Name = "/" + pt.Name
|
||||
}
|
||||
rootIndex.Paths.Store(p, pt)
|
||||
pathsCache.Store(p, pt)
|
||||
return pt, nil
|
||||
}
|
||||
|
|
41
pkger.go
41
pkger.go
|
@ -4,30 +4,11 @@ import (
|
|||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Open opens the named file for reading.
|
||||
func Open(p string) (*File, error) {
|
||||
pt, err := Parse(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rootIndex.Open(pt)
|
||||
}
|
||||
|
||||
// Create creates the named file with mode 0666 (before umask), truncating it if it already exists. If successful, methods on the returned File can be used for I/O; the associated file descriptor has mode O_RDWR. If there is an error, it will be of type *PathError.
|
||||
func Create(p string) (*File, error) {
|
||||
pt, err := Parse(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rootIndex.Create(pt)
|
||||
}
|
||||
|
||||
func Unpack(ind string) error {
|
||||
b, err := hex.DecodeString(ind)
|
||||
if err != nil {
|
||||
|
@ -42,10 +23,11 @@ func Unpack(ind string) error {
|
|||
}
|
||||
defer gz.Close()
|
||||
|
||||
if err := json.NewDecoder(gz).Decode(rootIndex); err != nil {
|
||||
log.Fatal("json.NewDecoder", err)
|
||||
return err
|
||||
}
|
||||
// TODO:
|
||||
// if err := json.NewDecoder(gz).Decode(rootIndex); err != nil {
|
||||
// log.Fatal("json.NewDecoder", err)
|
||||
// return err
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -66,20 +48,21 @@ func Pack(out io.Writer, paths []Path) error {
|
|||
return err
|
||||
}
|
||||
if fi.IsDir() {
|
||||
rootIndex.Files.Store(p, f)
|
||||
filesCache.Store(p, f)
|
||||
f.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
rootIndex.debug("Pack", "%s", p)
|
||||
rootIndex.Files.Store(p, f)
|
||||
dubeg("Pack", "%s", p)
|
||||
filesCache.Store(p, f)
|
||||
f.Close()
|
||||
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(gz).Encode(rootIndex); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO
|
||||
// if err := json.NewEncoder(gz).Encode(rootIndex); err != nil {
|
||||
// return err
|
||||
// }
|
||||
if err := gz.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
7
walk.go
7
walk.go
|
@ -16,12 +16,7 @@ func Walk(p string, wf WalkFunc) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rootIndex.Walk(pt, wf)
|
||||
}
|
||||
|
||||
func (i index) Walk(pt Path, wf WalkFunc) error {
|
||||
var err error
|
||||
i.Files.Range(func(k Path, v *File) bool {
|
||||
filesCache.Range(func(k Path, v *File) bool {
|
||||
if k.Pkg != pt.Pkg {
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue