diff --git a/README.md b/README.md new file mode 100644 index 0000000..6733f7e --- /dev/null +++ b/README.md @@ -0,0 +1,203 @@ +# Pkger + +[`github.com/markbates/pkger`](https://godoc.org/github.com/markbates/pkger) is a tool for embedding static files into Go binaries. It will, hopefully, be a replacement for [`github.com/gobuffalo/packr/v2`](https://godoc.org/github.com/gobuffalo/packr/v2). + +## How it Works + +Pkger is powered by the dark magic of Go Modules, so they're like, totally required. + +With Go Modules pkger can resolve packages with accuracy. No more guessing and trying to +figure out build paths, GOPATHS, etc... for this tired old lad. + +With the module's path correctly resolved, it can serve as the "root" directory for that +module, and all files in that module's directory are available. + +Paths: +* Paths should use UNIX style paths: + `/cmd/pkger/main.go` +* If unspecified the path's package is assumed to be the current module. +* Packages can specified in at the beginning of a path with a `:` seperator. +github.com/markbates/pkger:/cmd/pkger/main.go +* There are no relative paths. All paths are absolute to the modules root. + +``` +"github.com/gobuffalo/buffalo:/go.mod" => $GOPATH/pkg/mod/github.com/gobuffalo/buffalo@v0.14.7/go.mod +``` + +## Usage + +Pkger's API is modeled on that of the [`os`](https://godoc.org/os) package in Go's standard library. This makes Pkger usage familiar to Go developers. + + + +```go +type Pkger interface { + Parse(p string) (Path, error) + Abs(p string) (string, error) + AbsPath(Path) (string, error) + Current() (here.Info, error) + Info(p string) (here.Info, error) + Create(name string) (File, error) + MkdirAll(p string, perm os.FileMode) error + Open(name string) (File, error) + Stat(name string) (os.FileInfo, error) + Walk(p string, wf filepath.WalkFunc) error + Remove(name string) error + RemoveAll(path string) error +} + +type File interface { + Close() error + Abs() (string, error) + Info() here.Info + Name() string + Open(name string) (http.File, error) + Path() Path + Read(p []byte) (int, error) + Readdir(count int) ([]os.FileInfo, error) + Seek(offset int64, whence int) (int64, error) + Stat() (os.FileInfo, error) + Write(b []byte) (int, error) +} +``` + +```bash +├── go.mod +├── go.sum +├── main.go +├── public +│   ├── images +│   │   ├── mark-small.png +│   │   ├── mark.png +│   │   ├── mark_250px.png +│   │   └── mark_400px.png +│   └── index.html +└── templates + ├── a.txt + └── b + └── b.txt +``` + +```go +package main + +import ( + "fmt" + "log" + "net/http" + "os" + + "github.com/markbates/pkger" +) + +const host = ":3000" + +func main() { + // get the currently running application's here.Info. + // this contains really, really, really useful information + // about your application, check it out. :) + // we don't need it for this example, but i thought it could + // be good to show. + current, err := pkger.Current() + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Walking files for %s\n", current.ImportPath) + // walk the files in this module. "/" is where the `go.mod` for this module is + err = pkger.Walk("/", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + fmt.Println("> ", path) + return nil + }) + if err != nil { + log.Fatal(err) + } + + // find the public directory with using the full pkger path to it: + // pkg - is the module/package you want to get a file from + // if pkg is empty then it is assumed to be current.ImportPath + // : - seperator between the module/package name, pkg, and the "file path" + // path - this is the ABSOLUTE path to the file/directory you want, as relative + // to the root of the module/package's go.mod file. + dir, err := pkger.Open("github.com/markbates/pkger/examples/app:/public") + if err != nil { + log.Fatal(err) + } + // don't forget to close the file later + defer dir.Close() + + fmt.Printf("\nServing %q on %s\n", dir.Path(), host) + + // serve the public directory on the host (":3000") + // just like using the os package you still need to use + // http.FileServer to serve a directory. + // you DON'T, however, need to use http.Dir all pkger files + // already implement that interface. + log.Fatal(http.ListenAndServe(host, logger(http.FileServer(dir)))) +} + +// logger will print out the requests as they come in, otherwise its a blank +// screen, and that's no fun. +func logger(h http.Handler) http.HandlerFunc { + return func(res http.ResponseWriter, req *http.Request) { + log.Println(req.Method, req.URL.String()) + h.ServeHTTP(res, req) + } +} +``` + +### Output Without Packing + +```bash +# compile the go binary as usual and run the app: +$ go build -v; ./app + +Walking files for github.com/markbates/pkger/examples/app +> github.com/markbates/pkger/examples/app:/ +> github.com/markbates/pkger/examples/app:/.gitignore +> github.com/markbates/pkger/examples/app:/go.mod +> github.com/markbates/pkger/examples/app:/go.sum +> github.com/markbates/pkger/examples/app:/main.go +> github.com/markbates/pkger/examples/app:/public +> github.com/markbates/pkger/examples/app:/public/images +> github.com/markbates/pkger/examples/app:/public/images/mark-small.png +> github.com/markbates/pkger/examples/app:/public/images/mark.png +> github.com/markbates/pkger/examples/app:/public/images/mark_250px.png +> github.com/markbates/pkger/examples/app:/public/images/mark_400px.png +> github.com/markbates/pkger/examples/app:/public/index.html +> github.com/markbates/pkger/examples/app:/templates +> github.com/markbates/pkger/examples/app:/templates/a.txt +> github.com/markbates/pkger/examples/app:/templates/b +> github.com/markbates/pkger/examples/app:/templates/b/b.txt + +Serving "github.com/markbates/pkger/examples/app:/public" on :3000 +2019/09/22 14:07:41 GET / +2019/09/22 14:07:41 GET /images/mark.png +``` + +### Output With Packing + +```bash +# run the pkger cli to generate a pkged.go file: +$ pkger + +# compile the go binary as usual and run the app: +$ go build -v; ./app + +Walking files for github.com/markbates/pkger/examples/app +> github.com/markbates/pkger/examples/app:/ +> github.com/markbates/pkger/examples/app:/public +> github.com/markbates/pkger/examples/app:/public/images +> github.com/markbates/pkger/examples/app:/public/images/mark-small.png +> github.com/markbates/pkger/examples/app:/public/images/mark.png +> github.com/markbates/pkger/examples/app:/public/images/mark_250px.png +> github.com/markbates/pkger/examples/app:/public/images/mark_400px.png +> github.com/markbates/pkger/examples/app:/public/index.html + +Serving "github.com/markbates/pkger/examples/app:/public" on :3000 +2019/09/22 14:07:41 GET / +2019/09/22 14:07:41 GET /images/mark.png +``` diff --git a/apply.go b/apply.go index de3fe6f..cab8a66 100644 --- a/apply.go +++ b/apply.go @@ -1,18 +1,14 @@ +// +build !debug + package pkger import ( - "os" - "github.com/markbates/pkger/pkging" - "github.com/markbates/pkger/pkging/pkgutil" ) -var current pkging.Pkger - func Apply(pkg pkging.Pkger, err error) error { - if err := pkgutil.Dump(os.Stdout, pkg); err != nil { - return err - } + gil.Lock() + defer gil.Unlock() current = pkging.Wrap(current, pkg) return nil } diff --git a/apply_debug.go b/apply_debug.go new file mode 100644 index 0000000..9bc3ba1 --- /dev/null +++ b/apply_debug.go @@ -0,0 +1,20 @@ +// +build debug + +package pkger + +import ( + "os" + + "github.com/markbates/pkger/pkging" + "github.com/markbates/pkger/pkging/pkgutil" +) + +func Apply(pkg pkging.Pkger, err error) error { + gil.Lock() + defer gil.Unlock() + if err := pkgutil.Dump(os.Stdout, pkg); err != nil { + return err + } + current = pkging.Wrap(current, pkg) + return nil +} diff --git a/examples/app/main.go b/examples/app/main.go index a892560..80772dc 100644 --- a/examples/app/main.go +++ b/examples/app/main.go @@ -2,45 +2,67 @@ package main import ( "fmt" - "io" "log" "net/http" + "os" "github.com/markbates/pkger" ) -func main() { - mux := http.NewServeMux() +const host = ":3000" - pub, err := pkger.Open(":/public") +func main() { + // get the currently running application's here.Info. + // this contains really, really, really useful information + // about your application, check it out. :) + // we don't need it for this example, but i thought it could + // be good to show. + current, err := pkger.Current() if err != nil { log.Fatal(err) } - defer pub.Close() - fmt.Println(pub.Path()) + fmt.Printf("Walking files for %s\n", current.ImportPath) + // walk the files in this module. "/" is where the `go.mod` for this module is + err = pkger.Walk("github.com/markbates/pkger/examples/app:/", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + fmt.Println("> ", path) + return nil + }) + if err != nil { + log.Fatal(err) + } - mux.Handle("/t", http.StripPrefix("/t", tmplHandler())) - mux.Handle("/", http.FileServer(pub)) + // find the public directory with using the full pkger path to it: + // pkg - is the module/package you want to get a file from + // if pkg is empty then it is assumed to be current.ImportPath + // : - seperator between the module/package name, pkg, and the "file path" + // path - this is the ABSOLUTE path to the file/directory you want, as relative + // to the root of the module/package's go.mod file. + dir, err := pkger.Open("github.com/markbates/pkger/examples/app:/public") + if err != nil { + log.Fatal(err) + } + // don't forget to close the file later + defer dir.Close() - log.Fatal(http.ListenAndServe(":3000", logger(mux))) + fmt.Printf("\nServing %q on %s\n", dir.Path(), host) + + // serve the public directory on the host (":3000") + // just like using the os package you still need to use + // http.FileServer to serve a directory. + // you DON'T, however, need to use http.Dir all pkger files + // already implement that interface. + log.Fatal(http.ListenAndServe(host, logger(http.FileServer(dir)))) } +// logger will print out the requests as they come in, otherwise its a blank +// screen, and that's no fun. func logger(h http.Handler) http.HandlerFunc { return func(res http.ResponseWriter, req *http.Request) { log.Println(req.Method, req.URL.String()) h.ServeHTTP(res, req) } } - -func tmplHandler() http.HandlerFunc { - return func(res http.ResponseWriter, req *http.Request) { - t, err := pkger.Open(":/templates/a.txt") - if err != nil { - http.Error(res, err.Error(), 500) - } - defer t.Close() - - io.Copy(res, t) - } -} diff --git a/examples/extfile/go.mod b/examples/extfile/go.mod deleted file mode 100644 index 1fc766a..0000000 --- a/examples/extfile/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/markbates/pkger/examples/extfile - -go 1.12 - -require github.com/markbates/pkger v0.0.0 - -replace github.com/markbates/pkger => ../../ - diff --git a/examples/extfile/go.sum b/examples/extfile/go.sum deleted file mode 100644 index 45dc8ea..0000000 --- a/examples/extfile/go.sum +++ /dev/null @@ -1,21 +0,0 @@ -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/pkger v0.0.0-20190830024022-c5e3a7de4d41 h1:bFEHpLBby7Qdvq92qw0TudeOfUKIZLcrweE/MMlNueI= -github.com/markbates/pkger v0.0.0-20190830024022-c5e3a7de4d41/go.mod h1:M9VeozwduQUCr6z54kJrK9JegpbOv4wiePSbgSbFOew= -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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/examples/extfile/main.go b/examples/extfile/main.go deleted file mode 100644 index 538c959..0000000 --- a/examples/extfile/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "fmt" - "io" - "log" - "os" - - "github.com/markbates/pkger" -) - -func main() { - f, err := pkger.Open("github.com/gobuffalo/meta:/go.mod") - if err != nil { - log.Fatal("1", err) - } - - defer f.Close() - - fi, err := f.Stat() - if err != nil { - log.Fatal("2", err) - } - - fmt.Println(fi) - - io.Copy(os.Stdout, f) -} diff --git a/examples/httpserver/go.mod b/examples/httpserver/go.mod deleted file mode 100644 index c79a7e0..0000000 --- a/examples/httpserver/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/markbates/pkger/examples/httpserver - -go 1.12 - -require github.com/markbates/pkger v0.0.0 - -replace github.com/markbates/pkger => ../../ - diff --git a/examples/httpserver/go.sum b/examples/httpserver/go.sum deleted file mode 100644 index 7530aa3..0000000 --- a/examples/httpserver/go.sum +++ /dev/null @@ -1,22 +0,0 @@ -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/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= -github.com/markbates/pkger v0.0.0-20190830024022-c5e3a7de4d41 h1:bFEHpLBby7Qdvq92qw0TudeOfUKIZLcrweE/MMlNueI= -github.com/markbates/pkger v0.0.0-20190830024022-c5e3a7de4d41/go.mod h1:M9VeozwduQUCr6z54kJrK9JegpbOv4wiePSbgSbFOew= -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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/examples/httpserver/main.go b/examples/httpserver/main.go deleted file mode 100644 index 53979bb..0000000 --- a/examples/httpserver/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "fmt" - "io" - "log" - "net/http" - "os" - "time" - - "github.com/markbates/pkger" -) - -func main() { - dir, err := pkger.Open(".:/public") - if err != nil { - log.Fatal("1", err) - } - defer dir.Close() - - fmt.Println(dir.Path()) - - go func() { - time.Sleep(1 * time.Second) - res, err := http.Get("http://127.0.0.1:3000/assets/radio.radio") - if err != nil { - log.Fatal(err) - } - defer res.Body.Close() - - _, err = io.Copy(os.Stdout, res.Body) - if err != nil { - log.Fatal(err) - } - - if res.StatusCode >= 300 { - log.Fatal("code: ", res.StatusCode) - } - - }() - - log.Fatal(http.ListenAndServe(":3000", http.StripPrefix("/assets/", http.FileServer(dir)))) -} diff --git a/examples/httpserver/public/radio.radio b/examples/httpserver/public/radio.radio deleted file mode 100644 index e77fa7b..0000000 --- a/examples/httpserver/public/radio.radio +++ /dev/null @@ -1,35 +0,0 @@ -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 diff --git a/examples/walk/go.mod b/examples/walk/go.mod deleted file mode 100644 index 5f77686..0000000 --- a/examples/walk/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module github.com/markbates/pkger/examples/walk - -go 1.12 - -require github.com/markbates/pkger v0.0.0 - -replace github.com/markbates/pkger => ../../ - diff --git a/examples/walk/go.sum b/examples/walk/go.sum deleted file mode 100644 index 45dc8ea..0000000 --- a/examples/walk/go.sum +++ /dev/null @@ -1,21 +0,0 @@ -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/pkger v0.0.0-20190830024022-c5e3a7de4d41 h1:bFEHpLBby7Qdvq92qw0TudeOfUKIZLcrweE/MMlNueI= -github.com/markbates/pkger v0.0.0-20190830024022-c5e3a7de4d41/go.mod h1:M9VeozwduQUCr6z54kJrK9JegpbOv4wiePSbgSbFOew= -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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/examples/walk/main.go b/examples/walk/main.go deleted file mode 100644 index 0a3af04..0000000 --- a/examples/walk/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - - "github.com/markbates/pkger" -) - -func main() { - err := pkger.Walk("github.com/gobuffalo/envy", func(path pkger.Path, info os.FileInfo) error { - fmt.Println(path) - return nil - }) - if err != nil { - log.Fatal(err) - } - err = pkger.Walk("/", func(path pkger.Path, info os.FileInfo) error { - fmt.Println(path) - return nil - }) - if err != nil { - log.Fatal(err) - } -} diff --git a/parser/parser.go b/parser/parser.go index f152c71..831c12e 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -51,7 +51,6 @@ func Parse(her here.Info) (Results, error) { return nil } } - if info.IsDir() { if _, err := os.Stat(filepath.Join(path, "go.mod")); err == nil { her, err = here.Dir(path) diff --git a/parser/parser_test.go b/parser/parser_test.go index 3355bdd..da70cd6 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -32,7 +32,6 @@ func Test_Parser(t *testing.T) { "github.com/markbates/pkger/examples/app:/public/images/mark_250px.png", "github.com/markbates/pkger/examples/app:/public/images/mark_400px.png", "github.com/markbates/pkger/examples/app:/public/index.html", - "github.com/markbates/pkger/examples/app:/templates/a.txt", } sort.Strings(exp) diff --git a/parser/visitor.go b/parser/visitor.go index a7645cb..224da29 100644 --- a/parser/visitor.go +++ b/parser/visitor.go @@ -186,7 +186,7 @@ func (v *visitor) evalSelector(expr *ast.CallExpr, sel *ast.SelectorExpr) error switch sel.Sel.Name { case "Walk": if len(expr.Args) != 2 { - return fmt.Errorf("`New` requires two arguments") + return fmt.Errorf("`Walk` requires two arguments") } zz := func(e ast.Expr) (string, error) { diff --git a/pkger.go b/pkger.go index 5a44b72..651ce56 100644 --- a/pkger.go +++ b/pkger.go @@ -1,69 +1,87 @@ package pkger import ( + "log" "os" "path/filepath" + "sync" "github.com/markbates/pkger/here" "github.com/markbates/pkger/pkging" "github.com/markbates/pkger/pkging/stdos" ) -var _ = func() error { - return Apply(stdos.New()) +var current pkging.Pkger +var gil = &sync.RWMutex{} + +var disk = func() pkging.Pkger { + n, err := stdos.New() + if err != nil { + log.Println(err) + } + return n }() +func impl() pkging.Pkger { + gil.RLock() + defer gil.RUnlock() + if current == nil { + return disk + } + return current +} + func Parse(p string) (pkging.Path, error) { - return current.Parse(p) + return impl().Parse(p) } func Abs(p string) (string, error) { - return current.Abs(p) + return impl().Abs(p) } func AbsPath(p pkging.Path) (string, error) { - return current.AbsPath(p) + return impl().AbsPath(p) } func Current() (here.Info, error) { - return current.Current() + return impl().Current() } func Info(p string) (here.Info, error) { - return current.Info(p) + return impl().Info(p) } // Create creates the named file with mode 0666 (before umask) - It's actually 0644, 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. func Create(p string) (pkging.File, error) { - return current.Create(p) + return impl().Create(p) } // MkdirAll creates a directory named path, along with any necessary parents, and returns nil, or else returns an error. The permission bits perm (before umask) are used for all directories that MkdirAll creates. If path is already a directory, MkdirAll does nothing and returns nil. func MkdirAll(p string, perm os.FileMode) error { - return current.MkdirAll(p, perm) + return impl().MkdirAll(p, perm) } // Open opens the named file for reading. If successful, methods on the returned file can be used for reading; the associated file descriptor has mode O_RDONLY. func Open(p string) (pkging.File, error) { - return current.Open(p) + return impl().Open(p) } // Stat returns a FileInfo describing the named file. func Stat(name string) (os.FileInfo, error) { - return current.Stat(name) + return impl().Stat(name) } // Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root. All errors that arise visiting files and directories are filtered by walkFn. The files are walked in lexical order, which makes the output deterministic but means that for very large directories Walk can be inefficient. Walk does not follow symbolic links. - That is from the standard library. I know. Their grammar teachers can not be happy with them right now. func Walk(p string, wf filepath.WalkFunc) error { - return current.Walk(p, wf) + return impl().Walk(p, wf) } // Remove removes the named file or (empty) directory. func Remove(name string) error { - return current.Remove(name) + return impl().Remove(name) } // RemoveAll removes path and any children it contains. It removes everything it can but returns the first error it encounters. If the path does not exist, RemoveAll returns nil (no error). func RemoveAll(name string) error { - return current.RemoveAll(name) + return impl().RemoveAll(name) }