mirror of https://github.com/markbates/pkger.git
move me over
This commit is contained in:
parent
a40fcc3eeb
commit
0f102bc1e8
|
@ -1,2 +1,10 @@
|
|||
github.com/gobuffalo/here v0.2.0 h1:tbOsO8QVUL5MT4swc0JnqZ7IlUm09e6vXYxNSMhOYMw=
|
||||
github.com/gobuffalo/here v0.2.0/go.mod h1:2a6G14FaAKOGJMK/5UNa4Og/+iyFS5cq3MnlvFR7YDk=
|
||||
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/gobuffalo/here v0.2.1 h1:YWZUvrHnxNCIY2nnHPnF5Ob99Z5Iq29wHioLgcY+2G0=
|
||||
github.com/gobuffalo/here v0.2.1/go.mod h1:2a6G14FaAKOGJMK/5UNa4Og/+iyFS5cq3MnlvFR7YDk=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
|
|
@ -1,32 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var globalFlags = struct {
|
||||
*flag.FlagSet
|
||||
}{
|
||||
FlagSet: flag.NewFlagSet("", flag.ContinueOnError),
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
type ex func([]string) error
|
||||
|
||||
var cmds = map[string]ex{
|
||||
"walk": walk,
|
||||
"read": read,
|
||||
"info": info,
|
||||
"serve": serve,
|
||||
}
|
||||
args := os.Args[1:]
|
||||
|
||||
if len(args) == 0 {
|
||||
log.Fatal("does not compute")
|
||||
}
|
||||
|
||||
var fn ex
|
||||
switch args[0] {
|
||||
case "walk":
|
||||
fn = walk
|
||||
case "read":
|
||||
fn = read
|
||||
case "info":
|
||||
fn = info
|
||||
case "serve":
|
||||
fn = serve
|
||||
fn, ok := cmds[args[0]]
|
||||
if !ok {
|
||||
fmt.Fprintf(os.Stderr, "couldn't understand args %q\n\n", args)
|
||||
fmt.Fprintf(os.Stderr, "the following is a list of available commands:\n\n")
|
||||
for k := range cmds {
|
||||
fmt.Fprintf(os.Stderr, "\t%s\n", k)
|
||||
}
|
||||
if fn == nil {
|
||||
log.Fatal(args)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := fn(args[1:]); err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -8,29 +10,50 @@ import (
|
|||
"github.com/markbates/pkger"
|
||||
)
|
||||
|
||||
type readOptions struct {
|
||||
*flag.FlagSet
|
||||
JSON bool
|
||||
}
|
||||
|
||||
var readFlags = func() *readOptions {
|
||||
rd := &readOptions{}
|
||||
fs := flag.NewFlagSet("read", flag.ExitOnError)
|
||||
fs.BoolVar(&rd.JSON, "json", false, "print as JSON")
|
||||
rd.FlagSet = fs
|
||||
return rd
|
||||
}()
|
||||
|
||||
func read(args []string) error {
|
||||
if err := readFlags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
args = readFlags.Args()
|
||||
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
for _, a := range args {
|
||||
fmt.Printf("### cmd/pkger/read.go:16 a (%T) -> %q %+v\n", a, a, a)
|
||||
f, err := pkger.Open(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fmt.Println(f.Path())
|
||||
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
if fi.IsDir() && !readFlags.JSON {
|
||||
return fmt.Errorf("can not read a dir %s", a)
|
||||
}
|
||||
|
||||
if readFlags.JSON {
|
||||
err = json.NewEncoder(os.Stdout).Encode(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
_, err = io.Copy(os.Stdout, f)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
75
file.go
75
file.go
|
@ -3,10 +3,10 @@ package pkger
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/gobuffalo/here"
|
||||
|
@ -23,6 +23,59 @@ type File struct {
|
|||
Source io.ReadCloser
|
||||
}
|
||||
|
||||
func (f File) MarshalJSON() ([]byte, error) {
|
||||
m := map[string]interface{}{}
|
||||
m["info"] = f.info
|
||||
m["her"] = f.her
|
||||
m["path"] = f.path
|
||||
m["index"] = f.index
|
||||
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
|
||||
}
|
||||
|
||||
ind, ok := m["index"]
|
||||
if !ok {
|
||||
return fmt.Errorf("missing index")
|
||||
}
|
||||
f.index = &index{
|
||||
Files: map[Path]*File{},
|
||||
}
|
||||
if err := json.Unmarshal(ind, f.index); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *File) Open(name string) (http.File, error) {
|
||||
if f.index == nil {
|
||||
f.index = &index{
|
||||
|
@ -38,7 +91,9 @@ func (f *File) Open(name string) (http.File, error) {
|
|||
pt.Pkg = f.path.Pkg
|
||||
}
|
||||
|
||||
h := httpFile{}
|
||||
h := httpFile{
|
||||
crs: &byteCRS{bytes.NewReader(f.data)},
|
||||
}
|
||||
|
||||
if pt == f.path {
|
||||
h.File = f
|
||||
|
@ -52,18 +107,19 @@ func (f *File) Open(name string) (http.File, error) {
|
|||
}
|
||||
|
||||
if len(f.data) > 0 {
|
||||
h.crs = &byteCRS{bytes.NewReader(f.data)}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
bf, err := os.Open(h.File.Path())
|
||||
bf, err := f.her.Open(h.File.Path())
|
||||
if err != nil {
|
||||
return h, err
|
||||
}
|
||||
|
||||
fi, err := bf.Stat()
|
||||
if err != nil {
|
||||
return h, err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return h, nil
|
||||
}
|
||||
|
@ -98,12 +154,7 @@ func (f File) Name() string {
|
|||
}
|
||||
|
||||
func (f File) Path() string {
|
||||
dir := f.her.Dir
|
||||
if filepath.Base(dir) == f.Name() {
|
||||
return dir
|
||||
}
|
||||
fp := filepath.Join(dir, f.Name())
|
||||
return fp
|
||||
return f.her.FilePath(f.Name())
|
||||
}
|
||||
|
||||
func (f File) String() string {
|
||||
|
@ -119,7 +170,7 @@ func (f *File) Read(p []byte) (int, error) {
|
|||
return f.Source.Read(p)
|
||||
}
|
||||
|
||||
of, err := os.Open(f.Path())
|
||||
of, err := f.her.Open(f.Path())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -133,7 +184,7 @@ func (f *File) Read(p []byte) (int, error) {
|
|||
//
|
||||
// If n <= 0, Readdir returns all the FileInfo from the directory in a single slice. In this case, if Readdir succeeds (reads all the way to the end of the directory), it returns the slice and a nil error. If it encounters an error before the end of the directory, Readdir returns the FileInfo read until that point and a non-nil error.
|
||||
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
||||
of, err := os.Open(f.Path())
|
||||
of, err := f.her.Open(f.Path())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package pkger
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"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())
|
||||
}
|
6
go.mod
6
go.mod
|
@ -2,4 +2,8 @@ module github.com/markbates/pkger
|
|||
|
||||
go 1.12
|
||||
|
||||
require github.com/gobuffalo/here v0.2.0
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gobuffalo/here v0.2.1
|
||||
github.com/stretchr/testify v1.3.0
|
||||
)
|
||||
|
|
12
go.sum
12
go.sum
|
@ -1,2 +1,10 @@
|
|||
github.com/gobuffalo/here v0.2.0 h1:tbOsO8QVUL5MT4swc0JnqZ7IlUm09e6vXYxNSMhOYMw=
|
||||
github.com/gobuffalo/here v0.2.0/go.mod h1:2a6G14FaAKOGJMK/5UNa4Og/+iyFS5cq3MnlvFR7YDk=
|
||||
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/gobuffalo/here v0.2.1 h1:YWZUvrHnxNCIY2nnHPnF5Ob99Z5Iq29wHioLgcY+2G0=
|
||||
github.com/gobuffalo/here v0.2.1/go.mod h1:2a6G14FaAKOGJMK/5UNa4Og/+iyFS5cq3MnlvFR7YDk=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package pkger
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_HTTP_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_HTTP_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="main.go">main.go</a>`)
|
||||
|
||||
r.NoError(f.Close())
|
||||
}
|
17
index.go
17
index.go
|
@ -1,6 +1,7 @@
|
|||
package pkger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -15,6 +16,22 @@ type index struct {
|
|||
Files map[Path]*File
|
||||
}
|
||||
|
||||
func (i index) MarshalJSON() ([]byte, error) {
|
||||
m := map[string]interface{}{
|
||||
"pkg": i.Pkg,
|
||||
}
|
||||
|
||||
fm := map[string]File{}
|
||||
|
||||
for k, v := range i.Files {
|
||||
fm[k.String()] = *v
|
||||
}
|
||||
|
||||
m["files"] = fm
|
||||
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
func (i index) Walk(pt Path, wf WalkFunc) error {
|
||||
|
||||
if len(pt.Pkg) == 0 {
|
||||
|
|
4
path.go
4
path.go
|
@ -6,8 +6,8 @@ import (
|
|||
)
|
||||
|
||||
type Path struct {
|
||||
Pkg string
|
||||
Name string
|
||||
Pkg string `json:"pkg"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (p Path) String() string {
|
||||
|
|
|
@ -19,10 +19,6 @@ func Current() (here.Info, error) {
|
|||
return Dir(".")
|
||||
}
|
||||
|
||||
func Open(info here.Info, p string) (*os.File, error) {
|
||||
return os.Open(filepath.Join(info.Dir, p))
|
||||
}
|
||||
|
||||
func Stat(info here.Info, p string) (os.FileInfo, error) {
|
||||
return os.Stat(filepath.Join(info.Dir, p))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue