superstar

This commit is contained in:
Mark Bates 2019-09-22 16:47:40 -04:00
parent 0cb6202706
commit 9bd3853a21
18 changed files with 303 additions and 266 deletions

203
README.md Normal file
View File

@ -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 <pkg:/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
```

View File

@ -1,18 +1,14 @@
// +build !debug
package pkger package pkger
import ( import (
"os"
"github.com/markbates/pkger/pkging" "github.com/markbates/pkger/pkging"
"github.com/markbates/pkger/pkging/pkgutil"
) )
var current pkging.Pkger
func Apply(pkg pkging.Pkger, err error) error { func Apply(pkg pkging.Pkger, err error) error {
if err := pkgutil.Dump(os.Stdout, pkg); err != nil { gil.Lock()
return err defer gil.Unlock()
}
current = pkging.Wrap(current, pkg) current = pkging.Wrap(current, pkg)
return nil return nil
} }

20
apply_debug.go Normal file
View File

@ -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
}

View File

@ -2,45 +2,67 @@ package main
import ( import (
"fmt" "fmt"
"io"
"log" "log"
"net/http" "net/http"
"os"
"github.com/markbates/pkger" "github.com/markbates/pkger"
) )
func main() { const host = ":3000"
mux := http.NewServeMux()
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 { if err != nil {
log.Fatal(err) 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
mux.Handle("/t", http.StripPrefix("/t", tmplHandler())) err = pkger.Walk("github.com/markbates/pkger/examples/app:/", func(path string, info os.FileInfo, err error) error {
mux.Handle("/", http.FileServer(pub)) if err != nil {
return err
log.Fatal(http.ListenAndServe(":3000", logger(mux))) }
fmt.Println("> ", path)
return nil
})
if err != nil {
log.Fatal(err)
} }
// find the public directory with using the full pkger path <pkg:/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 { func logger(h http.Handler) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
log.Println(req.Method, req.URL.String()) log.Println(req.Method, req.URL.String())
h.ServeHTTP(res, req) 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)
}
}

View File

@ -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 => ../../

View File

@ -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=

View File

@ -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)
}

View File

@ -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 => ../../

View File

@ -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=

View File

@ -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))))
}

View File

@ -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

View File

@ -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 => ../../

View File

@ -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=

View File

@ -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)
}
}

View File

@ -51,7 +51,6 @@ func Parse(her here.Info) (Results, error) {
return nil return nil
} }
} }
if info.IsDir() { if info.IsDir() {
if _, err := os.Stat(filepath.Join(path, "go.mod")); err == nil { if _, err := os.Stat(filepath.Join(path, "go.mod")); err == nil {
her, err = here.Dir(path) her, err = here.Dir(path)

View File

@ -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_250px.png",
"github.com/markbates/pkger/examples/app:/public/images/mark_400px.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:/public/index.html",
"github.com/markbates/pkger/examples/app:/templates/a.txt",
} }
sort.Strings(exp) sort.Strings(exp)

View File

@ -186,7 +186,7 @@ func (v *visitor) evalSelector(expr *ast.CallExpr, sel *ast.SelectorExpr) error
switch sel.Sel.Name { switch sel.Sel.Name {
case "Walk": case "Walk":
if len(expr.Args) != 2 { 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) { zz := func(e ast.Expr) (string, error) {

View File

@ -1,69 +1,87 @@
package pkger package pkger
import ( import (
"log"
"os" "os"
"path/filepath" "path/filepath"
"sync"
"github.com/markbates/pkger/here" "github.com/markbates/pkger/here"
"github.com/markbates/pkger/pkging" "github.com/markbates/pkger/pkging"
"github.com/markbates/pkger/pkging/stdos" "github.com/markbates/pkger/pkging/stdos"
) )
var _ = func() error { var current pkging.Pkger
return Apply(stdos.New()) 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) { func Parse(p string) (pkging.Path, error) {
return current.Parse(p) return impl().Parse(p)
} }
func Abs(p string) (string, error) { func Abs(p string) (string, error) {
return current.Abs(p) return impl().Abs(p)
} }
func AbsPath(p pkging.Path) (string, error) { func AbsPath(p pkging.Path) (string, error) {
return current.AbsPath(p) return impl().AbsPath(p)
} }
func Current() (here.Info, error) { func Current() (here.Info, error) {
return current.Current() return impl().Current()
} }
func Info(p string) (here.Info, error) { 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. // 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) { 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. // 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 { 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. // 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) { func Open(p string) (pkging.File, error) {
return current.Open(p) return impl().Open(p)
} }
// Stat returns a FileInfo describing the named file. // Stat returns a FileInfo describing the named file.
func Stat(name string) (os.FileInfo, error) { 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. // 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 { 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. // Remove removes the named file or (empty) directory.
func Remove(name string) error { 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). // 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 { func RemoveAll(name string) error {
return current.RemoveAll(name) return impl().RemoveAll(name)
} }