diff --git a/cmd/pkger/go.sum b/cmd/pkger/go.sum index 9f71dc6..b2d6fa6 100644 --- a/cmd/pkger/go.sum +++ b/cmd/pkger/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= diff --git a/cmd/pkger/main.go b/cmd/pkger/main.go index 0238cf4..3412bf3 100644 --- a/cmd/pkger/main.go +++ b/cmd/pkger/main.go @@ -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 - } - if fn == nil { - log.Fatal(args) + 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) + } + os.Exit(1) } if err := fn(args[1:]); err != nil { log.Fatal(err) diff --git a/cmd/pkger/read.go b/cmd/pkger/read.go index ac1918d..832bd21 100644 --- a/cmd/pkger/read.go +++ b/cmd/pkger/read.go @@ -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 diff --git a/file.go b/file.go index 2925c7b..bba494e 100644 --- a/file.go +++ b/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 } diff --git a/file_test.go b/file_test.go new file mode 100644 index 0000000..78a25ee --- /dev/null +++ b/file_test.go @@ -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()) +} diff --git a/go.mod b/go.mod index 9ce7a9d..fade678 100644 --- a/go.mod +++ b/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 +) diff --git a/go.sum b/go.sum index 9f71dc6..b2d6fa6 100644 --- a/go.sum +++ b/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= diff --git a/http_test.go b/http_test.go new file mode 100644 index 0000000..4a2ac6e --- /dev/null +++ b/http_test.go @@ -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), `main.go`) + + r.NoError(f.Close()) +} diff --git a/index.go b/index.go index ca6acef..a162978 100644 --- a/index.go +++ b/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 { diff --git a/path.go b/path.go index ee09b66..af09b40 100644 --- a/path.go +++ b/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 { diff --git a/pkgs/current.go b/pkgs/current.go index 8b442b6..52de97d 100644 --- a/pkgs/current.go +++ b/pkgs/current.go @@ -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)) }