forked from mirror/pkger
Compare commits
No commits in common. "master" and "new-years-resolution" have entirely different histories.
master
...
new-years-
|
@ -1,4 +0,0 @@
|
||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: markbates
|
|
||||||
patreon: buffalo
|
|
|
@ -1,28 +0,0 @@
|
||||||
name: Release
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types:
|
|
||||||
- published
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Set up Go 1.13
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.13
|
|
||||||
id: go
|
|
||||||
-
|
|
||||||
name: Checkout Code
|
|
||||||
uses: actions/checkout@master
|
|
||||||
-
|
|
||||||
name: Run GoReleaser
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }}
|
|
||||||
uses: goreleaser/goreleaser-action@v1
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: release --rm-dist
|
|
|
@ -1,25 +0,0 @@
|
||||||
name: Tests
|
|
||||||
on: [push]
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
tests:
|
|
||||||
name: ${{matrix.os}} Tests
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
|
||||||
steps:
|
|
||||||
- name: Set up Go 1.13
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.13
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: |
|
|
||||||
go mod download
|
|
||||||
go mod tidy -v
|
|
||||||
go test -race ./...
|
|
|
@ -1,45 +1,33 @@
|
||||||
|
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
|
||||||
|
# Edit .goreleaser.yml.plush instead
|
||||||
|
|
||||||
builds:
|
builds:
|
||||||
-
|
-
|
||||||
main: ./cmd/pkger/main.go
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
ldflags:
|
|
||||||
- -s -w -X "github.com/markbates/pkger.Version={{.Tag}}"
|
|
||||||
goos:
|
goos:
|
||||||
- darwin
|
- darwin
|
||||||
- linux
|
- linux
|
||||||
- windows
|
- windows
|
||||||
goarch:
|
env:
|
||||||
- amd64
|
- CGO_ENABLED=0
|
||||||
- 386
|
main: ./cmd/pkger/main.go
|
||||||
- arm
|
|
||||||
- arm64
|
|
||||||
goarm:
|
|
||||||
- 6
|
|
||||||
- 7
|
|
||||||
archives:
|
|
||||||
-
|
|
||||||
replacements:
|
|
||||||
'386': i386
|
|
||||||
darwin: Darwin
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
amd64: x86_64
|
|
||||||
checksum:
|
checksum:
|
||||||
name_template: checksums.txt
|
name_template: 'checksums.txt'
|
||||||
|
|
||||||
snapshot:
|
snapshot:
|
||||||
name_template: '{{ .Tag }}-next'
|
name_template: "{{ .Tag }}-next"
|
||||||
|
|
||||||
changelog:
|
changelog:
|
||||||
sort: asc
|
sort: asc
|
||||||
filters:
|
filters:
|
||||||
exclude:
|
exclude:
|
||||||
- '^docs:'
|
- '^docs:'
|
||||||
- '^test:'
|
- '^test:'
|
||||||
|
|
||||||
brews:
|
brews:
|
||||||
-
|
-
|
||||||
name: 'pkger'
|
name: pkger
|
||||||
github:
|
github:
|
||||||
owner: 'markbates'
|
owner: markbates
|
||||||
name: 'homebrew-tap'
|
name: homebrew-tap
|
||||||
install: |
|
|
||||||
bin.install "pkger"
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
builds:
|
||||||
|
-
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
main: ./cmd/pkger/main.go
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ .Tag }}-next"
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^docs:'
|
||||||
|
- '^test:'
|
||||||
|
<%= if (brew) { %>
|
||||||
|
brews:
|
||||||
|
-
|
||||||
|
name: pkger
|
||||||
|
github:
|
||||||
|
owner: markbates
|
||||||
|
name: homebrew-tap
|
||||||
|
<% } %>
|
2
Makefile
2
Makefile
|
@ -17,7 +17,7 @@ build: tidy
|
||||||
make tidy
|
make tidy
|
||||||
|
|
||||||
test: tidy
|
test: tidy
|
||||||
$(GO_BIN) test -count 1 -cover -tags ${TAGS} -timeout 1m ./...
|
$(GO_BIN) test -cover -tags ${TAGS} -timeout 5s ./...
|
||||||
make tidy
|
make tidy
|
||||||
|
|
||||||
cov:
|
cov:
|
||||||
|
|
394
README.md
394
README.md
|
@ -2,12 +2,7 @@
|
||||||
|
|
||||||
[`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).
|
[`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).
|
||||||
|
|
||||||
### Requirements
|
## How it Works
|
||||||
|
|
||||||
* Go 1.13+
|
|
||||||
* Go Modules
|
|
||||||
|
|
||||||
## How it Works (Module Aware Pathing)
|
|
||||||
|
|
||||||
Pkger is powered by the dark magic of Go Modules, so they're like, totally required.
|
Pkger is powered by the dark magic of Go Modules, so they're like, totally required.
|
||||||
|
|
||||||
|
@ -24,146 +19,22 @@ Paths:
|
||||||
* Packages can specified in at the beginning of a path with a `:` seperator.
|
* Packages can specified in at the beginning of a path with a `:` seperator.
|
||||||
github.com/markbates/pkger:/cmd/pkger/main.go
|
github.com/markbates/pkger:/cmd/pkger/main.go
|
||||||
* There are no relative paths. All paths are absolute to the modules root.
|
* There are no relative paths. All paths are absolute to the modules root.
|
||||||
* Fully-qualified paths are embedded into the metadata of your static assets. If this behavior is undesirable, a preference is to build in a containerized environ, like docker, where the path strings are not ex-filtrating data about your development environment.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
"github.com/gobuffalo/buffalo:/go.mod" => /go/pkg/mod/github.com/gobuffalo/buffalo@v0.14.7/go.mod
|
"github.com/gobuffalo/buffalo:/go.mod" => $GOPATH/pkg/mod/github.com/gobuffalo/buffalo@v0.14.7/go.mod
|
||||||
```
|
```
|
||||||
|
|
||||||
## CLI
|
## Usage
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ go get github.com/markbates/pkger/cmd/pkger
|
|
||||||
$ pkger -h
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pkger
|
|
||||||
```
|
|
||||||
|
|
||||||
The result will be a `pkged.go` file in the **root** of the module with the embedded information and the package name of the module.
|
|
||||||
|
|
||||||
```go
|
|
||||||
// ./pkged.go
|
|
||||||
package <.>
|
|
||||||
|
|
||||||
// Pkger stuff here
|
|
||||||
```
|
|
||||||
|
|
||||||
The `-o` flag can be used to specify the directory of the `pkged.go` file.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pkger -o cmd/reader
|
|
||||||
```
|
|
||||||
|
|
||||||
The result will be a `pkged.go` file in the **cmd/reader** folder with the embedded information and the package name of that folder.
|
|
||||||
|
|
||||||
```go
|
|
||||||
// cmd/reader/pkged.go
|
|
||||||
package <reader>
|
|
||||||
|
|
||||||
// Pkger stuff here
|
|
||||||
```
|
|
||||||
|
|
||||||
### Including Files at Package Time
|
|
||||||
|
|
||||||
There may be reasons where you don't reference a particular file, or folder, that you want embedded in your application, such as a build artifact.
|
|
||||||
|
|
||||||
To do this you may use either the [`github.com/markbates/pkger#Include`](https://godoc.org/github.com/markbates/pkger#Include) function to set a no-op parser directive to include the specified path.
|
|
||||||
|
|
||||||
Alternatively, you may use the `-include` flag with the `pkger` and `pkger list` commands.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pkger list -include /actions -include github.com/gobuffalo/buffalo:/app.go
|
|
||||||
|
|
||||||
app
|
|
||||||
> app:/actions
|
|
||||||
> app:/actions/actions.go
|
|
||||||
> app:/assets
|
|
||||||
> app:/assets/css
|
|
||||||
> app:/assets/css/_buffalo.scss
|
|
||||||
> app:/assets/css/application.scss
|
|
||||||
> app:/assets/images
|
|
||||||
> app:/assets/images/favicon.ico
|
|
||||||
> app:/assets/images/logo.svg
|
|
||||||
> app:/assets/js
|
|
||||||
> app:/assets/js/application.js
|
|
||||||
> app:/go.mod
|
|
||||||
> app:/locales/all.en-us.yaml
|
|
||||||
> app:/public
|
|
||||||
> app:/public/assets
|
|
||||||
> app:/public/assets/.keep
|
|
||||||
> app:/public/assets/app.css
|
|
||||||
> app:/public/images
|
|
||||||
> app:/public/images/img1.png
|
|
||||||
> app:/public/index.html
|
|
||||||
> app:/public/robots.txt
|
|
||||||
> app:/templates
|
|
||||||
> app:/templates/_flash.plush.html
|
|
||||||
> app:/templates/application.plush.html
|
|
||||||
> app:/templates/index.plush.html
|
|
||||||
> app:/web
|
|
||||||
> app:/web/web.go
|
|
||||||
> github.com/gobuffalo/buffalo:/app.go
|
|
||||||
> github.com/gobuffalo/buffalo:/logo.svg
|
|
||||||
```
|
|
||||||
|
|
||||||
## Reference Application
|
|
||||||
|
|
||||||
The reference application for the `README` examples, as well as all testing, can be found at [https://github.com/markbates/pkger/tree/master/pkging/pkgtest/testdata/ref](https://github.com/markbates/pkger/tree/master/pkging/pkgtest/testdata/ref).
|
|
||||||
|
|
||||||
```
|
|
||||||
├── actions
|
|
||||||
│ └── actions.go
|
|
||||||
├── assets
|
|
||||||
│ ├── css
|
|
||||||
│ │ ├── _buffalo.scss
|
|
||||||
│ │ └── application.scss
|
|
||||||
│ ├── images
|
|
||||||
│ │ ├── favicon.ico
|
|
||||||
│ │ └── logo.svg
|
|
||||||
│ └── js
|
|
||||||
│ └── application.js
|
|
||||||
├── go.mod
|
|
||||||
├── go.sum
|
|
||||||
├── locales
|
|
||||||
│ └── all.en-us.yaml
|
|
||||||
├── main.go
|
|
||||||
├── mod
|
|
||||||
│ └── mod.go
|
|
||||||
├── models
|
|
||||||
│ └── models.go
|
|
||||||
├── public
|
|
||||||
│ ├── assets
|
|
||||||
│ │ └── app.css
|
|
||||||
│ ├── images
|
|
||||||
│ │ └── img1.png
|
|
||||||
│ ├── index.html
|
|
||||||
│ └── robots.txt
|
|
||||||
├── templates
|
|
||||||
│ ├── _flash.plush.html
|
|
||||||
│ ├── application.plush.html
|
|
||||||
│ └── index.plush.html
|
|
||||||
└── web
|
|
||||||
└── web.go
|
|
||||||
|
|
||||||
13 directories, 20 files
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## API 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.
|
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.
|
||||||
|
|
||||||
The two most important interfaces are [`github.com/markbates/pkger/pkging#Pkger`](https://godoc.org/github.com/markbates/pkger/pkging#Pkger) and [`github.com/markbates/pkger/pkging#File`](https://godoc.org/github.com/markbates/pkger/pkging#File).
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Pkger interface {
|
type Pkger interface {
|
||||||
Parse(p string) (Path, error)
|
Parse(p string) (Path, error)
|
||||||
|
Abs(p string) (string, error)
|
||||||
|
AbsPath(Path) (string, error)
|
||||||
Current() (here.Info, error)
|
Current() (here.Info, error)
|
||||||
Info(p string) (here.Info, error)
|
Info(p string) (here.Info, error)
|
||||||
Create(name string) (File, error)
|
Create(name string) (File, error)
|
||||||
|
@ -177,6 +48,7 @@ type Pkger interface {
|
||||||
|
|
||||||
type File interface {
|
type File interface {
|
||||||
Close() error
|
Close() error
|
||||||
|
Abs() (string, error)
|
||||||
Info() here.Info
|
Info() here.Info
|
||||||
Name() string
|
Name() string
|
||||||
Open(name string) (http.File, error)
|
Open(name string) (http.File, error)
|
||||||
|
@ -189,56 +61,38 @@ type File interface {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
These two interfaces, along with the [`os#FileInfo`](https://godoc.org/os#FileInfo), provide the bulk of the API surface area.
|
```bash
|
||||||
|
├── go.mod
|
||||||
### Open
|
├── go.sum
|
||||||
|
├── main.go
|
||||||
```go
|
├── public
|
||||||
func run() error {
|
│ ├── images
|
||||||
f, err := pkger.Open("/public/index.html")
|
│ │ ├── mark-small.png
|
||||||
if err != nil {
|
│ │ ├── img1.png
|
||||||
return err
|
│ │ ├── mark_250px.png
|
||||||
}
|
│ │ └── mark_400px.png
|
||||||
defer f.Close()
|
│ └── index.html
|
||||||
|
|
||||||
info, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Name: ", info.Name())
|
|
||||||
fmt.Println("Size: ", info.Size())
|
|
||||||
fmt.Println("Mode: ", info.Mode())
|
|
||||||
fmt.Println("ModTime: ", info.ModTime())
|
|
||||||
|
|
||||||
if _, err := io.Copy(os.Stdout, f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Stat
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func run() error {
|
package main
|
||||||
info, err := pkger.Stat("/public/index.html")
|
|
||||||
if err != nil {
|
import (
|
||||||
return err
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"text/tabwriter"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := run(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Name: ", info.Name())
|
|
||||||
fmt.Println("Size: ", info.Size())
|
|
||||||
fmt.Println("Mode: ", info.Mode())
|
|
||||||
fmt.Println("ModTime: ", info.ModTime())
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### Walk
|
|
||||||
|
|
||||||
```go
|
|
||||||
func run() error {
|
func run() error {
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 0, ' ', tabwriter.Debug)
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 0, ' ', tabwriter.Debug)
|
||||||
defer w.Flush()
|
defer w.Flush()
|
||||||
|
@ -262,171 +116,33 @@ func run() error {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Understanding the Parser
|
### Output Without Packing
|
||||||
|
|
||||||
The [`github.com/markbates/pkger/parser#Parser`](https://godoc.org/github.com/markbates/pkger/parser#Parser) works by statically analyzing the source code of your module using the [`go/parser`](https://godoc.org/go/parser) to find a selection of declarations.
|
|
||||||
|
|
||||||
The following declarations in your source code will tell the parser to embed files or folders.
|
|
||||||
|
|
||||||
* `pkger.Dir("<path>")` - Embeds all files under the specified path.
|
|
||||||
* `pkger.Open("<path>")` - Embeds the file, or folder, of the specified path.
|
|
||||||
* `pkger.Stat("<path>")` - Embeds the file, or folder, of the specified path.
|
|
||||||
* `pkger.Walk("<path>", filepath.WalkFunc)` - Embeds all files under the specified path.
|
|
||||||
* `pkger.Include("<path>")` - `Include` is a no-op that directs the pkger tool to include the desired file or folder.
|
|
||||||
|
|
||||||
### CLI Usage
|
|
||||||
|
|
||||||
To see what declarations the parser has found, you can use the `pkger parse` command to get a `JSON` list of the declarations.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ pkger parse
|
# compile the go binary as usual and run the app:
|
||||||
|
$ go build -v; ./app
|
||||||
{
|
/public | 128 | drwxr-xr-x | 2019-10-17T15:02:57-04:00 |
|
||||||
".": [
|
/public/images | 192 | drwxr-xr-x | 2019-10-17T15:02:57-04:00 |
|
||||||
{
|
/public/images/mark-small.png | 649549 | -rw-r--r-- | 2019-10-17T15:02:56-04:00 |
|
||||||
"file": {
|
/public/images/img1.png | 50401191 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
"Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/foo/bar/baz",
|
/public/images/mark_250px.png | 27718 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
"Path": {
|
/public/images/mark_400px.png | 63543 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
"Pkg": "app",
|
/public/index.html | 257 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
"Name": "/foo/bar/baz"
|
|
||||||
},
|
|
||||||
"Here": {
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
|
|
||||||
"ImportPath": "app",
|
|
||||||
"Module": {
|
|
||||||
"Path": "app",
|
|
||||||
"Main": true,
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
|
|
||||||
"GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
|
|
||||||
"GoVersion": "1.13"
|
|
||||||
},
|
|
||||||
"Name": "main"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pos": {
|
|
||||||
"Filename": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/main.go",
|
|
||||||
"Offset": 629,
|
|
||||||
"Line": 47,
|
|
||||||
"Column": 27
|
|
||||||
},
|
|
||||||
"type": "pkger.MkdirAll",
|
|
||||||
"value": "/foo/bar/baz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file": {
|
|
||||||
"Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/foo/bar/baz/biz.txt",
|
|
||||||
"Path": {
|
|
||||||
"Pkg": "app",
|
|
||||||
"Name": "/foo/bar/baz/biz.txt"
|
|
||||||
},
|
|
||||||
"Here": {
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
|
|
||||||
"ImportPath": "app",
|
|
||||||
"Module": {
|
|
||||||
"Path": "app",
|
|
||||||
"Main": true,
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
|
|
||||||
"GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
|
|
||||||
"GoVersion": "1.13"
|
|
||||||
},
|
|
||||||
"Name": "main"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pos": {
|
|
||||||
"Filename": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/main.go",
|
|
||||||
"Offset": 706,
|
|
||||||
"Line": 51,
|
|
||||||
"Column": 25
|
|
||||||
},
|
|
||||||
"type": "pkger.Create",
|
|
||||||
"value": "/foo/bar/baz/biz.txt"
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For a module aware list use the `pkger list` command.
|
### Output With Packing
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ pkger list
|
# run the pkger cli to generate a pkged.go file:
|
||||||
|
$ pkger
|
||||||
|
|
||||||
app
|
# compile the go binary as usual and run the app:
|
||||||
> app:/assets
|
$ go build -v; ./app
|
||||||
> app:/assets/css
|
/ | 128 | drwxr-xr-x | 2019-10-17T15:02:57-04:00 |
|
||||||
> app:/assets/css/_buffalo.scss
|
/images | 192 | drwxr-xr-x | 2019-10-17T15:02:57-04:00 |
|
||||||
> app:/assets/css/application.scss
|
/images/mark-small.png | 649549 | -rw-r--r-- | 2019-10-17T15:02:56-04:00 |
|
||||||
> app:/assets/images
|
/images/img1.png | 50401191 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
> app:/assets/images/favicon.ico
|
/images/mark_250px.png | 27718 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
> app:/assets/images/logo.svg
|
/images/mark_400px.png | 63543 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
> app:/assets/js
|
/index.html | 257 | -rw-r--r-- | 2019-10-17T15:02:57-04:00 |
|
||||||
> app:/assets/js/application.js
|
|
||||||
> app:/go.mod
|
|
||||||
> app:/locales/all.en-us.yaml
|
|
||||||
> app:/public
|
|
||||||
> app:/public/assets
|
|
||||||
> app:/public/assets/.keep
|
|
||||||
> app:/public/assets/app.css
|
|
||||||
> app:/public/images
|
|
||||||
> app:/public/images/img1.png
|
|
||||||
> app:/public/index.html
|
|
||||||
> app:/public/robots.txt
|
|
||||||
> app:/templates
|
|
||||||
> app:/templates/_flash.plush.html
|
|
||||||
> app:/templates/application.plush.html
|
|
||||||
> app:/templates/index.plush.html
|
|
||||||
> app:/web
|
|
||||||
> app:/web/web.go
|
|
||||||
> github.com/gobuffalo/buffalo:/logo.svg
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `-json` flag can be used to get a more detailed list in JSON.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ pkger list -json
|
|
||||||
|
|
||||||
{
|
|
||||||
"ImportPath": "app",
|
|
||||||
"Files": [
|
|
||||||
{
|
|
||||||
"Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets",
|
|
||||||
"Path": {
|
|
||||||
"Pkg": "app",
|
|
||||||
"Name": "/assets"
|
|
||||||
},
|
|
||||||
"Here": {
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets",
|
|
||||||
"ImportPath": "",
|
|
||||||
"Module": {
|
|
||||||
"Path": "app",
|
|
||||||
"Main": true,
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
|
|
||||||
"GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
|
|
||||||
"GoVersion": "1.13"
|
|
||||||
},
|
|
||||||
"Name": "assets"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets/css",
|
|
||||||
"Path": {
|
|
||||||
"Pkg": "app",
|
|
||||||
"Name": "/assets/css"
|
|
||||||
},
|
|
||||||
"Here": {
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/assets",
|
|
||||||
"ImportPath": "",
|
|
||||||
"Module": {
|
|
||||||
"Path": "app",
|
|
||||||
"Main": true,
|
|
||||||
"Dir": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref",
|
|
||||||
"GoMod": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/go.mod",
|
|
||||||
"GoVersion": "1.13"
|
|
||||||
},
|
|
||||||
"Name": "assets"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
3
apply.go
3
apply.go
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !debug
|
||||||
|
|
||||||
package pkger
|
package pkger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -9,7 +11,6 @@ import (
|
||||||
// for layering of pkging.Pkger implementations.
|
// for layering of pkging.Pkger implementations.
|
||||||
func Apply(pkg pkging.Pkger, err error) error {
|
func Apply(pkg pkging.Pkger, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gil.Lock()
|
gil.Lock()
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// +build debug
|
||||||
|
|
||||||
|
package pkger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/pkging"
|
||||||
|
"github.com/markbates/pkger/pkging/pkgutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Apply will wrap the current implementation
|
||||||
|
// of pkger.Pkger with the new pkg. This allows
|
||||||
|
// for layering of pkging.Pkger implementations.
|
||||||
|
func Apply(pkg pkging.Pkger, err error) error {
|
||||||
|
gil.Lock()
|
||||||
|
defer gil.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := pkgutil.Dump(os.Stdout, pkg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
current = pkging.Wrap(current, pkg)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
variables:
|
||||||
|
GOPROXY: "https://proxy.golang.org"
|
||||||
|
GOBIN: "$(GOPATH)/bin" # Go binaries path
|
||||||
|
GOPATH: "$(system.defaultWorkingDirectory)/gopath" # Go workspace path
|
||||||
|
modulePath: "$(GOPATH)/src/github.com/$(build.repository.name)" # Path to the module"s code
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: Windows
|
||||||
|
pool:
|
||||||
|
vmImage: "vs2017-win2016"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go 1.12 (on):
|
||||||
|
go_version: "1.12.9"
|
||||||
|
GO111MODULE: "on"
|
||||||
|
go 1.13 (on):
|
||||||
|
go_version: "1.13"
|
||||||
|
GO111MODULE: "on"
|
||||||
|
steps:
|
||||||
|
- template: azure-tests.yml
|
||||||
|
|
||||||
|
- job: macOS
|
||||||
|
pool:
|
||||||
|
vmImage: "macOS-10.13"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go 1.12 (on):
|
||||||
|
go_version: "1.12.9"
|
||||||
|
GO111MODULE: "on"
|
||||||
|
go 1.13 (on):
|
||||||
|
go_version: "1.13"
|
||||||
|
GO111MODULE: "on"
|
||||||
|
steps:
|
||||||
|
- template: azure-tests.yml
|
||||||
|
|
||||||
|
- job: Linux
|
||||||
|
pool:
|
||||||
|
vmImage: "ubuntu-16.04"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go 1.12 (on):
|
||||||
|
go_version: "1.12.9"
|
||||||
|
GO111MODULE: "on"
|
||||||
|
go 1.13 (on):
|
||||||
|
go_version: "1.13"
|
||||||
|
GO111MODULE: "on"
|
||||||
|
steps:
|
||||||
|
- template: azure-tests.yml
|
|
@ -0,0 +1,19 @@
|
||||||
|
steps:
|
||||||
|
- task: GoTool@0
|
||||||
|
inputs:
|
||||||
|
version: $(go_version)
|
||||||
|
- task: Bash@3
|
||||||
|
inputs:
|
||||||
|
targetType: inline
|
||||||
|
script: |
|
||||||
|
mkdir -p "$(GOBIN)"
|
||||||
|
mkdir -p "$(GOPATH)/pkg"
|
||||||
|
mkdir -p "$(modulePath)"
|
||||||
|
shopt -s extglob
|
||||||
|
mv !(gopath) "$(modulePath)"
|
||||||
|
displayName: "Setup Go Workspace"
|
||||||
|
- script: |
|
||||||
|
go get -t -v ./...
|
||||||
|
go test -race ./...
|
||||||
|
workingDirectory: "$(modulePath)"
|
||||||
|
displayName: "Tests"
|
|
@ -1,91 +0,0 @@
|
||||||
package cmds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger"
|
|
||||||
"github.com/markbates/pkger/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
type listCmd struct {
|
|
||||||
*flag.FlagSet
|
|
||||||
help bool
|
|
||||||
json bool
|
|
||||||
include slice
|
|
||||||
subs []command
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *listCmd) Name() string {
|
|
||||||
return e.Flags().Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *listCmd) Exec(args []string) error {
|
|
||||||
e.Parse(args)
|
|
||||||
|
|
||||||
if e.help {
|
|
||||||
e.Usage()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
args = e.Args()
|
|
||||||
|
|
||||||
info, err := pkger.Current()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fp := filepath.Join(info.Dir, outName)
|
|
||||||
os.RemoveAll(fp)
|
|
||||||
|
|
||||||
decls, err := parser.Parse(info, e.include...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
jay := struct {
|
|
||||||
ImportPath string
|
|
||||||
Files []*parser.File
|
|
||||||
}{
|
|
||||||
ImportPath: info.ImportPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
files, err := decls.Files()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
jay.Files = files
|
|
||||||
|
|
||||||
if e.json {
|
|
||||||
bb := &bytes.Buffer{}
|
|
||||||
|
|
||||||
enc := json.NewEncoder(bb)
|
|
||||||
enc.SetIndent("", " ")
|
|
||||||
if err := enc.Encode(jay); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = os.Stdout.Write(bb.Bytes())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(jay.ImportPath)
|
|
||||||
for _, f := range jay.Files {
|
|
||||||
fmt.Println(" >", f.Path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *listCmd) Flags() *flag.FlagSet {
|
|
||||||
if e.FlagSet == nil {
|
|
||||||
e.FlagSet = flag.NewFlagSet("list", flag.ExitOnError)
|
|
||||||
e.BoolVar(&e.json, "json", false, "prints in JSON format")
|
|
||||||
e.Var(&e.include, "include", "packages the specified file or directory")
|
|
||||||
}
|
|
||||||
e.Usage = Usage(os.Stderr, e.FlagSet)
|
|
||||||
return e.FlagSet
|
|
||||||
}
|
|
|
@ -4,34 +4,19 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger"
|
"github.com/markbates/pkger"
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
"github.com/markbates/pkger/parser"
|
"github.com/markbates/pkger/parser"
|
||||||
"github.com/markbates/pkger/pkging/pkgutil"
|
"github.com/markbates/pkger/pkging/pkgutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type slice []string
|
|
||||||
|
|
||||||
func (i slice) String() string {
|
|
||||||
return fmt.Sprintf("%s", []string(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *slice) Set(value string) error {
|
|
||||||
*i = append(*i, value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const outName = "pkged.go"
|
const outName = "pkged.go"
|
||||||
|
|
||||||
type packCmd struct {
|
type packCmd struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
out string
|
|
||||||
help bool
|
help bool
|
||||||
include slice
|
list bool
|
||||||
subs []command
|
subs []command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,15 +30,24 @@ func (e *packCmd) Exec(args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fp := filepath.Join(info.Dir, e.out, outName)
|
fp := info.FilePath(outName)
|
||||||
os.RemoveAll(fp)
|
os.RemoveAll(fp)
|
||||||
|
|
||||||
decls, err := parser.Parse(info, e.include...)
|
res, err := parser.Parse(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := Package(info, fp, decls); err != nil {
|
if e.list {
|
||||||
|
fmt.Println(info.ImportPath)
|
||||||
|
|
||||||
|
for _, p := range res {
|
||||||
|
fmt.Printf(" > %s\n", p)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := Package(fp, res); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,23 +82,22 @@ func (e *packCmd) Route(args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("unknown arguments: %s", strings.Join(args, " "))
|
return e.Exec(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() (*packCmd, error) {
|
func New() (*packCmd, error) {
|
||||||
c := &packCmd{}
|
c := &packCmd{}
|
||||||
|
|
||||||
c.subs = []command{
|
c.subs = []command{
|
||||||
&serveCmd{}, &statCmd{}, &infoCmd{}, &pathCmd{}, &parseCmd{}, &listCmd{},
|
&readCmd{}, &serveCmd{}, &statCmd{}, &infoCmd{},
|
||||||
}
|
}
|
||||||
sort.Slice(c.subs, func(a, b int) bool {
|
sort.Slice(c.subs, func(a, b int) bool {
|
||||||
return c.subs[a].Name() <= c.subs[b].Name()
|
return c.subs[a].Name() <= c.subs[b].Name()
|
||||||
})
|
})
|
||||||
|
|
||||||
c.FlagSet = flag.NewFlagSet("pkger", flag.ExitOnError)
|
c.FlagSet = flag.NewFlagSet("pkger", flag.ExitOnError)
|
||||||
|
c.BoolVar(&c.list, "list", false, "prints a list of files/dirs to be packaged")
|
||||||
c.BoolVar(&c.help, "h", false, "prints help information")
|
c.BoolVar(&c.help, "h", false, "prints help information")
|
||||||
c.StringVar(&c.out, "o", "", "output directory for pkged.go")
|
|
||||||
c.Var(&c.include, "include", "packages the specified file or directory")
|
|
||||||
c.Usage = func() {
|
c.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage:\n\n")
|
fmt.Fprintf(os.Stderr, "Usage:\n\n")
|
||||||
Usage(os.Stderr, c.FlagSet)()
|
Usage(os.Stderr, c.FlagSet)()
|
||||||
|
@ -118,23 +111,14 @@ func New() (*packCmd, error) {
|
||||||
func (e *packCmd) Flags() *flag.FlagSet {
|
func (e *packCmd) Flags() *flag.FlagSet {
|
||||||
if e.FlagSet == nil {
|
if e.FlagSet == nil {
|
||||||
e.FlagSet = flag.NewFlagSet("", flag.ExitOnError)
|
e.FlagSet = flag.NewFlagSet("", flag.ExitOnError)
|
||||||
|
e.BoolVar(&e.list, "list", false, "prints a list of files/dirs to be packaged")
|
||||||
}
|
}
|
||||||
e.Usage = Usage(os.Stderr, e.FlagSet)
|
e.Usage = Usage(os.Stderr, e.FlagSet)
|
||||||
return e.FlagSet
|
return e.FlagSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func Package(info here.Info, out string, decls parser.Decls) error {
|
func Package(out string, decls parser.Decls) error {
|
||||||
c, err := here.Dir(filepath.Dir(out))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
os.RemoveAll(out)
|
os.RemoveAll(out)
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
os.RemoveAll(out)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
f, err := os.Create(out)
|
f, err := os.Create(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,14 +126,20 @@ func Package(info here.Info, out string, decls parser.Decls) error {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
fmt.Fprintf(f, "// Code generated by pkger; DO NOT EDIT.\n\n")
|
c, err := pkger.Current()
|
||||||
fmt.Fprintf(f, "// +build !skippkger\n\n")
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
fmt.Fprintf(f, "package %s\n\n", c.Name)
|
fmt.Fprintf(f, "package %s\n\n", c.Name)
|
||||||
fmt.Fprintf(f, "import (\n\t\"github.com/markbates/pkger\"\n\t")
|
fmt.Fprintf(f, "import \"github.com/markbates/pkger\"\n\n")
|
||||||
fmt.Fprintf(f, "\"github.com/markbates/pkger/pkging/mem\"\n)\n\n")
|
fmt.Fprintf(f, "import \"github.com/markbates/pkger/pkging/mem\"\n\n")
|
||||||
fmt.Fprintf(f, "var _ = pkger.Apply(mem.UnmarshalEmbed([]byte(`")
|
fmt.Fprintf(f, "// packing:\n")
|
||||||
|
// for _, p := range paths {
|
||||||
|
// fmt.Fprintf(f, "// %s\n", p)
|
||||||
|
// }
|
||||||
|
fmt.Fprintf(f, "\nvar _ = pkger.Apply(mem.UnmarshalEmbed([]byte(`")
|
||||||
|
|
||||||
if err := pkgutil.Stuff(f, info, decls); err != nil {
|
if err := pkgutil.Stuff(f, c, decls); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
package cmds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
"github.com/markbates/pkger/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
type parseCmd struct {
|
|
||||||
*flag.FlagSet
|
|
||||||
json bool
|
|
||||||
help bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *parseCmd) Name() string {
|
|
||||||
return s.Flags().Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *parseCmd) Flags() *flag.FlagSet {
|
|
||||||
if c.FlagSet == nil {
|
|
||||||
c.FlagSet = flag.NewFlagSet("parse", flag.ExitOnError)
|
|
||||||
// c.BoolVar(&c.json, "json", false, "outputs as json")
|
|
||||||
c.BoolVar(&c.help, "h", false, "prints help information")
|
|
||||||
}
|
|
||||||
return c.FlagSet
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *parseCmd) Exec(args []string) error {
|
|
||||||
|
|
||||||
c.Parse(args)
|
|
||||||
|
|
||||||
if c.help {
|
|
||||||
c.Usage()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
args = c.Args()
|
|
||||||
if len(args) == 0 {
|
|
||||||
args = append(args, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
m := map[string]parser.Decls{}
|
|
||||||
|
|
||||||
for _, a := range args {
|
|
||||||
var info here.Info
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if a == "." {
|
|
||||||
info, err = here.Dir(a)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info, err = here.Package(a)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
decls, err := parser.Parse(info)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
m[a] = decls
|
|
||||||
}
|
|
||||||
|
|
||||||
enc := json.NewEncoder(os.Stdout)
|
|
||||||
enc.SetIndent("", " ")
|
|
||||||
return enc.Encode(m)
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package cmds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger"
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
)
|
|
||||||
|
|
||||||
type pathCmd struct {
|
|
||||||
*flag.FlagSet
|
|
||||||
json bool
|
|
||||||
help bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *pathCmd) Name() string {
|
|
||||||
return s.Flags().Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *pathCmd) Flags() *flag.FlagSet {
|
|
||||||
if c.FlagSet == nil {
|
|
||||||
c.FlagSet = flag.NewFlagSet("path", flag.ExitOnError)
|
|
||||||
// c.BoolVar(&c.json, "json", false, "outputs as json")
|
|
||||||
c.BoolVar(&c.help, "h", false, "prints help information")
|
|
||||||
}
|
|
||||||
return c.FlagSet
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *pathCmd) Exec(args []string) error {
|
|
||||||
|
|
||||||
c.Parse(args)
|
|
||||||
|
|
||||||
if c.help {
|
|
||||||
c.Usage()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
args = c.Args()
|
|
||||||
if len(args) == 0 {
|
|
||||||
return fmt.Errorf("you specify at least one path")
|
|
||||||
}
|
|
||||||
|
|
||||||
paths := map[string]here.Path{}
|
|
||||||
for _, a := range args {
|
|
||||||
pt, err := pkger.Parse(a)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
paths[a] = pt
|
|
||||||
}
|
|
||||||
|
|
||||||
enc := json.NewEncoder(os.Stdout)
|
|
||||||
enc.SetIndent("", " ")
|
|
||||||
return enc.Encode(paths)
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package cmds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type readCmd struct {
|
||||||
|
*flag.FlagSet
|
||||||
|
JSON bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *readCmd) Name() string {
|
||||||
|
return s.Flags().Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *readCmd) Flags() *flag.FlagSet {
|
||||||
|
if r.FlagSet == nil {
|
||||||
|
r.FlagSet = flag.NewFlagSet("read", flag.ExitOnError)
|
||||||
|
r.FlagSet.BoolVar(&r.JSON, "json", false, "print as JSON")
|
||||||
|
}
|
||||||
|
return r.FlagSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *readCmd) Exec(args []string) error {
|
||||||
|
if len(args) == 0 {
|
||||||
|
args = []string{"."}
|
||||||
|
}
|
||||||
|
for _, a := range args {
|
||||||
|
f, err := pkger.Open(a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
fi, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.IsDir() && !r.JSON {
|
||||||
|
return fmt.Errorf("can not read a dir %s", a)
|
||||||
|
}
|
||||||
|
if r.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cmds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func walk(args []string) error {
|
||||||
|
err := pkger.Walk("/", func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(path)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
clean := func() {
|
clean := func() {
|
||||||
c := exec.Command("go", "mod", "tidy")
|
c := exec.Command("go", "mod", "tidy", "-v")
|
||||||
c.Stdout = os.Stdout
|
c.Stdout = os.Stdout
|
||||||
c.Stderr = os.Stderr
|
c.Stderr = os.Stderr
|
||||||
c.Stdin = os.Stdin
|
c.Stdin = os.Stdin
|
||||||
|
@ -18,13 +18,6 @@ func main() {
|
||||||
}
|
}
|
||||||
defer clean()
|
defer clean()
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
clean()
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := run(); err != nil {
|
if err := run(); err != nil {
|
||||||
clean()
|
clean()
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
FROM alpine
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
COPY example /bin/
|
|
||||||
|
|
||||||
|
|
||||||
CMD /bin/example
|
|
|
@ -1,5 +0,0 @@
|
||||||
default:
|
|
||||||
pkger
|
|
||||||
GOOS=linux go build -v -o example
|
|
||||||
docker build -t pkger:example .
|
|
||||||
docker run -p 3000:3000 pkger:example
|
|
|
@ -1,5 +0,0 @@
|
||||||
module app
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require github.com/markbates/pkger v0.5.1
|
|
|
@ -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/pkger v0.5.1 h1:l0s55z4X5XbwIat2LyLe0HABMBswVK1GJbzLXQbuAXs=
|
|
||||||
github.com/markbates/pkger v0.5.1/go.mod h1:so/QD8FeTM0IilC3nRArkwOvUT+tsJsaXLFUAKmjzJk=
|
|
||||||
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=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
|
@ -1,43 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := run(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() error {
|
|
||||||
info, err := pkger.Stat("/go.mod")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(info)
|
|
||||||
if err := pkger.MkdirAll("/foo/bar/baz", 0755); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := pkger.Create("/foo/bar/baz/biz.txt")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.Write([]byte("BIZ!!"))
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err = pkger.Open("/foo/bar/baz/biz.txt")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
io.Copy(os.Stdout, f)
|
|
||||||
return f.Close()
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
default:
|
default:
|
||||||
|
go get github.com/markbates/pkger/cmd/pkger
|
||||||
pkger
|
pkger
|
||||||
GOOS=linux go build -v -o example
|
GOOS=linux go build -v -o example
|
||||||
docker build -t pkger:example .
|
docker build -t pkger:example .
|
||||||
|
|
|
@ -2,6 +2,4 @@ module app
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/markbates/pkger v0.5.0
|
require github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b
|
||||||
|
|
||||||
replace github.com/markbates/pkger => ../../../
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gobuffalo/here v0.5.2-0.20191203194143-8e97fc9ad6d3 h1:9NGxHWbGFujaZ5vT+uXurb9m3QoWa175cYM2Qs97nQo=
|
|
||||||
github.com/gobuffalo/here v0.5.2-0.20191203194143-8e97fc9ad6d3/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
|
||||||
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
|
||||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b h1:cXYQ3JZQkRLFyN8m22Q58mOhdKyTooPqvGt8pyWR8eA=
|
||||||
|
github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b/go.mod h1:0nBNvgA9jJk9gWhO/BcIYz1qJ8BJ0MWCSyKFPApdWNs=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -20,7 +18,3 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func run() error {
|
func run() error {
|
||||||
dir := http.FileServer(pkger.Dir("/public"))
|
f, err := pkger.Open("/public")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dir := http.FileServer(f)
|
||||||
return http.ListenAndServe(":3000", dir)
|
return http.ListenAndServe(":3000", dir)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// +build !skippackr
|
||||||
|
// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.
|
||||||
|
|
||||||
|
// You can use the "packr clean" command to clean up this,
|
||||||
|
// and any other packr generated files.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "app/packrd"
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,5 @@
|
||||||
default:
|
default:
|
||||||
|
go get github.com/markbates/pkger/cmd/pkger
|
||||||
pkger
|
pkger
|
||||||
GOOS=linux go build -v -o example
|
GOOS=linux go build -v -o example
|
||||||
docker build -t pkger:example .
|
docker build -t pkger:example .
|
||||||
|
|
|
@ -2,6 +2,4 @@ module app
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/markbates/pkger v0.8.0
|
require github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b
|
||||||
|
|
||||||
replace github.com/markbates/pkger => ../../../
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b h1:cXYQ3JZQkRLFyN8m22Q58mOhdKyTooPqvGt8pyWR8eA=
|
||||||
|
github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b/go.mod h1:0nBNvgA9jJk9gWhO/BcIYz1qJ8BJ0MWCSyKFPApdWNs=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -14,6 +16,5 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
FROM alpine
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
COPY example /bin/
|
|
||||||
|
|
||||||
|
|
||||||
CMD /bin/example
|
|
|
@ -1,5 +0,0 @@
|
||||||
default:
|
|
||||||
pkger
|
|
||||||
GOOS=linux go build -v -o example
|
|
||||||
docker build -t pkger:example .
|
|
||||||
docker run -p 3000:3000 pkger:example
|
|
|
@ -1,7 +0,0 @@
|
||||||
module app
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require github.com/markbates/pkger v0.8.0
|
|
||||||
|
|
||||||
replace github.com/markbates/pkger => ../../../
|
|
|
@ -1,19 +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/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
|
@ -1,28 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := run(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() error {
|
|
||||||
info, err := pkger.Stat("/public/index.html")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Name: ", info.Name())
|
|
||||||
fmt.Println("Size: ", info.Size())
|
|
||||||
fmt.Println("Mode: ", info.Mode())
|
|
||||||
fmt.Println("ModTime: ", info.ModTime())
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
|
@ -1,12 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
<title>HI</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
HELLO
|
|
||||||
<img src="/images/img1.png" alt=""/>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,7 +0,0 @@
|
||||||
FROM alpine
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
COPY example /bin/
|
|
||||||
|
|
||||||
|
|
||||||
CMD /bin/example
|
|
|
@ -1,4 +0,0 @@
|
||||||
default:
|
|
||||||
GOOS=linux go build -v -o example
|
|
||||||
docker build -t pkger:example .
|
|
||||||
docker run -p 3000:3000 pkger:example
|
|
|
@ -1,3 +0,0 @@
|
||||||
module app
|
|
||||||
|
|
||||||
go 1.13
|
|
|
@ -1,27 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := run(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() error {
|
|
||||||
info, err := os.Stat("./public/index.html")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Name: ", info.Name())
|
|
||||||
fmt.Println("Size: ", info.Size())
|
|
||||||
fmt.Println("Mode: ", info.Mode())
|
|
||||||
fmt.Println("ModTime: ", info.ModTime())
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
|
@ -1,12 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
<title>HI</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
HELLO
|
|
||||||
<img src="/images/img1.png" alt=""/>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// +build !skippackr
|
||||||
|
// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.
|
||||||
|
|
||||||
|
// You can use the "packr clean" command to clean up this,
|
||||||
|
// and any other packr generated files.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "app/packrd"
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,3 @@
|
||||||
module app
|
module app
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/markbates/pkger v0.4.0 // indirect
|
|
||||||
|
|
|
@ -1,18 +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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/markbates/pkger v0.4.0 h1:fIzmOXYsJV+nFS+RtsmWZvXeH5DDGQtF/SwKJgfgVoE=
|
|
||||||
github.com/markbates/pkger v0.4.0/go.mod h1:so/QD8FeTM0IilC3nRArkwOvUT+tsJsaXLFUAKmjzJk=
|
|
||||||
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
5
go.mod
5
go.mod
|
@ -3,6 +3,9 @@ module github.com/markbates/pkger
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gobuffalo/here v0.6.0
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.2.4 // indirect
|
||||||
)
|
)
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -1,8 +1,7 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
|
||||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
@ -10,13 +9,14 @@ 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/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var curOnce sync.Once
|
||||||
|
var curErr error
|
||||||
|
var current Info
|
||||||
|
|
||||||
|
func Current() (Info, error) {
|
||||||
|
(&curOnce).Do(func() {
|
||||||
|
b, err := run("go", "env", "GOMOD")
|
||||||
|
if err != nil {
|
||||||
|
curErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root := filepath.Dir(string(b))
|
||||||
|
i, err := Dir(root)
|
||||||
|
if err != nil {
|
||||||
|
curErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
current = i
|
||||||
|
})
|
||||||
|
|
||||||
|
return current, curErr
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dir attempts to gather info for the requested directory.
|
||||||
|
func Dir(p string) (Info, error) {
|
||||||
|
i, err := Cache(p, func(p string) (Info, error) {
|
||||||
|
var i Info
|
||||||
|
|
||||||
|
fi, err := os.Stat(p)
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fi.IsDir() {
|
||||||
|
p = filepath.Dir(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer os.Chdir(pwd)
|
||||||
|
|
||||||
|
os.Chdir(p)
|
||||||
|
|
||||||
|
b, err := run("go", "list", "-json")
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(b, &i); err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return i, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache(i.ImportPath, func(p string) (Info, error) {
|
||||||
|
return i, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return i, nil
|
||||||
|
}
|
41
here/here.go
41
here/here.go
|
@ -1,14 +1,39 @@
|
||||||
package here
|
package here
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gobuffalo/here"
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Info = here.Info
|
var cache = &infoMap{
|
||||||
type Module = here.Module
|
data: &sync.Map{},
|
||||||
type Path = here.Path
|
}
|
||||||
|
|
||||||
var Here = here.New()
|
func run(n string, args ...string) ([]byte, error) {
|
||||||
var Dir = Here.Dir
|
c := exec.Command(n, args...)
|
||||||
var Package = Here.Package
|
|
||||||
var Current = Here.Current
|
bb := &bytes.Buffer{}
|
||||||
|
c.Stdout = bb
|
||||||
|
c.Stderr = os.Stderr
|
||||||
|
err := c.Run()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cache(p string, fn func(string) (Info, error)) (Info, error) {
|
||||||
|
i, ok := cache.Load(p)
|
||||||
|
if ok {
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
i, err := fn(p)
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
cache.Store(p, i)
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa"
|
||||||
|
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Info represents details about the directory/package
|
||||||
|
type Info struct {
|
||||||
|
Dir string
|
||||||
|
ImportPath string
|
||||||
|
Name string
|
||||||
|
// Imports []string
|
||||||
|
Module Module
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fi Info) MarshalJSON() ([]byte, error) {
|
||||||
|
mm := map[string]interface{}{
|
||||||
|
"ImportPath": fi.ImportPath,
|
||||||
|
"Name": fi.Name,
|
||||||
|
// "Imports": fi.Imports,
|
||||||
|
"Module": fi.Module,
|
||||||
|
}
|
||||||
|
|
||||||
|
hep := hepa.New()
|
||||||
|
hep = hepa.With(hep, filters.Home())
|
||||||
|
hep = hepa.With(hep, filters.Golang())
|
||||||
|
|
||||||
|
cm := map[string]string{
|
||||||
|
"Dir": fi.Dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cm {
|
||||||
|
b, err := hep.Filter([]byte(v))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mm[k] = string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(mm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Info) FilePath(paths ...string) string {
|
||||||
|
res := []string{i.Dir}
|
||||||
|
for _, p := range paths {
|
||||||
|
p = strings.TrimPrefix(p, i.Dir)
|
||||||
|
p = strings.TrimPrefix(p, "/")
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
p = strings.Replace(p, "/", "\\", -1)
|
||||||
|
}
|
||||||
|
res = append(res, p)
|
||||||
|
}
|
||||||
|
return filepath.Join(res...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Info) Open(p string) (*os.File, error) {
|
||||||
|
return os.Open(i.FilePath(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModuleName returns the name of the current
|
||||||
|
// module, or if not using modules, the current
|
||||||
|
// package. These *might* not match.
|
||||||
|
func (i Info) ModuleName() string {
|
||||||
|
if i.Mods() {
|
||||||
|
return i.Module.Path
|
||||||
|
}
|
||||||
|
return i.ImportPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZero checks if the type has been filled
|
||||||
|
// with rich chocolately data goodness
|
||||||
|
func (i Info) IsZero() bool {
|
||||||
|
return i.String() == Info{}.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mods returns whether Go modules are used
|
||||||
|
// in this directory/package.
|
||||||
|
func (i Info) Mods() bool {
|
||||||
|
return !i.Module.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Info) String() string {
|
||||||
|
b, err := json.MarshalIndent(i, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
return s
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// infoMap wraps sync.Map and uses the following types:
|
||||||
|
// key: string
|
||||||
|
// value: Info
|
||||||
|
type infoMap struct {
|
||||||
|
data *sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the key from the map
|
||||||
|
func (m *infoMap) Delete(key string) {
|
||||||
|
m.data.Delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the key from the map.
|
||||||
|
// Returns Info or bool.
|
||||||
|
// A false return indicates either the key was not found
|
||||||
|
// or the value is not of type Info
|
||||||
|
func (m *infoMap) Load(key string) (Info, bool) {
|
||||||
|
i, ok := m.data.Load(key)
|
||||||
|
if !ok {
|
||||||
|
return Info{}, false
|
||||||
|
}
|
||||||
|
s, ok := i.(Info)
|
||||||
|
return s, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadOrStore will return an existing key or
|
||||||
|
// store the value if not already in the map
|
||||||
|
func (m *infoMap) LoadOrStore(key string, value Info) (Info, bool) {
|
||||||
|
i, _ := m.data.LoadOrStore(key, value)
|
||||||
|
s, ok := i.(Info)
|
||||||
|
return s, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadOr will return an existing key or
|
||||||
|
// run the function and store the results
|
||||||
|
func (m *infoMap) LoadOr(key string, fn func(*infoMap) (Info, bool)) (Info, bool) {
|
||||||
|
i, ok := m.Load(key)
|
||||||
|
if ok {
|
||||||
|
return i, ok
|
||||||
|
}
|
||||||
|
i, ok = fn(m)
|
||||||
|
if ok {
|
||||||
|
m.Store(key, i)
|
||||||
|
return i, ok
|
||||||
|
}
|
||||||
|
return i, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range over the Info values in the map
|
||||||
|
func (m *infoMap) Range(f func(key string, value Info) bool) {
|
||||||
|
m.data.Range(func(k, v interface{}) bool {
|
||||||
|
key, ok := k.(string)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
value, ok := v.(Info)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return f(key, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store a Info in the map
|
||||||
|
func (m *infoMap) Store(key string, value Info) {
|
||||||
|
m.data.Store(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns a list of keys in the map
|
||||||
|
func (m *infoMap) Keys() []string {
|
||||||
|
var keys []string
|
||||||
|
m.Range(func(key string, value Info) bool {
|
||||||
|
keys = append(keys, key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa"
|
||||||
|
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Module struct {
|
||||||
|
Path string
|
||||||
|
Main bool
|
||||||
|
Dir string
|
||||||
|
GoMod string
|
||||||
|
GoVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Module) MarshalJSON() ([]byte, error) {
|
||||||
|
mm := map[string]interface{}{
|
||||||
|
"Main": m.Main,
|
||||||
|
"GoVersion": m.GoVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
hep := hepa.New()
|
||||||
|
hep = hepa.With(hep, filters.Home())
|
||||||
|
hep = hepa.With(hep, filters.Golang())
|
||||||
|
|
||||||
|
cm := map[string]string{
|
||||||
|
"Path": m.Path,
|
||||||
|
"Dir": m.Dir,
|
||||||
|
"GoMod": m.GoMod,
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cm {
|
||||||
|
b, err := hep.Filter([]byte(v))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mm[k] = string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(mm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Module) String() string {
|
||||||
|
b, err := json.MarshalIndent(i, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Module) IsZero() bool {
|
||||||
|
return i.String() == Module{}.String()
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (i Info) Parse(p string) (Path, error) {
|
||||||
|
p = strings.TrimSpace(p)
|
||||||
|
p = filepath.Clean(p)
|
||||||
|
p = strings.TrimPrefix(p, i.Dir)
|
||||||
|
|
||||||
|
p = strings.Replace(p, "\\", "/", -1)
|
||||||
|
p = strings.TrimSpace(p)
|
||||||
|
|
||||||
|
if len(p) == 0 || p == ":" || p == "." {
|
||||||
|
return i.build("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
res := pathrx.FindAllStringSubmatch(p, -1)
|
||||||
|
if len(res) == 0 {
|
||||||
|
return Path{}, fmt.Errorf("could not parse %q", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := res[0]
|
||||||
|
|
||||||
|
if len(matches) != 4 {
|
||||||
|
return Path{}, fmt.Errorf("could not parse %q", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.build(p, matches[1], matches[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Info) build(p, pkg, name string) (Path, error) {
|
||||||
|
pt := Path{
|
||||||
|
Pkg: pkg,
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(pt.Pkg, "/") || len(pt.Pkg) == 0 {
|
||||||
|
pt.Name = pt.Pkg
|
||||||
|
pt.Pkg = i.ImportPath
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pt.Name) == 0 {
|
||||||
|
pt.Name = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if pt.Pkg == pt.Name {
|
||||||
|
pt.Pkg = i.ImportPath
|
||||||
|
pt.Name = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(pt.Name, "/") {
|
||||||
|
pt.Name = "/" + pt.Name
|
||||||
|
}
|
||||||
|
pt.Name = strings.TrimPrefix(pt.Name, i.Dir)
|
||||||
|
return pt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var pathrx = regexp.MustCompile("([^:]+)(:(/.+))?")
|
|
@ -0,0 +1,60 @@
|
||||||
|
package here_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/here"
|
||||||
|
"github.com/markbates/pkger/pkging/pkgtest"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Info_Parse(t *testing.T) {
|
||||||
|
const name = "/public/index.html"
|
||||||
|
|
||||||
|
r := require.New(t)
|
||||||
|
|
||||||
|
app, err := pkgtest.App()
|
||||||
|
r.NoError(err)
|
||||||
|
|
||||||
|
ip := app.Info.ImportPath
|
||||||
|
ip2 := "another/app"
|
||||||
|
|
||||||
|
table := []struct {
|
||||||
|
in string
|
||||||
|
exp here.Path
|
||||||
|
err bool
|
||||||
|
}{
|
||||||
|
{in: name, exp: here.Path{Pkg: ip, Name: name}},
|
||||||
|
{in: "", exp: here.Path{Pkg: ip, Name: "/"}},
|
||||||
|
{in: "/", exp: here.Path{Pkg: ip, Name: "/"}},
|
||||||
|
{in: filepath.Join(app.Info.Dir, name), exp: here.Path{Pkg: ip, Name: name}},
|
||||||
|
{in: ":" + name, exp: here.Path{Pkg: ip, Name: name}},
|
||||||
|
{in: ip + ":" + name, exp: here.Path{Pkg: ip, Name: name}},
|
||||||
|
{in: ip, exp: here.Path{Pkg: ip, Name: "/"}},
|
||||||
|
{in: ":", exp: here.Path{Pkg: ip, Name: "/"}},
|
||||||
|
{in: ip2 + ":" + name, exp: here.Path{Pkg: ip2, Name: name}},
|
||||||
|
{in: ip2, exp: here.Path{Pkg: ip2, Name: "/"}},
|
||||||
|
{in: ip2 + ":", exp: here.Path{Pkg: ip2, Name: "/"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range table {
|
||||||
|
for _, in := range []string{tt.in, strings.ReplaceAll(tt.in, "/", "\\")} {
|
||||||
|
t.Run(in, func(st *testing.T) {
|
||||||
|
r := require.New(st)
|
||||||
|
|
||||||
|
pt, err := app.Info.Parse(in)
|
||||||
|
|
||||||
|
if tt.err {
|
||||||
|
r.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.NoError(err)
|
||||||
|
|
||||||
|
r.Equal(tt.exp, pt)
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Path struct {
|
||||||
|
Pkg string `json:"pkg"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Path) String() string {
|
||||||
|
if p.Name == "" {
|
||||||
|
p.Name = "/"
|
||||||
|
}
|
||||||
|
if p.Pkg == "" {
|
||||||
|
return p.Name
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s:%s", p.Pkg, p.Name)
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package here
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Package attempts to gather info for the requested package.
|
||||||
|
//
|
||||||
|
// From the `go help list` docs:
|
||||||
|
// The -find flag causes list to identify the named packages but not
|
||||||
|
// resolve their dependencies: the Imports and Deps lists will be empty.
|
||||||
|
//
|
||||||
|
// A workaround for this issue is to use the `Dir` field in the
|
||||||
|
// returned `Info` value and pass it to the `Dir(string) (Info, error)`
|
||||||
|
// function to return the complete data.
|
||||||
|
func Package(p string) (Info, error) {
|
||||||
|
i, err := Cache(p, func(p string) (Info, error) {
|
||||||
|
var i Info
|
||||||
|
b, err := run("go", "list", "-json", "-find", p)
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(b, &i); err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return i, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache(i.Dir, func(p string) (Info, error) {
|
||||||
|
return i, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return i, nil
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2019 Mark Bates
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,35 @@
|
||||||
|
package hepa
|
||||||
|
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
type Filter interface {
|
||||||
|
Filter([]byte) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FilterFunc func([]byte) ([]byte, error)
|
||||||
|
|
||||||
|
func (f FilterFunc) Filter(b []byte) ([]byte, error) {
|
||||||
|
return f(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Rinse(p Purifier, s, r []byte) Purifier {
|
||||||
|
return WithFunc(p, func(b []byte) ([]byte, error) {
|
||||||
|
b = bytes.ReplaceAll(b, s, r)
|
||||||
|
return b, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clean(p Purifier, s []byte) Purifier {
|
||||||
|
return WithFunc(p, func(b []byte) ([]byte, error) {
|
||||||
|
if bytes.Contains(b, s) {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Noop() FilterFunc {
|
||||||
|
return func(b []byte) ([]byte, error) {
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var env = func() map[string]string {
|
||||||
|
m := map[string]string{}
|
||||||
|
|
||||||
|
for _, line := range os.Environ() {
|
||||||
|
kv := strings.Split(line, "=")
|
||||||
|
|
||||||
|
k, v := kv[0], kv[1]
|
||||||
|
kt, vt := strings.TrimSpace(k), strings.TrimSpace(v)
|
||||||
|
|
||||||
|
if len(kt) == 0 || len(vt) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch k {
|
||||||
|
case "GO111MODULE":
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v {
|
||||||
|
case "true", "TRUE", "false", "FALSE", "null", "nil", "NULL":
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := strconv.Atoi(k); err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := strconv.Atoi(v); err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}()
|
|
@ -0,0 +1,12 @@
|
||||||
|
package filters
|
||||||
|
|
||||||
|
type FilterFunc func([]byte) ([]byte, error)
|
||||||
|
|
||||||
|
func (f FilterFunc) Filter(b []byte) ([]byte, error) {
|
||||||
|
return f(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type dir struct {
|
||||||
|
Dir string
|
||||||
|
Err error
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Golang() FilterFunc {
|
||||||
|
return func(b []byte) ([]byte, error) {
|
||||||
|
gp, err := gopath(home)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b = bytes.ReplaceAll(b, []byte(gp.Dir), []byte("$GOPATH"))
|
||||||
|
|
||||||
|
gru, err := goroot(gp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b = bytes.ReplaceAll(b, []byte(gru.Dir), []byte("$GOROOT"))
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func goroot(gp dir) (dir, error) {
|
||||||
|
gru, ok := os.LookupEnv("GOROOT")
|
||||||
|
if !ok {
|
||||||
|
if gp.Err != nil {
|
||||||
|
return gp, gp.Err
|
||||||
|
}
|
||||||
|
gru = filepath.Join(string(gp.Dir), "go")
|
||||||
|
}
|
||||||
|
return dir{
|
||||||
|
Dir: gru,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gopath(home dir) (dir, error) {
|
||||||
|
gp, ok := os.LookupEnv("GOPATH")
|
||||||
|
if !ok {
|
||||||
|
if home.Err != nil {
|
||||||
|
return home, home.Err
|
||||||
|
}
|
||||||
|
gp = filepath.Join(string(home.Dir), "go")
|
||||||
|
}
|
||||||
|
return dir{
|
||||||
|
Dir: gp,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var home = func() dir {
|
||||||
|
var d dir
|
||||||
|
home, ok := os.LookupEnv("HOME")
|
||||||
|
if !ok {
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
d.Err = err
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
home = pwd
|
||||||
|
}
|
||||||
|
d.Dir = home
|
||||||
|
|
||||||
|
return d
|
||||||
|
}()
|
||||||
|
|
||||||
|
func Home() FilterFunc {
|
||||||
|
return func(b []byte) ([]byte, error) {
|
||||||
|
if home.Err != nil {
|
||||||
|
return b, home.Err
|
||||||
|
}
|
||||||
|
return bytes.ReplaceAll(b, []byte(home.Dir), []byte("$HOME")), nil
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Secrets() FilterFunc {
|
||||||
|
return func(b []byte) ([]byte, error) {
|
||||||
|
for k, v := range env {
|
||||||
|
for _, s := range secretSuffixes {
|
||||||
|
if !strings.HasSuffix(k, s) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b = bytes.ReplaceAll(b, []byte(v), []byte(mask()))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var secretSuffixes = []string{
|
||||||
|
"_KEY",
|
||||||
|
"_SECRET",
|
||||||
|
"_TOKEN",
|
||||||
|
"_PASSWORD",
|
||||||
|
"_PASS",
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package hepa
|
||||||
|
|
||||||
|
func WithFunc(p Purifier, fn FilterFunc) Purifier {
|
||||||
|
c := New()
|
||||||
|
c.parent = &p
|
||||||
|
c.filter = fn
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func With(p Purifier, f Filter) Purifier {
|
||||||
|
c := New()
|
||||||
|
c.parent = &p
|
||||||
|
c.filter = f
|
||||||
|
return c
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package hepa
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Purifier struct {
|
||||||
|
parent *Purifier
|
||||||
|
filter Filter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Purifier) Filter(b []byte) ([]byte, error) {
|
||||||
|
if p.filter == nil {
|
||||||
|
p.filter = filters.Home()
|
||||||
|
}
|
||||||
|
b, err := p.filter.Filter(b)
|
||||||
|
if err != nil {
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
if p.parent != nil {
|
||||||
|
return p.parent.Filter(b)
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Purifier) Clean(r io.Reader) ([]byte, error) {
|
||||||
|
bb := &bytes.Buffer{}
|
||||||
|
|
||||||
|
if p.filter == nil {
|
||||||
|
if p.parent != nil {
|
||||||
|
return p.parent.Clean(r)
|
||||||
|
}
|
||||||
|
_, err := io.Copy(bb, r)
|
||||||
|
return bb.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
home := filters.Home()
|
||||||
|
reader := bufio.NewReader(r)
|
||||||
|
for {
|
||||||
|
input, _, err := reader.ReadLine()
|
||||||
|
if err != nil && err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
input, err = p.Filter(input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
input, err = home(input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bb.Write(input)
|
||||||
|
// if len(input) > 0 {
|
||||||
|
bb.Write([]byte("\n"))
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() Purifier {
|
||||||
|
return Purifier{}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package hepa
|
||||||
|
|
||||||
|
// Version of hepa
|
||||||
|
const Version = "v0.0.1"
|
|
@ -1,51 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Decl = CreateDecl{}
|
|
||||||
|
|
||||||
type CreateDecl struct {
|
|
||||||
file *File
|
|
||||||
pos token.Position
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d CreateDecl) String() string {
|
|
||||||
b, _ := json.Marshal(d)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d CreateDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.Create",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d CreateDecl) File() (*File, error) {
|
|
||||||
if d.file == nil {
|
|
||||||
return nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d CreateDecl) Position() (token.Position, error) {
|
|
||||||
return d.pos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d CreateDecl) Value() (string, error) {
|
|
||||||
if d.value == "" {
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d CreateDecl) VirtualPaths() []string {
|
|
||||||
return []string{d.value}
|
|
||||||
}
|
|
|
@ -1,51 +1,38 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Decl interface {
|
type Decl interface {
|
||||||
File() (*File, error)
|
File() (*File, error)
|
||||||
Position() (token.Position, error)
|
Pos() (token.Pos, error)
|
||||||
Value() (string, error)
|
Value() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Filer interface {
|
type Filer interface {
|
||||||
Files(map[string]string) ([]*File, error)
|
Files() ([]*File, error)
|
||||||
}
|
|
||||||
|
|
||||||
type Virtualer interface {
|
|
||||||
VirtualPaths() []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Decls []Decl
|
type Decls []Decl
|
||||||
|
|
||||||
func (decls Decls) Files() ([]*File, error) {
|
func (decls Decls) Files() ([]*File, error) {
|
||||||
m := map[string]*File{}
|
m := map[string]*File{}
|
||||||
v := map[string]string{}
|
|
||||||
|
|
||||||
for _, d := range decls {
|
for _, d := range decls {
|
||||||
if vt, ok := d.(Virtualer); ok {
|
|
||||||
for _, s := range vt.VirtualPaths() {
|
|
||||||
v[s] = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fl, ok := d.(Filer)
|
fl, ok := d.(Filer)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := fl.Files(v)
|
files, err := fl.Files()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %s", err, d)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
m[f.Abs] = f
|
m[f.Path.String()] = f
|
||||||
v[f.Abs] = f.Abs
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,11 @@ package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
"github.com/markbates/pkger/here"
|
||||||
)
|
)
|
||||||
|
@ -16,3 +21,36 @@ func (f File) String() string {
|
||||||
b, _ := json.MarshalIndent(f, "", " ")
|
b, _ := json.MarshalIndent(f, "", " ")
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type parsedFile struct {
|
||||||
|
File string
|
||||||
|
FileSet *token.FileSet
|
||||||
|
Ast *ast.File
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseFileMode ...
|
||||||
|
func parseFileMode(f string, mode parser.Mode) (parsedFile, error) {
|
||||||
|
pf := parsedFile{
|
||||||
|
File: f,
|
||||||
|
FileSet: token.NewFileSet(),
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(f)
|
||||||
|
if err != nil {
|
||||||
|
return pf, err
|
||||||
|
}
|
||||||
|
src := string(b)
|
||||||
|
|
||||||
|
pff, err := parser.ParseFile(pf.FileSet, f, src, mode)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return pf, err
|
||||||
|
}
|
||||||
|
pf.Ast = pff
|
||||||
|
|
||||||
|
return pf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseFile ...
|
||||||
|
func parseFile(f string) (parsedFile, error) {
|
||||||
|
return parseFileMode(f, 0)
|
||||||
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Decl = HTTPDecl{}
|
|
||||||
|
|
||||||
type HTTPDecl struct {
|
|
||||||
file *File
|
|
||||||
pos token.Position
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d HTTPDecl) String() string {
|
|
||||||
b, _ := json.Marshal(d)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d HTTPDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.Dir",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d HTTPDecl) File() (*File, error) {
|
|
||||||
if d.file == nil {
|
|
||||||
return nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d HTTPDecl) Position() (token.Position, error) {
|
|
||||||
return d.pos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d HTTPDecl) Value() (string, error) {
|
|
||||||
if d.value == "" {
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d HTTPDecl) Files(virtual map[string]string) ([]*File, error) {
|
|
||||||
od := OpenDecl{
|
|
||||||
file: d.file,
|
|
||||||
pos: d.pos,
|
|
||||||
value: d.value,
|
|
||||||
}
|
|
||||||
|
|
||||||
return od.Files(virtual)
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Decl = IncludeDecl{}
|
|
||||||
|
|
||||||
type IncludeDecl struct {
|
|
||||||
file *File
|
|
||||||
pos token.Position
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewInclude(her here.Info, inc string) (IncludeDecl, error) {
|
|
||||||
var id IncludeDecl
|
|
||||||
pt, err := her.Parse(inc)
|
|
||||||
if err != nil {
|
|
||||||
return id, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if pt.Pkg != her.ImportPath {
|
|
||||||
her, err = here.Package(pt.Pkg)
|
|
||||||
if err != nil {
|
|
||||||
return id, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abs := filepath.Join(her.Module.Dir, pt.Name)
|
|
||||||
|
|
||||||
f := &File{
|
|
||||||
Abs: abs,
|
|
||||||
Path: pt,
|
|
||||||
Here: her,
|
|
||||||
}
|
|
||||||
|
|
||||||
return IncludeDecl{
|
|
||||||
value: inc,
|
|
||||||
file: f,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d IncludeDecl) String() string {
|
|
||||||
return fmt.Sprintf("pkger.Include(%q)", d.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d IncludeDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.Include",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d IncludeDecl) File() (*File, error) {
|
|
||||||
if d.file == nil {
|
|
||||||
return nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d IncludeDecl) Position() (token.Position, error) {
|
|
||||||
return d.pos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d IncludeDecl) Value() (string, error) {
|
|
||||||
if d.value == "" {
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d IncludeDecl) Files(virtual map[string]string) ([]*File, error) {
|
|
||||||
od := OpenDecl{
|
|
||||||
file: d.file,
|
|
||||||
pos: d.pos,
|
|
||||||
value: d.value,
|
|
||||||
}
|
|
||||||
|
|
||||||
return od.Files(virtual)
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Decl = MkdirAllDecl{}
|
|
||||||
|
|
||||||
type MkdirAllDecl struct {
|
|
||||||
file *File
|
|
||||||
pos token.Position
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d MkdirAllDecl) String() string {
|
|
||||||
b, _ := json.Marshal(d)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d MkdirAllDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.MkdirAll",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d MkdirAllDecl) File() (*File, error) {
|
|
||||||
if d.file == nil {
|
|
||||||
return nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d MkdirAllDecl) Position() (token.Position, error) {
|
|
||||||
return d.pos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d MkdirAllDecl) Value() (string, error) {
|
|
||||||
if d.value == "" {
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d MkdirAllDecl) VirtualPaths() []string {
|
|
||||||
return []string{d.value}
|
|
||||||
}
|
|
|
@ -1,34 +1,22 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
|
"github.com/markbates/pkger/here"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Decl = OpenDecl{}
|
var _ Decl = OpenDecl{}
|
||||||
|
|
||||||
type OpenDecl struct {
|
type OpenDecl struct {
|
||||||
file *File
|
file *File
|
||||||
pos token.Position
|
pos token.Pos
|
||||||
value string
|
value string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d OpenDecl) String() string {
|
|
||||||
b, _ := json.Marshal(d)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d OpenDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.Open",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d OpenDecl) File() (*File, error) {
|
func (d OpenDecl) File() (*File, error) {
|
||||||
if d.file == nil {
|
if d.file == nil {
|
||||||
return nil, os.ErrNotExist
|
return nil, os.ErrNotExist
|
||||||
|
@ -36,7 +24,10 @@ func (d OpenDecl) File() (*File, error) {
|
||||||
return d.file, nil
|
return d.file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d OpenDecl) Position() (token.Position, error) {
|
func (d OpenDecl) Pos() (token.Pos, error) {
|
||||||
|
if d.pos <= 0 {
|
||||||
|
return -1, os.ErrNotExist
|
||||||
|
}
|
||||||
return d.pos, nil
|
return d.pos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,15 +38,19 @@ func (d OpenDecl) Value() (string, error) {
|
||||||
return d.value, nil
|
return d.value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d OpenDecl) Files(virtual map[string]string) ([]*File, error) {
|
func (d OpenDecl) Files() ([]*File, error) {
|
||||||
if _, ok := virtual[d.value]; ok {
|
|
||||||
return nil, nil
|
pt, err := pkger.Parse(d.value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
her := d.file.Here
|
her, err := here.Package(pt.Pkg)
|
||||||
pt := d.file.Path
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
fp := filepath.Join(her.Module.Dir, pt.Name)
|
fp := filepath.Join(her.Dir, pt.Name)
|
||||||
|
|
||||||
osf, err := os.Stat(fp)
|
osf, err := os.Stat(fp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -68,11 +63,15 @@ func (d OpenDecl) Files(virtual map[string]string) ([]*File, error) {
|
||||||
pos: d.pos,
|
pos: d.pos,
|
||||||
value: d.value,
|
value: d.value,
|
||||||
}
|
}
|
||||||
return wd.Files(virtual)
|
return wd.Files()
|
||||||
}
|
}
|
||||||
|
|
||||||
var files []*File
|
var files []*File
|
||||||
files = append(files, d.file)
|
files = append(files, &File{
|
||||||
|
Abs: filepath.Join(her.Dir, pt.Name),
|
||||||
|
Path: pt,
|
||||||
|
Here: her,
|
||||||
|
})
|
||||||
|
|
||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
237
parser/parser.go
237
parser/parser.go
|
@ -4,237 +4,56 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
"github.com/markbates/pkger/here"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "testdata"}
|
// var DefaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "_fixtures", "testdata"}
|
||||||
|
|
||||||
func New(her here.Info) (*Parser, error) {
|
func Parse(her here.Info) (Decls, error) {
|
||||||
return &Parser{
|
src, err := fromSource(her)
|
||||||
Info: her,
|
if err != nil {
|
||||||
decls: map[string]Decls{},
|
return nil, err
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
return src, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Parser struct {
|
func fromSource(her here.Info) (Decls, error) {
|
||||||
here.Info
|
root := her.Dir
|
||||||
decls map[string]Decls
|
fi, err := os.Stat(root)
|
||||||
once sync.Once
|
|
||||||
includes []string
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func Parse(her here.Info, includes ...string) (Decls, error) {
|
|
||||||
p, err := New(her)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.includes = includes
|
if !fi.IsDir() {
|
||||||
|
return nil, fmt.Errorf("%q is not a directory", root)
|
||||||
return p.Decls()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) ParseSource(source Source, mode parser.Mode) (*ParsedSource, error) {
|
|
||||||
pf := &ParsedSource{
|
|
||||||
Source: source,
|
|
||||||
FileSet: token.NewFileSet(),
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(source.Abs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
src := string(b)
|
|
||||||
|
|
||||||
pff, err := parser.ParseFile(pf.FileSet, source.Abs, src, mode)
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pf.Ast = pff
|
|
||||||
|
|
||||||
return pf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) ParseFile(abs string, mode parser.Mode) (*ParsedSource, error) {
|
|
||||||
s := Source{
|
|
||||||
Abs: abs,
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := os.Stat(abs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil, fmt.Errorf("%s is a directory", abs)
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := filepath.Dir(abs)
|
|
||||||
|
|
||||||
s.Here, err = here.Dir(dir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Path, err = s.Here.Parse(strings.TrimPrefix(abs, dir))
|
|
||||||
|
|
||||||
return p.ParseSource(s, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) ParseDir(abs string, mode parser.Mode) ([]*ParsedSource, error) {
|
|
||||||
info, err := os.Stat(abs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !info.IsDir() {
|
|
||||||
return nil, fmt.Errorf("%s is not a directory", abs)
|
|
||||||
}
|
|
||||||
|
|
||||||
her, err := here.Dir(abs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s: here.Dir failed %s", err, abs)
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := her.Parse(strings.TrimPrefix(abs, filepath.Dir(abs)))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s: here.Parse failed %s", err, abs)
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := func(f os.FileInfo) bool {
|
|
||||||
return !f.IsDir()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
pkgs, err := parser.ParseDir(fset, abs, filter, 0)
|
|
||||||
|
pkgs, err := parser.ParseDir(fset, root, nil, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: ParseDir failed %s", err, abs)
|
|
||||||
}
|
|
||||||
|
|
||||||
var srcs []*ParsedSource
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
for name, pf := range pkg.Files {
|
|
||||||
s := &ParsedSource{
|
|
||||||
Source: Source{
|
|
||||||
Abs: name,
|
|
||||||
Path: pt,
|
|
||||||
Here: her,
|
|
||||||
},
|
|
||||||
FileSet: fset,
|
|
||||||
Ast: pf,
|
|
||||||
}
|
|
||||||
srcs = append(srcs, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return srcs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) Decls() (Decls, error) {
|
|
||||||
if err := p.parse(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var decls Decls
|
var decls Decls
|
||||||
orderedNames := []string{
|
|
||||||
"MkdirAll",
|
for _, pkg := range pkgs {
|
||||||
"Create",
|
for name, pf := range pkg.Files {
|
||||||
"Include",
|
f := &file{
|
||||||
"Stat",
|
fset: fset,
|
||||||
"Open",
|
astFile: pf,
|
||||||
"Dir",
|
filename: name,
|
||||||
"Walk",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range orderedNames {
|
x, err := f.find()
|
||||||
decls = append(decls, p.decls[n]...)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
decls = append(decls, x...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return decls, nil
|
return decls, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) DeclsMap() (map[string]Decls, error) {
|
|
||||||
err := p.Parse()
|
|
||||||
return p.decls, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) Parse() error {
|
|
||||||
(&p.once).Do(func() {
|
|
||||||
p.err = p.parse()
|
|
||||||
})
|
|
||||||
return p.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) parse() error {
|
|
||||||
p.decls = map[string]Decls{}
|
|
||||||
|
|
||||||
root := p.Dir
|
|
||||||
|
|
||||||
if err := p.parseIncludes(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fi, err := os.Stat(root)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fi.IsDir() {
|
|
||||||
return fmt.Errorf("%q is not a directory", root)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
base := filepath.Base(path)
|
|
||||||
for _, x := range defaultIgnoredFolders {
|
|
||||||
if strings.HasPrefix(base, x) {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
srcs, err := p.ParseDir(path, 0)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%s: %s", err, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, src := range srcs {
|
|
||||||
mm, err := src.DeclsMap()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%s: %s", err, src.Abs)
|
|
||||||
}
|
|
||||||
for k, v := range mm {
|
|
||||||
p.decls[k] = append(p.decls[k], v...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Parser) parseIncludes() error {
|
|
||||||
for _, i := range p.includes {
|
|
||||||
d, err := NewInclude(p.Info, i)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.decls["Include"] = append(p.decls["Include"], d)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,122 +1,37 @@
|
||||||
package parser
|
package parser_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"sort"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
"github.com/markbates/pkger/parser"
|
||||||
"github.com/markbates/pkger/pkging/pkgtest"
|
"github.com/markbates/pkger/pkging/pkgtest"
|
||||||
"github.com/markbates/pkger/pkging/stdos"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Parser_Ref(t *testing.T) {
|
func Test_Parser_App(t *testing.T) {
|
||||||
defer func() {
|
|
||||||
c := exec.Command("go", "mod", "tidy", "-v")
|
|
||||||
c.Run()
|
|
||||||
}()
|
|
||||||
r := require.New(t)
|
r := require.New(t)
|
||||||
|
|
||||||
ref, err := pkgtest.NewRef()
|
app, err := pkgtest.App()
|
||||||
r.NoError(err)
|
|
||||||
defer os.RemoveAll(ref.Dir)
|
|
||||||
|
|
||||||
disk, err := stdos.New(ref.Info)
|
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
_, err = pkgtest.LoadFiles("/", ref, disk)
|
res, err := parser.Parse(app.Info)
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
res, err := Parse(ref.Info)
|
|
||||||
|
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
files, err := res.Files()
|
files, err := res.Files()
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
for _, f := range files {
|
|
||||||
fmt.Println(f.Path)
|
act := make([]string, len(files))
|
||||||
|
for i := 0; i < len(files); i++ {
|
||||||
|
act[i] = files[i].Path.String()
|
||||||
}
|
}
|
||||||
r.Len(files, 25)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Parser_Ref_Include(t *testing.T) {
|
sort.Strings(act)
|
||||||
defer func() {
|
|
||||||
c := exec.Command("go", "mod", "tidy", "-v")
|
|
||||||
c.Run()
|
|
||||||
}()
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
ref, err := pkgtest.NewRef()
|
for _, a := range act {
|
||||||
r.NoError(err)
|
fmt.Println(a)
|
||||||
defer os.RemoveAll(ref.Dir)
|
|
||||||
|
|
||||||
disk, err := stdos.New(ref.Info)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
_, err = pkgtest.LoadFiles("/", ref, disk)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
res, err := Parse(ref.Info, "github.com/stretchr/testify:/go.mod")
|
|
||||||
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
files, err := res.Files()
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
l := len(files)
|
|
||||||
r.Equal(26, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Parser_dotGo_Directory(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
ref, err := pkgtest.NewRef()
|
|
||||||
r.NoError(err)
|
|
||||||
defer os.RemoveAll(ref.Dir)
|
|
||||||
|
|
||||||
err = os.Mkdir(filepath.Join(ref.Dir, ".go"), 0755)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
disk, err := stdos.New(ref.Info)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
_, err = pkgtest.LoadFiles("/", ref, disk)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
res, err := Parse(ref.Info)
|
|
||||||
r.NoError(err)
|
|
||||||
r.Equal(11, len(res))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Parser_Example_HTTP(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
cur, err := here.Package("github.com/markbates/pkger")
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
root := filepath.Join(cur.Dir, "examples", "http", "pkger")
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
c := exec.Command("go", "mod", "tidy", "-v")
|
|
||||||
c.Run()
|
|
||||||
}()
|
|
||||||
|
|
||||||
her, err := here.Dir(root)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
res, err := Parse(her)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
files, err := res.Files()
|
|
||||||
r.NoError(err)
|
|
||||||
r.Len(files, 5)
|
|
||||||
|
|
||||||
for _, f := range files {
|
|
||||||
r.True(strings.HasPrefix(f.Abs, her.Dir), "%q %q", f.Abs, her.Dir)
|
|
||||||
r.True(strings.HasPrefix(f.Path.Name, "/public"), "%q %q", f.Path.Name, "/public")
|
|
||||||
}
|
}
|
||||||
|
r.Equal(app.Paths.Parser, act)
|
||||||
}
|
}
|
||||||
|
|
216
parser/source.go
216
parser/source.go
|
@ -1,216 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/token"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Source struct {
|
|
||||||
Abs string // full path on disk to file
|
|
||||||
Path here.Path
|
|
||||||
Here here.Info
|
|
||||||
}
|
|
||||||
|
|
||||||
type ParsedSource struct {
|
|
||||||
Source
|
|
||||||
FileSet *token.FileSet
|
|
||||||
Ast *ast.File
|
|
||||||
decls map[string]Decls
|
|
||||||
once sync.Once
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParsedSource) Parse() error {
|
|
||||||
(&p.once).Do(func() {
|
|
||||||
p.err = p.parse()
|
|
||||||
})
|
|
||||||
return p.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParsedSource) valueIdent(node *ast.Ident) (s string) {
|
|
||||||
s = node.Name
|
|
||||||
if node.Obj.Kind != ast.Con {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// As per ast package a Con object is always a *ValueSpec,
|
|
||||||
// but double-checking to avoid panics
|
|
||||||
if x, ok := node.Obj.Decl.(*ast.ValueSpec); ok {
|
|
||||||
// The const var can be defined inline with other vars,
|
|
||||||
// as in `const a, b = "a", "b"`.
|
|
||||||
for i, v := range x.Names {
|
|
||||||
if v.Name == node.Name {
|
|
||||||
s = p.valueNode(x.Values[i])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParsedSource) valueNode(node ast.Node) string {
|
|
||||||
var s string
|
|
||||||
switch x := node.(type) {
|
|
||||||
case *ast.BasicLit:
|
|
||||||
s = x.Value
|
|
||||||
case *ast.Ident:
|
|
||||||
s = p.valueIdent(x)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParsedSource) value(node ast.Node) (string, error) {
|
|
||||||
s := p.valueNode(node)
|
|
||||||
return strconv.Unquote(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParsedSource) parse() error {
|
|
||||||
p.decls = map[string]Decls{}
|
|
||||||
var fn walker = func(node ast.Node) bool {
|
|
||||||
ce, ok := node.(*ast.CallExpr)
|
|
||||||
if !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
sel, ok := ce.Fun.(*ast.SelectorExpr)
|
|
||||||
if !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg, ok := sel.X.(*ast.Ident)
|
|
||||||
if !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if pkg.Name != "pkger" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var fn func(f File, pos token.Position, value string) Decl
|
|
||||||
|
|
||||||
name := sel.Sel.Name
|
|
||||||
switch name {
|
|
||||||
case "MkdirAll":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return MkdirAllDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "Create":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return CreateDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "Include":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return IncludeDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "Stat":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return StatDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "Open":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return OpenDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "Dir":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return HTTPDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "Walk":
|
|
||||||
fn = func(f File, pos token.Position, value string) Decl {
|
|
||||||
return WalkDecl{
|
|
||||||
file: &f,
|
|
||||||
pos: pos,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ce.Args) < 1 {
|
|
||||||
p.err = fmt.Errorf("declarations require at least one argument")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
n := ce.Args[0]
|
|
||||||
val, err := p.value(n)
|
|
||||||
if err != nil {
|
|
||||||
p.err = fmt.Errorf("%s: %s", err, n)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := here.Dir(filepath.Dir(p.Abs))
|
|
||||||
if err != nil {
|
|
||||||
p.err = fmt.Errorf("%s: %s", err, p.Abs)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := info.Parse(val)
|
|
||||||
if err != nil {
|
|
||||||
p.err = fmt.Errorf("%s: %s", err, p.Abs)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if pt.Pkg != info.Module.Path {
|
|
||||||
info, err = here.Package(pt.Pkg)
|
|
||||||
if err != nil {
|
|
||||||
p.err = fmt.Errorf("%s: %s", err, p.Abs)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f := File{
|
|
||||||
Abs: filepath.Join(info.Module.Dir, pt.Name),
|
|
||||||
Here: info,
|
|
||||||
Path: pt,
|
|
||||||
}
|
|
||||||
|
|
||||||
p.decls[name] = append(p.decls[name], fn(f, p.FileSet.Position(n.Pos()), val))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
ast.Walk(fn, p.Ast)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParsedSource) DeclsMap() (map[string]Decls, error) {
|
|
||||||
err := p.Parse()
|
|
||||||
return p.decls, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrap a function to fulfill ast.Visitor interface
|
|
||||||
type walker func(ast.Node) bool
|
|
||||||
|
|
||||||
func (w walker) Visit(node ast.Node) ast.Visitor {
|
|
||||||
if w(node) {
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Decl = StatDecl{}
|
|
||||||
|
|
||||||
type StatDecl struct {
|
|
||||||
file *File
|
|
||||||
pos token.Position
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d StatDecl) String() string {
|
|
||||||
return fmt.Sprintf("pkger.Stat(%q)", d.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d StatDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.Stat",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d StatDecl) File() (*File, error) {
|
|
||||||
if d.file == nil {
|
|
||||||
return nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d StatDecl) Position() (token.Position, error) {
|
|
||||||
return d.pos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d StatDecl) Value() (string, error) {
|
|
||||||
if d.value == "" {
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
return d.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d StatDecl) Files(virtual map[string]string) ([]*File, error) {
|
|
||||||
od := OpenDecl{
|
|
||||||
file: d.file,
|
|
||||||
pos: d.pos,
|
|
||||||
value: d.value,
|
|
||||||
}
|
|
||||||
|
|
||||||
return od.Files(virtual)
|
|
||||||
}
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/here"
|
||||||
|
)
|
||||||
|
|
||||||
|
type visitor func(node ast.Node) (w ast.Visitor)
|
||||||
|
|
||||||
|
func (v visitor) Visit(node ast.Node) ast.Visitor {
|
||||||
|
return v(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// inspired by https://gist.github.com/cryptix/d1b129361cea51a59af2
|
||||||
|
type file struct {
|
||||||
|
fset *token.FileSet
|
||||||
|
astFile *ast.File
|
||||||
|
filename string
|
||||||
|
decls Decls
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) walk(fn func(ast.Node) bool) {
|
||||||
|
ast.Walk(walker(fn), f.astFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) find() (Decls, error) {
|
||||||
|
if err := f.findOpenCalls(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.findWalkCalls(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.decls, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) asValue(node ast.Node) (string, error) {
|
||||||
|
var s string
|
||||||
|
|
||||||
|
switch x := node.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
s = x.Value
|
||||||
|
case *ast.Ident:
|
||||||
|
s = x.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return strconv.Unquote(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) findOpenCalls() error {
|
||||||
|
var err error
|
||||||
|
f.walk(func(node ast.Node) bool {
|
||||||
|
ce, ok := node.(*ast.CallExpr)
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
exists := isPkgDot(ce.Fun, "pkger", "Open")
|
||||||
|
if !(exists) || len(ce.Args) != 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
n := ce.Args[0]
|
||||||
|
|
||||||
|
s, err := f.asValue(n)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := here.Dir(filepath.Dir(f.filename))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pf := &File{
|
||||||
|
Abs: f.filename,
|
||||||
|
Here: info,
|
||||||
|
}
|
||||||
|
|
||||||
|
decl := OpenDecl{
|
||||||
|
file: pf,
|
||||||
|
pos: n.Pos(),
|
||||||
|
value: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
f.decls = append(f.decls, decl)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *file) findWalkCalls() error {
|
||||||
|
var err error
|
||||||
|
f.walk(func(node ast.Node) bool {
|
||||||
|
ce, ok := node.(*ast.CallExpr)
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
exists := isPkgDot(ce.Fun, "pkger", "Walk")
|
||||||
|
if !(exists) || len(ce.Args) != 2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
n := ce.Args[0]
|
||||||
|
|
||||||
|
s, err := f.asValue(n)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := here.Dir(filepath.Dir(f.filename))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pf := &File{
|
||||||
|
Abs: f.filename,
|
||||||
|
Here: info,
|
||||||
|
}
|
||||||
|
|
||||||
|
decl := WalkDecl{
|
||||||
|
file: pf,
|
||||||
|
pos: n.Pos(),
|
||||||
|
value: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
f.decls = append(f.decls, decl)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
// =======
|
||||||
|
func isPkgDot(expr ast.Expr, pkg, name string) bool {
|
||||||
|
sel, ok := expr.(*ast.SelectorExpr)
|
||||||
|
return ok && isIdent(sel.X, pkg) && isIdent(sel.Sel, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIdent(expr ast.Expr, ident string) bool {
|
||||||
|
id, ok := expr.(*ast.Ident)
|
||||||
|
return ok && id.Name == ident
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrap a function to fulfill ast.Visitor interface
|
||||||
|
type walker func(ast.Node) bool
|
||||||
|
|
||||||
|
func (w walker) Visit(node ast.Node) ast.Visitor {
|
||||||
|
if w(node) {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger"
|
||||||
"github.com/markbates/pkger/here"
|
"github.com/markbates/pkger/here"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,24 +14,10 @@ var _ Decl = WalkDecl{}
|
||||||
|
|
||||||
type WalkDecl struct {
|
type WalkDecl struct {
|
||||||
file *File
|
file *File
|
||||||
pos token.Position
|
pos token.Pos
|
||||||
value string
|
value string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d WalkDecl) String() string {
|
|
||||||
b, _ := json.Marshal(d)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d WalkDecl) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(map[string]interface{}{
|
|
||||||
"type": "pkger.Walk",
|
|
||||||
"file": d.file,
|
|
||||||
"pos": d.pos,
|
|
||||||
"value": d.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d WalkDecl) File() (*File, error) {
|
func (d WalkDecl) File() (*File, error) {
|
||||||
if d.file == nil {
|
if d.file == nil {
|
||||||
return nil, os.ErrNotExist
|
return nil, os.ErrNotExist
|
||||||
|
@ -39,7 +25,10 @@ func (d WalkDecl) File() (*File, error) {
|
||||||
return d.file, nil
|
return d.file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d WalkDecl) Position() (token.Position, error) {
|
func (d WalkDecl) Pos() (token.Pos, error) {
|
||||||
|
if d.pos <= 0 {
|
||||||
|
return -1, os.ErrNotExist
|
||||||
|
}
|
||||||
return d.pos, nil
|
return d.pos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,44 +39,37 @@ func (d WalkDecl) Value() (string, error) {
|
||||||
return d.value, nil
|
return d.value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d WalkDecl) Files(virtual map[string]string) ([]*File, error) {
|
func (d WalkDecl) Files() ([]*File, error) {
|
||||||
|
pt, err := pkger.Parse(d.value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cur, err := here.Package(pt.Pkg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := filepath.Join(cur.Dir, pt.Name)
|
||||||
|
|
||||||
var files []*File
|
var files []*File
|
||||||
|
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||||
her := d.file.Here
|
|
||||||
pt := d.file.Path
|
|
||||||
|
|
||||||
root := filepath.Join(her.Module.Dir, pt.Name)
|
|
||||||
|
|
||||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.IsDir() {
|
n := strings.TrimPrefix(path, cur.Dir)
|
||||||
her, err = here.Dir(path)
|
|
||||||
|
pt, err := pkger.Parse(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
pt.Pkg = cur.ImportPath
|
||||||
|
|
||||||
n := strings.TrimPrefix(path, her.Module.Dir)
|
|
||||||
|
|
||||||
pt, err := her.Parse(n)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := virtual[n]; ok {
|
|
||||||
if info.IsDir() {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
files = append(files, &File{
|
files = append(files, &File{
|
||||||
Abs: path,
|
Abs: path,
|
||||||
Path: pt,
|
Path: pt,
|
||||||
Here: her,
|
Here: cur,
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
37
pkger.go
37
pkger.go
|
@ -1,7 +1,7 @@
|
||||||
package pkger
|
package pkger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -15,8 +15,14 @@ var current pkging.Pkger
|
||||||
var gil = &sync.RWMutex{}
|
var gil = &sync.RWMutex{}
|
||||||
|
|
||||||
var disk = func() pkging.Pkger {
|
var disk = func() pkging.Pkger {
|
||||||
her, _ := here.Current()
|
her, err := here.Current()
|
||||||
n, _ := stdos.New(her)
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
n, err := stdos.New(her)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -29,21 +35,21 @@ func impl() pkging.Pkger {
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
type Dir string
|
|
||||||
|
|
||||||
func (d Dir) Open(name string) (http.File, error) {
|
|
||||||
f, err := impl().Open(string(d))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return f.Open(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the string in here.Path format.
|
// Parse the string in here.Path format.
|
||||||
func Parse(p string) (here.Path, error) {
|
func Parse(p string) (here.Path, error) {
|
||||||
return impl().Parse(p)
|
return impl().Parse(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Abs returns an absolute representation of path. If the path is not absolute it will be joined with the current working directory to turn it into an absolute path. The absolute path name for a given file is not guaranteed to be unique. Abs calls Clean on the result.
|
||||||
|
func Abs(p string) (string, error) {
|
||||||
|
return impl().Abs(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AbsPath returns an absolute representation of here.Path. If the path is not absolute it will be joined with the current working directory to turn it into an absolute path. The absolute path name for a given file is not guaranteed to be unique. AbsPath calls Clean on the result.
|
||||||
|
func AbsPath(p here.Path) (string, error) {
|
||||||
|
return impl().AbsPath(p)
|
||||||
|
}
|
||||||
|
|
||||||
// Current returns the here.Info representing the current Pkger implementation.
|
// Current returns the here.Info representing the current Pkger implementation.
|
||||||
func Current() (here.Info, error) {
|
func Current() (here.Info, error) {
|
||||||
return impl().Current()
|
return impl().Current()
|
||||||
|
@ -88,8 +94,3 @@ func Remove(name string) error {
|
||||||
func RemoveAll(name string) error {
|
func RemoveAll(name string) error {
|
||||||
return impl().RemoveAll(name)
|
return impl().RemoveAll(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include is a no-op that directs the pkger tool to include the desired file or folder.
|
|
||||||
func Include(name string) string {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,8 +2,10 @@ package pkger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/markbates/pkger/here"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,6 +18,31 @@ func Test_Parse(t *testing.T) {
|
||||||
r.Equal("/little", pt.Name)
|
r.Equal("/little", pt.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Abs(t *testing.T) {
|
||||||
|
r := require.New(t)
|
||||||
|
|
||||||
|
s, err := Abs(":/rocket.ship")
|
||||||
|
r.NoError(err)
|
||||||
|
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
r.NoError(err)
|
||||||
|
r.Equal(filepath.Join(pwd, "rocket.ship"), s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_AbsPath(t *testing.T) {
|
||||||
|
r := require.New(t)
|
||||||
|
|
||||||
|
s, err := AbsPath(here.Path{
|
||||||
|
Pkg: "github.com/markbates/pkger",
|
||||||
|
Name: "/rocket.ship",
|
||||||
|
})
|
||||||
|
r.NoError(err)
|
||||||
|
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
r.NoError(err)
|
||||||
|
r.Equal(filepath.Join(pwd, "rocket.ship"), s)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Current(t *testing.T) {
|
func Test_Current(t *testing.T) {
|
||||||
r := require.New(t)
|
r := require.New(t)
|
||||||
|
|
||||||
|
@ -39,7 +66,7 @@ func Test_Create(t *testing.T) {
|
||||||
defer RemoveAll("/tmp")
|
defer RemoveAll("/tmp")
|
||||||
f, err := Create("/tmp/test.create")
|
f, err := Create("/tmp/test.create")
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.Equal("github.com/markbates/pkger:/tmp/test.create", f.Name())
|
r.Equal("/tmp/test.create", f.Name())
|
||||||
r.NoError(f.Close())
|
r.NoError(f.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +80,7 @@ func Test_MkdirAll(t *testing.T) {
|
||||||
|
|
||||||
f, err := Open("/tmp")
|
f, err := Open("/tmp")
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.Equal("github.com/markbates/pkger:/tmp", f.Name())
|
r.Equal("/tmp", f.Name())
|
||||||
r.NoError(f.Close())
|
r.NoError(f.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,14 +89,14 @@ func Test_Stat(t *testing.T) {
|
||||||
|
|
||||||
info, err := Stat("/go.mod")
|
info, err := Stat("/go.mod")
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
r.Equal("go.mod", info.Name())
|
r.Equal("/go.mod", info.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Walk(t *testing.T) {
|
func Test_Walk(t *testing.T) {
|
||||||
r := require.New(t)
|
r := require.New(t)
|
||||||
|
|
||||||
files := map[string]os.FileInfo{}
|
files := map[string]os.FileInfo{}
|
||||||
err := Walk("/pkging/pkgtest/testdata/ref", func(path string, info os.FileInfo, err error) error {
|
err := Walk("/pkging/pkgtest/internal/testdata/app", func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -88,6 +115,7 @@ func Test_Remove(t *testing.T) {
|
||||||
defer RemoveAll("/tmp")
|
defer RemoveAll("/tmp")
|
||||||
f, err := Create("/tmp/test.create")
|
f, err := Create("/tmp/test.create")
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
r.Equal("/tmp/test.create", f.Name())
|
||||||
r.NoError(f.Close())
|
r.NoError(f.Close())
|
||||||
r.NoError(Remove("/tmp/test.create"))
|
r.NoError(Remove("/tmp/test.create"))
|
||||||
|
|
||||||
|
|
|
@ -4,48 +4,17 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
"github.com/markbates/pkger/here"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Decode(src []byte) ([]byte, error) {
|
type Embedder interface {
|
||||||
dst := make([]byte, hex.DecodedLen(len(src)))
|
MarshalEmbed() ([]byte, error)
|
||||||
_, err := hex.Decode(dst, src)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := gzip.NewReader(bytes.NewReader(dst))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bb := &bytes.Buffer{}
|
|
||||||
if _, err := io.Copy(bb, r); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return bb.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Encode(b []byte) ([]byte, error) {
|
type Unembedder interface {
|
||||||
bb := &bytes.Buffer{}
|
UnmarshalEmbed([]byte) error
|
||||||
gz := gzip.NewWriter(bb)
|
|
||||||
|
|
||||||
if _, err := gz.Write(b); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := gz.Flush(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := gz.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s := hex.EncodeToString(bb.Bytes())
|
|
||||||
return []byte(s), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Data struct {
|
type Data struct {
|
||||||
|
@ -53,3 +22,37 @@ type Data struct {
|
||||||
Files map[string]File `json:"files"`
|
Files map[string]File `json:"files"`
|
||||||
Here here.Info `json:"here"`
|
Here here.Info `json:"here"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Data) MarshalEmbed() ([]byte, error) {
|
||||||
|
bb := &bytes.Buffer{}
|
||||||
|
gz := gzip.NewWriter(bb)
|
||||||
|
defer gz.Close()
|
||||||
|
if err := json.NewEncoder(gz).Encode(d); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := gz.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s := hex.EncodeToString(bb.Bytes())
|
||||||
|
return []byte(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Data) UnmarshalEmbed(in []byte) error {
|
||||||
|
b := make([]byte, len(in))
|
||||||
|
if _, err := hex.Decode(b, in); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
gz, err := gzip.NewReader(bytes.NewReader(b))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer gz.Close()
|
||||||
|
|
||||||
|
p := &Data{}
|
||||||
|
if err := json.NewDecoder(gz).Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
(*d) = *p
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package embed
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Encoding(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
in := []byte("hi\n")
|
|
||||||
|
|
||||||
enc, err := Encode(in)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
r.NotEqual(in, enc)
|
|
||||||
|
|
||||||
dec, err := Decode(enc)
|
|
||||||
r.NoError(err)
|
|
||||||
r.Equal(in, dec)
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
package pkging
|
package pkging
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
type Adder interface {
|
type Adder interface {
|
||||||
Add(files ...*os.File) error
|
Add(files ...File) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ type File interface {
|
||||||
// Close closes the File, rendering it unusable for I/O.
|
// Close closes the File, rendering it unusable for I/O.
|
||||||
Close() error
|
Close() error
|
||||||
|
|
||||||
|
// Abs returns an absolute representation of the file. If the path is not absolute it will be joined with the current working directory to turn it into an absolute path. The absolute path name for a given file is not guaranteed to be unique. Abs calls Clean on the result.
|
||||||
|
Abs() (string, error)
|
||||||
|
|
||||||
// Info returns the here.Info of the file
|
// Info returns the here.Info of the file
|
||||||
Info() here.Info
|
Info() here.Info
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package pkging_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
"github.com/markbates/pkger/pkging"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_NewFileInfo(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
her, err := here.Current()
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
exp, err := os.Stat(filepath.Join(her.Dir, "go.mod"))
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
act := pkging.NewFileInfo(exp)
|
|
||||||
|
|
||||||
r.Equal(exp.Name(), act.Name())
|
|
||||||
r.Equal(exp.Size(), act.Size())
|
|
||||||
r.Equal(exp.Mode(), act.Mode())
|
|
||||||
r.Equal(exp.IsDir(), act.IsDir())
|
|
||||||
r.Equal(exp.ModTime().Format(time.RFC3339), act.ModTime().Format(time.RFC3339))
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@ package pkging
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,7 +15,6 @@ type Details struct {
|
||||||
IsDir bool `json:"is_dir"`
|
IsDir bool `json:"is_dir"`
|
||||||
Sys interface{} `json:"sys"`
|
Sys interface{} `json:"sys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileInfo struct {
|
type FileInfo struct {
|
||||||
Details `json:"details"`
|
Details `json:"details"`
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ var _ os.FileInfo = &FileInfo{}
|
||||||
func NewFileInfo(info os.FileInfo) *FileInfo {
|
func NewFileInfo(info os.FileInfo) *FileInfo {
|
||||||
fi := &FileInfo{
|
fi := &FileInfo{
|
||||||
Details: Details{
|
Details: Details{
|
||||||
Name: info.Name(),
|
Name: cleanName(info.Name()),
|
||||||
Size: info.Size(),
|
Size: info.Size(),
|
||||||
Mode: info.Mode(),
|
Mode: info.Mode(),
|
||||||
ModTime: ModTime(info.ModTime()),
|
ModTime: ModTime(info.ModTime()),
|
||||||
|
@ -63,3 +63,29 @@ func NewFileInfo(info os.FileInfo) *FileInfo {
|
||||||
}
|
}
|
||||||
return fi
|
return fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithName(name string, info os.FileInfo) *FileInfo {
|
||||||
|
fo := NewFileInfo(info)
|
||||||
|
fo.Details.Name = cleanName(name)
|
||||||
|
return fo
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithRelName(name string, info os.FileInfo) *FileInfo {
|
||||||
|
fo := NewFileInfo(info)
|
||||||
|
|
||||||
|
s := cleanName(name)
|
||||||
|
s = strings.TrimPrefix(s, "/")
|
||||||
|
|
||||||
|
fo.Details.Name = s
|
||||||
|
return fo
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanName(s string) string {
|
||||||
|
if strings.Contains(s, "\\") {
|
||||||
|
s = strings.Replace(s, "\\", "/", -1)
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(s, "/") {
|
||||||
|
s = "/" + s
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package pkging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_NewFileInfo(t *testing.T) {
|
||||||
|
|
||||||
|
in := []string{
|
||||||
|
"/public/images/img1.png",
|
||||||
|
"public/images/img1.png",
|
||||||
|
"/public\\images/img1.png",
|
||||||
|
"public/images\\img1.png",
|
||||||
|
"\\public\\images\\img1.png",
|
||||||
|
"public\\images\\img1.png",
|
||||||
|
"\\public/images\\img1.png",
|
||||||
|
"public\\images/img1.png",
|
||||||
|
"\\public\\images\\img1.png",
|
||||||
|
}
|
||||||
|
|
||||||
|
const exp = "/public/images/img1.png"
|
||||||
|
for _, n := range in {
|
||||||
|
t.Run(n, func(st *testing.T) {
|
||||||
|
r := require.New(st)
|
||||||
|
|
||||||
|
f1 := &FileInfo{
|
||||||
|
Details: Details{
|
||||||
|
Name: n,
|
||||||
|
Size: 42,
|
||||||
|
Mode: os.FileMode(0644),
|
||||||
|
IsDir: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
f2 := NewFileInfo(f1)
|
||||||
|
|
||||||
|
r.Equal(exp, f2.Name())
|
||||||
|
r.Equal(f1.Size(), f2.Size())
|
||||||
|
r.Equal(f1.Mode(), f2.Mode())
|
||||||
|
r.Equal(f1.IsDir(), f2.IsDir())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_WithName(t *testing.T) {
|
||||||
|
|
||||||
|
f1 := &FileInfo{
|
||||||
|
Details: Details{
|
||||||
|
Name: "/walls/crumbling",
|
||||||
|
Size: 42,
|
||||||
|
Mode: os.FileMode(0644),
|
||||||
|
IsDir: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const exp = "/public/images/img1.png"
|
||||||
|
in := []string{
|
||||||
|
"/public/images/img1.png",
|
||||||
|
"public/images/img1.png",
|
||||||
|
"/public\\images/img1.png",
|
||||||
|
"public/images\\img1.png",
|
||||||
|
"\\public\\images\\img1.png",
|
||||||
|
"public\\images\\img1.png",
|
||||||
|
"\\public/images\\img1.png",
|
||||||
|
"public\\images/img1.png",
|
||||||
|
"\\public\\images\\img1.png",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range in {
|
||||||
|
t.Run(n, func(st *testing.T) {
|
||||||
|
r := require.New(st)
|
||||||
|
|
||||||
|
f2 := WithName(n, f1)
|
||||||
|
|
||||||
|
r.Equal(exp, f2.Name())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,88 +3,32 @@ package mem
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
"github.com/markbates/pkger/pkging"
|
"github.com/markbates/pkger/pkging"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ pkging.Adder = &Pkger{}
|
|
||||||
|
|
||||||
// Add copies the pkging.File into the *Pkger
|
// Add copies the pkging.File into the *Pkger
|
||||||
func (fx *Pkger) Add(files ...*os.File) error {
|
func (fx *Pkger) Add(files ...pkging.File) error {
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
info, err := f.Stat()
|
info, err := f.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pt, err := fx.Parse(f.Name())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := f.Name()
|
if f.Path().Pkg == fx.Here.ImportPath {
|
||||||
if !info.IsDir() {
|
dir := filepath.Dir(f.Name())
|
||||||
dir = filepath.Dir(dir)
|
if dir != "/" {
|
||||||
}
|
if err := fx.MkdirAll(dir, 0755); err != nil {
|
||||||
|
|
||||||
her, err := here.Dir(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if info.IsDir() {
|
|
||||||
err = filepath.Walk(f.Name(), func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
pt, err := fx.Parse(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
her, err := here.Package(pt.Pkg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mf := &File{
|
mf := &File{
|
||||||
Here: her,
|
Here: f.Info(),
|
||||||
info: pkging.NewFileInfo(info),
|
info: pkging.NewFileInfo(info),
|
||||||
path: pt,
|
path: f.Path(),
|
||||||
pkging: fx,
|
|
||||||
}
|
|
||||||
|
|
||||||
if !info.IsDir() {
|
|
||||||
bb := &bytes.Buffer{}
|
|
||||||
_, err = io.Copy(bb, f)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mf.data = bb.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
fx.files.Store(mf.Path(), mf)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mf := &File{
|
|
||||||
Here: her,
|
|
||||||
info: pkging.NewFileInfo(info),
|
|
||||||
path: pt,
|
|
||||||
pkging: fx,
|
pkging: fx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package mem_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/here"
|
|
||||||
"github.com/markbates/pkger/pkging/mem"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Pkger_Add(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
cur, err := here.Package("github.com/markbates/pkger")
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
pkg, err := mem.New(cur)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
var exp []os.FileInfo
|
|
||||||
root := filepath.Join(cur.Dir, "pkging", "pkgtest", "testdata", "ref")
|
|
||||||
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
exp = append(exp, info)
|
|
||||||
return pkg.Add(f)
|
|
||||||
})
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
var act []os.FileInfo
|
|
||||||
err = pkg.Walk("/", func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
act = append(act, info)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
r.Len(act, len(exp))
|
|
||||||
|
|
||||||
for i, e := range exp {
|
|
||||||
a := act[i]
|
|
||||||
|
|
||||||
r.Equal(e.Name(), a.Name())
|
|
||||||
r.Equal(e.Size(), a.Size())
|
|
||||||
r.Equal(e.Mode(), a.Mode())
|
|
||||||
r.Equal(e.IsDir(), a.IsDir())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/pkging/pkgtest"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Pkger_Create(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
ref, err := pkgtest.NewRef()
|
|
||||||
r.NoError(err)
|
|
||||||
defer os.RemoveAll(ref.Dir)
|
|
||||||
|
|
||||||
pkg, err := New(ref.Info)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
pkgtest.CreateTest(t, ref, pkg)
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package mem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/markbates/pkger/pkging/pkgtest"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Pkger_Current(t *testing.T) {
|
|
||||||
r := require.New(t)
|
|
||||||
|
|
||||||
ref, err := pkgtest.NewRef()
|
|
||||||
r.NoError(err)
|
|
||||||
defer os.RemoveAll(ref.Dir)
|
|
||||||
|
|
||||||
pkg, err := New(ref.Info)
|
|
||||||
r.NoError(err)
|
|
||||||
|
|
||||||
pkgtest.CurrentTest(t, ref, pkg)
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue