Compare commits

...

130 Commits

Author SHA1 Message Date
Mark Bates 0273362499
Merge pull request #102 from requaos/requaos/gzip
Remove hepa library for revision at a later date
2020-08-12 13:53:52 -04:00
Neil Skinner c78e87acb0 Updating documentation to reflect the paths generated without the hepa library 2020-06-10 09:31:24 -04:00
Neil Skinner 143afe6a94 remove post-processing library hepa; pending revision 2020-06-09 10:09:43 -04:00
Mark Bates 992ea93a2a
Merge pull request #97 from qmuntal/master
Support const paths
2020-06-03 14:03:53 -04:00
Mark Bates d84a13e7c2
Merge pull request #101 from requaos/requaos/gzip
Apply hepa filters before gzip'ing content
2020-06-03 14:03:12 -04:00
Neil Skinner fdcec3a4ea Apply hepa filters before gzip'ing content
- markbates/pkger#26
2020-06-03 12:46:06 -04:00
Quim Muntal Diaz c7908c9bfc support const expressions 2020-05-21 17:19:19 +02:00
Mark Bates d97c60c346
Merge pull request #93 from xDuck/master
Fixes high cache miss rate, significant performance increase.
2020-05-15 17:09:09 -04:00
xDuck efed726c9e Fixes high cache miss rate, significant performance increase. Closes #92 2020-05-15 15:34:27 -04:00
Mark Bates c028e66556
Merge pull request #82 from xDuck/master
Add conditional build tag to generated files
2020-04-03 10:58:08 -04:00
Mark Bates 8554e69817
Merge pull request #83 from Bios-Marcel/patch-1
Fix a small typo
2020-04-03 10:57:47 -04:00
Marcel Schramm b4563ccbec
Fix a small typo 2020-03-27 20:01:47 +01:00
Chris 3c88c54d65
Removed optional tags with one tag, !skippkger 2020-03-24 14:14:21 -04:00
Chris 331c57067b
Moved build tags below code generation warning 2020-03-24 14:02:20 -04:00
Chris bc0ae93dc6
Added -t for specifying conditional build tags 2020-03-24 13:51:10 -04:00
Mark Bates a78c11e368
Merge pull request #80 from taiyangc/master
Fix pkger generating the wrong package name for pkger.go
2020-03-11 14:37:04 -04:00
Eric Chen 9552dcf46d Fix pkger generating the wrong package name for pkger.go
The issue is that, if pkger.go is created (empty) before the `go list
-json` call it will fail and give the generic directory name instead of the
actual package name under the directory. This is fine in most cases,
except when the package name differs from the directory name - which is
allowed. Then pkger.go will conflict and fail to compile with the rest
of *.go under the same directory.

To fix, we simply obtain the real package name before creating the dummy
pkger.go file and then pass the name into the file.
2020-03-11 03:31:03 -07:00
Mark Bates 5b8abbabca
Merge pull request #77 from ghouscht/issue-76
fix pkger error if a project contains a .go directory #76
2020-03-04 09:55:04 -05:00
Thomas Gosteli 5d81ba66cb fix pkger error if a project contains a .go directory #76 2020-03-04 14:33:57 +01:00
Mark Bates c9b56cd758
Merge pull request #70 from hnnsgstfssn/fix-typo
Fix typo
2020-02-17 16:29:53 -05:00
Hannes Gustafsson 9925b6cc05 Fix typo
4e1fe7b43f introduced a Fprintf call that
passes a variable without a formatting directive. This will cause go vet
-printf to fail with

    cmd/pkger/cmds/pack.go:150: no formatting directive in Fprintf call

Drop the variable from the call.
2020-02-16 22:05:56 +00:00
Mark Bates defb2921c0
Merge pull request #69 from hnnsgstfssn/add-generated-code-disclaimer
Add generated code disclaimer
2020-02-16 15:13:34 -05:00
Hannes Gustafsson 4e1fe7b43f Add generated code disclaimer
Generated code should contain a disclaimer as per [1].

Add a disclaimer to the top of the file generated by the pack command.

Fixes #68.

[1] https://golang.org/s/generatedcode
2020-02-16 19:54:06 +00:00
Mark Bates d9d5139985
Merge pull request #61 from markbates/fix-external-pkgs
Fixes issues with `<pkg>:/<name>` paths not resolving correctly.
2020-01-09 15:48:40 -05:00
Mark Bates 4a3675581d use pkg info from string parse 2020-01-08 17:37:55 -05:00
Mark Bates c5e820d039
Merge pull request #50 from markbates/here-here
use gobuffalo/here fixes #49
2019-12-17 10:19:58 -05:00
Mark Bates db2f21a8c7 see yourself 2019-12-17 10:16:55 -05:00
Mark Bates 7a3189e727 Merge branch 'master' into here-here 2019-12-17 10:12:20 -05:00
Mark Bates 6217c988eb
Merge pull request #55 from moqmar/master
Provide workaround for segmentation fault (fixes #54)
2019-12-17 10:08:08 -05:00
Moritz Marquardt 2a4daae578
Provide workaround for segmentation fault (fixes #54) 2019-12-16 09:09:58 +01:00
Mark Bates 6c1b23a5cb new include 2019-12-13 11:24:17 -05:00
Mark Bates 5497054b42
Merge pull request #53 from markbates/handle-main
handle main packages
2019-12-11 15:15:54 -05:00
Mark Bates 945a3a2811
Merge branch 'master' into handle-main 2019-12-11 15:04:01 -05:00
Mark Bates b334bd73ac handle main functions 2019-12-11 15:02:51 -05:00
Mark Bates b0a67f7917
Merge pull request #52 from koddr/patch-1
Fixed import block (generated pkged.go file)
2019-12-11 15:02:41 -05:00
Vic Shóstak 9d57b03b3c
Fixed import block 2019-12-05 22:09:34 +03:00
Mark Bates 6431634511 better error 2019-12-03 17:40:04 -05:00
Mark Bates 0167919fce ignore .tmp stuff 2019-12-03 17:36:58 -05:00
Mark Bates e4d652a24e revert 2019-12-03 15:32:08 -05:00
Mark Bates ec8c803b27 verbs 2019-12-03 15:29:17 -05:00
Mark Bates b24faf1070 get -t 2019-12-03 15:23:12 -05:00
Mark Bates 94798bc8a6 remove 1.12 2019-12-03 15:13:55 -05:00
Mark Bates 10f43292e9 github stuff 2019-12-03 15:11:25 -05:00
Mark Bates 16972f8f18 use gobuffalo/here fixes #49 2019-12-03 15:07:51 -05:00
Mark Bates 7752bb822e magic prize 2019-11-21 11:42:19 -05:00
Mark Bates 43a11bf0fc fix goreleaser 2019-11-21 11:35:54 -05:00
Mark Bates d6ca5ac119
Merge pull request #41 from markbates/github-actions 2019-11-21 08:33:32 -08:00
Mark Bates 32f1de1b25 the ship is leaking 2019-11-21 11:31:06 -05:00
Mark Bates 2560bdca09 in the sun 2019-11-21 11:29:00 -05:00
Mark Bates ddc055cac4 tidy 2019-11-21 09:02:05 -05:00
Mark Bates e611253b7b dop 2019-11-21 08:53:05 -05:00
Mark Bates 0b8a69abe2 why? 2019-11-21 08:07:00 -05:00
Mark Bates b40b98d739 do you? 2019-11-20 22:02:20 -05:00
Mark Bates c83687a932 copy sum too 2019-11-20 21:58:48 -05:00
Mark Bates 8f84b7462f sum 2019-11-20 21:54:48 -05:00
Mark Bates 9b9b72922d the killing curse 2019-11-20 21:50:35 -05:00
Mark Bates f548238cc7
Merge pull request #40 from devnode/fix-file-seek
missing File.reader initialization on Seek()
2019-11-20 18:43:18 -08:00
Tom Mombourquette 5d492d737f removed io package for consistency 2019-11-20 21:48:09 -04:00
Tom Mombourquette b8247ce972 added test 2019-11-20 19:17:36 -04:00
Tom Mombourquette d9ef17a04d initial 2019-11-20 16:36:29 -04:00
Mark Bates 3f76ab6dd9 version bump: v0.12.5 2019-11-20 05:50:48 -08:00
Mark Bates 338906395e version bump: v0.12.4 2019-11-17 10:10:11 -08:00
Mark Bates 9ca6c03d94 version bump: v0.12.3 2019-11-14 11:51:18 -05:00
Mark Bates 6089e09d37
Merge pull request #35 from markbates/fix-no-go-err
`go list` need at least one `.go` file in the root of the project fixes #34
2019-11-14 08:50:27 -08:00
Mark Bates 0c7e018c10 `go list` need at least one `.go` file in the root of the project fixes #34 2019-11-13 17:29:41 -05:00
Mark Bates 7a5b071f5b version bump: v0.12.2 2019-11-11 18:21:41 -05:00
Mark Bates b4c1e6e713
Merge pull request #31 from markbates/rocks-my-soul
drag it up
2019-11-11 15:21:17 -08:00
Mark Bates 1e03febf38 drag it up 2019-11-11 18:17:26 -05:00
Mark Bates d14ce58f35 version bump: v0.12.1 2019-11-11 17:56:13 -05:00
Mark Bates f25d3ebfe9
Merge pull request #30 from nlepage/fix/out_pkged
fix embed not working with -o
2019-11-11 14:55:39 -08:00
Mark Bates 7067fa6132 docs 2019-11-11 17:45:39 -05:00
Nicolas Lepage b97aa787b5
fix embed not working with -o 2019-11-11 23:34:17 +01:00
Mark Bates c69a63df8d version bump: v0.12.0 2019-11-11 17:27:36 -05:00
Mark Bates e6edc3713b
Merge pull request #29 from markbates/minotaur
Adds -include flag and pkger.Include directive fixes #28
2019-11-11 14:26:35 -08:00
Mark Bates b3c81b5fd3 docs 2019-11-11 17:21:59 -05:00
Mark Bates 8879dba851 remove out file if packing panics 2019-11-11 16:46:12 -05:00
Mark Bates 7ee0500044 Adds -include flag and pkger.Include directive fixes #28 2019-11-11 16:01:05 -05:00
Mark Bates 1a3cb0f04d update README.md 2019-11-10 18:59:20 -05:00
Mark Bates d90c068476 version bump: v0.11.0 2019-11-10 18:50:09 -05:00
Mark Bates 834898d6b5
Merge pull request #25 from markbates/out-flag
add -o flag
2019-11-10 15:49:12 -08:00
Mark Bates 5c0596fcb6
Merge branch 'master' into out-flag 2019-11-10 15:44:45 -08:00
Mark Bates 9da9f00821 add -o flag 2019-11-10 18:43:12 -05:00
Mark Bates 342e00a7be
Merge pull request #24 from markbates/aperezg-22_detect_gomod_no_pkg
Error when a directory contains no `.go` or `go.mod` files fixes #22
2019-11-10 15:42:52 -08:00
Mark Bates ac15f56d3f match error for nonGoDirRx 2019-11-10 18:38:44 -05:00
Mark Bates 794943f042 now with less printlns and more tests 2019-11-10 18:27:57 -05:00
Mark Bates 812232aaff improve error testing for non go directories.
also cleans up there here.Info api
2019-11-10 18:22:06 -05:00
Mark Bates 2a9f9649bb stabilize tests 2019-11-10 17:22:01 -05:00
Mark Bates b4f921bd19 reset the testdata/ref app 2019-11-10 17:09:54 -05:00
Mark Bates 37ad5dad0f Revert "remove accidental testdata"
This reverts commit 93cf940d5a.
2019-11-10 17:09:08 -05:00
Mark Bates 93cf940d5a remove accidental testdata 2019-11-10 17:06:28 -05:00
aperezg e8ea7c2ce8 modify test stuff to cover the case for isolated go.mod 2019-11-10 14:11:07 +01:00
aperezg 6a21c5378b remove ImportPath from NewInfoFromPath 2019-11-10 11:56:09 +01:00
aperezg 71d20943f0 check if there a go.mod in a directory without any go files 2019-11-09 20:43:22 +01:00
aperezg 6cf141c51a remove unnecessary conversion 2019-11-09 20:26:33 +01:00
Mark Bates 2a3000b896 version bump: v0.10.1 2019-11-08 11:21:34 -08:00
Mark Bates 5e527e6ae5
Merge pull request #20 from markbates/pkger-hangs
pkger hangs fixes #19
2019-11-08 11:21:09 -08:00
Mark Bates 632f108343 ignore .C errors 2019-11-08 11:07:33 -08:00
Mark Bates ac960d47a9 pkger hangs fixes #19 2019-11-08 11:05:03 -08:00
Mark Bates 9a9d8d6275
Update README.md 2019-11-05 15:22:08 -05:00
Mark Bates 992448a71b
Update README.md 2019-11-05 15:21:12 -05:00
Mark Bates a04b1791e4 version bump: v0.10.0 2019-11-05 15:16:50 -05:00
Mark Bates 08fb31c710
Merge pull request #17 from markbates/declan-macmanus
skip ignoreable directories
2019-11-05 15:16:12 -05:00
Mark Bates 889d184af7 prime the mod cache 2019-11-05 15:09:28 -05:00
Mark Bates e7599507eb giggling crew 2019-11-05 15:04:38 -05:00
Mark Bates 5a8d085fb8 long lost 2019-11-05 11:55:53 -05:00
Mark Bates d96dfd3e37 always be tidying 2019-11-05 11:52:13 -05:00
Mark Bates 9ef79c78e8 test for external module 2019-11-05 11:44:15 -05:00
Mark Bates 20292c885b skip ignoreable directories 2019-11-04 11:48:06 -05:00
Mark Bates 3cbd07f98b fix stat example 2019-11-01 16:22:08 -04:00
Mark Bates 9473092e41 version bump: v0.9.0 2019-11-01 16:12:39 -04:00
Mark Bates afce25df00
Merge pull request #16 from markbates/elvis
Elvis
2019-11-01 16:12:18 -04:00
Mark Bates 1fa89d0323 Digging the "Dancing Queen" 2019-11-01 16:08:10 -04:00
Mark Bates 93d467fbde You were a spoilt child then with a record to plug 2019-11-01 16:04:37 -04:00
Mark Bates 952d962d54 Imploring: "Another melody?" 2019-11-01 16:00:30 -04:00
Mark Bates c191846c48 You gave me this tattoo back in '82 2019-11-01 15:53:54 -04:00
Mark Bates cc6861871c better tests 2019-10-31 17:20:15 -04:00
Mark Bates d41fe52ef2 a self-made mug is hard to break 2019-10-31 11:12:18 -04:00
Mark Bates 5c07a3dede it's not your punch then it's your pout 2019-10-31 11:06:20 -04:00
Mark Bates 6638215c4d where is the harmony? 2019-10-30 17:32:47 -04:00
Mark Bates 296799efbc even though I've seen the movie 2019-10-30 17:15:49 -04:00
Mark Bates b9ac82f558 always fascinated by the weird edge of town 2019-10-30 16:56:22 -04:00
Mark Bates f79eafd257 his suntan lotion and his castanets 2019-10-30 16:49:55 -04:00
Mark Bates da03471d96 juliet was waiting with a safety net 2019-10-30 16:39:05 -04:00
Mark Bates 0edd9cf5cc please don't stick me on the late shift 2019-10-30 13:05:35 -04:00
Mark Bates 4481d6120d 13 steps lead down 2019-10-30 11:31:39 -04:00
Mark Bates 13275eea7b Close-up of the sign that says,"We never close" 2019-10-25 17:11:34 -04:00
Mark Bates 77f832ce9e version bump: v0.8.1 2019-10-25 15:30:59 -04:00
Mark Bates 49b57cab14 you remind me of everyone 2019-10-25 15:30:12 -04:00
Mark Bates c84d74f6cf version bump: v0.8.0 2019-10-25 11:42:16 -04:00
Mark Bates 5e795946c5
Merge pull request #15 from markbates/marshal-mathers
do run run
2019-10-25 11:41:54 -04:00
158 changed files with 3655 additions and 9968 deletions

4
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: markbates
patreon: buffalo

28
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,28 @@
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

25
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,25 @@
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 ./...

View File

@ -1,33 +1,45 @@
# Code generated by github.com/gobuffalo/release. DO NOT EDIT.
# Edit .goreleaser.yml.plush instead
builds: builds:
- -
goos: main: ./cmd/pkger/main.go
- darwin env:
- linux - CGO_ENABLED=0
- windows ldflags:
env: - -s -w -X "github.com/markbates/pkger.Version={{.Tag}}"
- CGO_ENABLED=0 goos:
main: ./cmd/pkger/main.go - darwin
- linux
- windows
goarch:
- amd64
- 386
- 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"

View File

@ -1,30 +0,0 @@
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
<% } %>

View File

@ -17,7 +17,7 @@ build: tidy
make tidy make tidy
test: tidy test: tidy
$(GO_BIN) test -cover -tags ${TAGS} -timeout 5s ./... $(GO_BIN) test -count 1 -cover -tags ${TAGS} -timeout 1m ./...
make tidy make tidy
cov: cov:

394
README.md
View File

@ -2,7 +2,12 @@
[`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).
## How it Works ### Requirements
* 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.
@ -19,22 +24,146 @@ 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" => $GOPATH/pkg/mod/github.com/gobuffalo/buffalo@v0.14.7/go.mod "github.com/gobuffalo/buffalo:/go.mod" => /go/pkg/mod/github.com/gobuffalo/buffalo@v0.14.7/go.mod
``` ```
## Usage ## CLI
### 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)
@ -48,7 +177,6 @@ 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)
@ -61,38 +189,56 @@ type File interface {
} }
``` ```
```bash These two interfaces, along with the [`os#FileInfo`](https://godoc.org/os#FileInfo), provide the bulk of the API surface area.
├── go.mod
├── go.sum ### Open
├── main.go
├── public
│   ├── images
│   │   ├── mark-small.png
│   │   ├── img1.png
│   │   ├── mark_250px.png
│   │   └── mark_400px.png
│   └── index.html
```
```go ```go
package main func run() error {
f, err := pkger.Open("/public/index.html")
import ( if err != nil {
"fmt" return err
"log"
"os"
"text/tabwriter"
"time"
"github.com/markbates/pkger"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
} }
} defer f.Close()
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
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
}
```
### 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()
@ -116,31 +262,171 @@ func run() error {
} }
``` ```
### Output Without Packing ## Understanding the Parser
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
# compile the go binary as usual and run the app: $ pkger parse
$ go build -v; ./app
public | 128 | drwxr-xr-x | 2019-10-18T16:24:55-04:00 | {
images | 128 | drwxr-xr-x | 2019-10-18T16:24:55-04:00 | ".": [
img1.png | 27718 | -rw-r--r-- | 2019-10-18T16:24:55-04:00 | {
img2.png | 27718 | -rw-r--r-- | 2019-10-18T16:24:55-04:00 | "file": {
index.html | 257 | -rw-r--r-- | 2019-10-18T16:24:55-04:00 | "Abs": "/go/src/github.com/markbates/pkger/pkging/pkgtest/testdata/ref/foo/bar/baz",
"Path": {
"Pkg": "app",
"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"
},
...
]
}
``` ```
### Output With Packing For a module aware list use the `pkger list` command.
```bash ```bash
# run the pkger cli to generate a pkged.go file: $ pkger list
$ pkger
# compile the go binary as usual and run the app: app
$ go build -v; ./app > app:/assets
> app:/assets/css
public | 128 | drwxr-xr-x | 2019-10-18T16:24:55-04:00 | > app:/assets/css/_buffalo.scss
images | 128 | drwxr-xr-x | 2019-10-18T16:24:55-04:00 | > app:/assets/css/application.scss
img1.png | 27718 | -rw-r--r-- | 2019-10-18T16:24:55-04:00 | > app:/assets/images
img2.png | 27718 | -rw-r--r-- | 2019-10-18T16:24:55-04:00 | > app:/assets/images/favicon.ico
index.html | 257 | -rw-r--r-- | 2019-10-18T16:24:55-04:00 | > 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:/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"
}
},
...
}
```

View File

@ -1,5 +1,3 @@
// +build !debug
package pkger package pkger
import ( import (

View File

@ -1,48 +0,0 @@
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

View File

@ -1,19 +0,0 @@
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"

View File

@ -6,18 +6,18 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"path/filepath"
"github.com/markbates/pkger" "github.com/markbates/pkger"
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa"
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa/filters"
"github.com/markbates/pkger/parser" "github.com/markbates/pkger/parser"
) )
type listCmd struct { type listCmd struct {
*flag.FlagSet *flag.FlagSet
help bool help bool
json bool json bool
subs []command include slice
subs []command
} }
func (e *listCmd) Name() string { func (e *listCmd) Name() string {
@ -39,17 +39,17 @@ func (e *listCmd) Exec(args []string) error {
return err return err
} }
fp := info.FilePath(outName) fp := filepath.Join(info.Dir, outName)
os.RemoveAll(fp) os.RemoveAll(fp)
decls, err := parser.Parse(info) decls, err := parser.Parse(info, e.include...)
if err != nil { if err != nil {
return err return err
} }
jay := struct { jay := struct {
ImportPath string `json:"import_path"` ImportPath string
Files []*parser.File `json:"files"` Files []*parser.File
}{ }{
ImportPath: info.ImportPath, ImportPath: info.ImportPath,
} }
@ -69,15 +69,7 @@ func (e *listCmd) Exec(args []string) error {
return err return err
} }
hep := hepa.New() _, err = os.Stdout.Write(bb.Bytes())
hep = hepa.With(hep, filters.Home())
hep = hepa.With(hep, filters.Golang())
b, err := hep.Filter(bb.Bytes())
if err != nil {
return err
}
_, err = os.Stdout.Write(b)
return err return err
} }
@ -92,6 +84,7 @@ func (e *listCmd) Flags() *flag.FlagSet {
if e.FlagSet == nil { if e.FlagSet == nil {
e.FlagSet = flag.NewFlagSet("list", flag.ExitOnError) e.FlagSet = flag.NewFlagSet("list", flag.ExitOnError)
e.BoolVar(&e.json, "json", false, "prints in JSON format") 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) e.Usage = Usage(os.Stderr, e.FlagSet)
return e.FlagSet return e.FlagSet

View File

@ -4,20 +4,35 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"path/filepath"
"sort" "sort"
"strings" "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
help bool out string
subs []command help bool
include slice
subs []command
} }
func (e *packCmd) Name() string { func (e *packCmd) Name() string {
@ -30,15 +45,15 @@ func (e *packCmd) Exec(args []string) error {
return err return err
} }
fp := info.FilePath(outName) fp := filepath.Join(info.Dir, e.out, outName)
os.RemoveAll(fp) os.RemoveAll(fp)
decls, err := parser.Parse(info) decls, err := parser.Parse(info, e.include...)
if err != nil { if err != nil {
return err return err
} }
if err := Package(fp, decls); err != nil { if err := Package(info, fp, decls); err != nil {
return err return err
} }
@ -88,6 +103,8 @@ func New() (*packCmd, error) {
c.FlagSet = flag.NewFlagSet("pkger", flag.ExitOnError) c.FlagSet = flag.NewFlagSet("pkger", flag.ExitOnError)
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)()
@ -106,8 +123,18 @@ func (e *packCmd) Flags() *flag.FlagSet {
return e.FlagSet return e.FlagSet
} }
func Package(out string, decls parser.Decls) error { func Package(info here.Info, 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 {
@ -115,16 +142,14 @@ func Package(out string, decls parser.Decls) error {
} }
defer f.Close() defer f.Close()
c, err := pkger.Current() fmt.Fprintf(f, "// Code generated by pkger; DO NOT EDIT.\n\n")
if err != nil { fmt.Fprintf(f, "// +build !skippkger\n\n")
return err
}
fmt.Fprintf(f, "package %s\n\n", c.Name) fmt.Fprintf(f, "package %s\n\n", c.Name)
fmt.Fprintf(f, "import \"github.com/markbates/pkger\"\n\n") fmt.Fprintf(f, "import (\n\t\"github.com/markbates/pkger\"\n\t")
fmt.Fprintf(f, "import \"github.com/markbates/pkger/pkging/mem\"\n\n") fmt.Fprintf(f, "\"github.com/markbates/pkger/pkging/mem\"\n)\n\n")
fmt.Fprintf(f, "\nvar _ = pkger.Apply(mem.UnmarshalEmbed([]byte(`") fmt.Fprintf(f, "var _ = pkger.Apply(mem.UnmarshalEmbed([]byte(`")
if err := pkgutil.Stuff(f, c, decls); err != nil { if err := pkgutil.Stuff(f, info, decls); err != nil {
return err return err
} }

View File

@ -45,11 +45,21 @@ func (c *parseCmd) Exec(args []string) error {
m := map[string]parser.Decls{} m := map[string]parser.Decls{}
for _, a := range args { for _, a := range args {
info, err := here.Package(a) var info here.Info
if err != nil { var err error
return err
}
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) decls, err := parser.Parse(info)
if err != nil { if err != nil {
return err return err

View File

@ -10,7 +10,7 @@ import (
func main() { func main() {
clean := func() { clean := func() {
c := exec.Command("go", "mod", "tidy", "-v") c := exec.Command("go", "mod", "tidy")
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,6 +18,13 @@ 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)

View File

@ -1,6 +1,10 @@
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=
@ -18,3 +22,5 @@ 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 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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=

View File

@ -1,8 +0,0 @@
// +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

View File

@ -1,5 +1,4 @@
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 .

View File

@ -2,4 +2,6 @@ module app
go 1.13 go 1.13
require github.com/markbates/pkger v0.0.0-20191016200917-09e9684b656b require github.com/markbates/pkger v0.8.0
replace github.com/markbates/pkger => ../../../

View File

@ -6,8 +6,6 @@ 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=
@ -16,5 +14,6 @@ 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=

View File

@ -0,0 +1,7 @@
FROM alpine
EXPOSE 3000
COPY example /bin/
CMD /bin/example

View File

@ -0,0 +1,5 @@
default:
pkger
GOOS=linux go build -v -o example
docker build -t pkger:example .
docker run -p 3000:3000 pkger:example

View File

@ -0,0 +1,7 @@
module app
go 1.13
require github.com/markbates/pkger v0.8.0
replace github.com/markbates/pkger => ../../../

View File

@ -0,0 +1,19 @@
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=

View File

@ -0,0 +1,28 @@
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
}

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -0,0 +1,7 @@
FROM alpine
EXPOSE 3000
COPY example /bin/
CMD /bin/example

View File

@ -0,0 +1,4 @@
default:
GOOS=linux go build -v -o example
docker build -t pkger:example .
docker run -p 3000:3000 pkger:example

3
examples/stat/std/go.mod Normal file
View File

@ -0,0 +1,3 @@
module app
go 1.13

27
examples/stat/std/main.go Normal file
View File

@ -0,0 +1,27 @@
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.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -0,0 +1,12 @@
<!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>

View File

@ -1,8 +0,0 @@
// +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

5
go.mod
View File

@ -3,9 +3,6 @@ module github.com/markbates/pkger
go 1.13 go 1.13
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/gobuffalo/here v0.6.0
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
View File

@ -1,7 +1,8 @@
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=
@ -9,14 +10,13 @@ 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.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,29 +0,0 @@
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
}

View File

@ -1,53 +0,0 @@
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
}

View File

@ -1,39 +1,14 @@
package here package here
import ( import (
"bytes" "github.com/gobuffalo/here"
"os"
"os/exec"
"sync"
) )
var cache = &infoMap{ type Info = here.Info
data: &sync.Map{}, type Module = here.Module
} type Path = here.Path
func run(n string, args ...string) ([]byte, error) { var Here = here.New()
c := exec.Command(n, args...) var Dir = Here.Dir
var Package = Here.Package
bb := &bytes.Buffer{} var Current = Here.Current
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
}

View File

@ -1,88 +0,0 @@
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
Module Module
}
func (fi Info) MarshalJSON() ([]byte, error) {
mm := map[string]interface{}{
"ImportPath": fi.ImportPath,
"Name": fi.Name,
"Module": fi.Module,
"Dir": fi.Dir,
}
b, err := json.Marshal(mm)
if err != nil {
return nil, err
}
hep := hepa.New()
hep = hepa.With(hep, filters.Home())
hep = hepa.With(hep, filters.Golang())
return hep.Filter(b)
}
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
}

View File

@ -1,87 +0,0 @@
// 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
}

View File

@ -1,55 +0,0 @@
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()
}

View File

@ -1,63 +0,0 @@
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("([^:]+)(:(/.+))?")

View File

@ -1,61 +0,0 @@
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: "/"}},
{in: filepath.Join(app.Info.Dir, "public"), exp: here.Path{Pkg: ip, Name: "/public"}},
}
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)
})
}
}
}

View File

@ -1,20 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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
}

View File

@ -1,21 +0,0 @@
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.

View File

@ -1,35 +0,0 @@
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
}
}

View File

@ -1,42 +0,0 @@
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
}()

View File

@ -1,12 +0,0 @@
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
}

View File

@ -1,51 +0,0 @@
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
}

View File

@ -1,31 +0,0 @@
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

View File

@ -1,29 +0,0 @@
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",
}

View File

@ -1,15 +0,0 @@
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
}

View File

@ -1,67 +0,0 @@
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{}
}

View File

@ -1,4 +0,0 @@
package hepa
// Version of hepa
const Version = "v0.0.1"

View File

@ -10,7 +10,7 @@ var _ Decl = CreateDecl{}
type CreateDecl struct { type CreateDecl struct {
file *File file *File
pos token.Pos pos token.Position
value string value string
} }
@ -35,10 +35,7 @@ func (d CreateDecl) File() (*File, error) {
return d.file, nil return d.file, nil
} }
func (d CreateDecl) Pos() (token.Pos, error) { func (d CreateDecl) Position() (token.Position, error) {
if d.pos <= 0 {
return -1, os.ErrNotExist
}
return d.pos, nil return d.pos, nil
} }

View File

@ -1,13 +1,14 @@
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)
Pos() (token.Pos, error) Position() (token.Position, error)
Value() (string, error) Value() (string, error)
} }
@ -39,11 +40,12 @@ func (decls Decls) Files() ([]*File, error) {
files, err := fl.Files(v) files, err := fl.Files(v)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("%s: %s", err, d)
} }
for _, f := range files { for _, f := range files {
m[f.Path.String()] = f m[f.Abs] = f
v[f.Abs] = f.Abs
} }
} }

View File

@ -2,11 +2,6 @@ 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"
) )
@ -21,36 +16,3 @@ 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)
}

View File

@ -10,7 +10,7 @@ var _ Decl = HTTPDecl{}
type HTTPDecl struct { type HTTPDecl struct {
file *File file *File
pos token.Pos pos token.Position
value string value string
} }
@ -35,10 +35,7 @@ func (d HTTPDecl) File() (*File, error) {
return d.file, nil return d.file, nil
} }
func (d HTTPDecl) Pos() (token.Pos, error) { func (d HTTPDecl) Position() (token.Position, error) {
if d.pos <= 0 {
return -1, os.ErrNotExist
}
return d.pos, nil return d.pos, nil
} }
@ -55,5 +52,6 @@ func (d HTTPDecl) Files(virtual map[string]string) ([]*File, error) {
pos: d.pos, pos: d.pos,
value: d.value, value: d.value,
} }
return od.Files(virtual) return od.Files(virtual)
} }

88
parser/include.go Normal file
View File

@ -0,0 +1,88 @@
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)
}

View File

@ -10,7 +10,7 @@ var _ Decl = MkdirAllDecl{}
type MkdirAllDecl struct { type MkdirAllDecl struct {
file *File file *File
pos token.Pos pos token.Position
value string value string
} }
@ -35,10 +35,7 @@ func (d MkdirAllDecl) File() (*File, error) {
return d.file, nil return d.file, nil
} }
func (d MkdirAllDecl) Pos() (token.Pos, error) { func (d MkdirAllDecl) Position() (token.Position, error) {
if d.pos <= 0 {
return -1, os.ErrNotExist
}
return d.pos, nil return d.pos, nil
} }

View File

@ -5,16 +5,13 @@ import (
"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.Pos pos token.Position
value string value string
} }
@ -39,10 +36,7 @@ func (d OpenDecl) File() (*File, error) {
return d.file, nil return d.file, nil
} }
func (d OpenDecl) Pos() (token.Pos, error) { func (d OpenDecl) Position() (token.Position, error) {
if d.pos <= 0 {
return -1, os.ErrNotExist
}
return d.pos, nil return d.pos, nil
} }
@ -58,17 +52,10 @@ func (d OpenDecl) Files(virtual map[string]string) ([]*File, error) {
return nil, nil return nil, nil
} }
pt, err := pkger.Parse(d.value) her := d.file.Here
if err != nil { pt := d.file.Path
return nil, err
}
her, err := here.Package(pt.Pkg) fp := filepath.Join(her.Module.Dir, pt.Name)
if err != nil {
return nil, err
}
fp := filepath.Join(her.Dir, pt.Name)
osf, err := os.Stat(fp) osf, err := os.Stat(fp)
if err != nil { if err != nil {
@ -85,11 +72,7 @@ func (d OpenDecl) Files(virtual map[string]string) ([]*File, error) {
} }
var files []*File var files []*File
files = append(files, &File{ files = append(files, d.file)
Abs: filepath.Join(her.Dir, pt.Name),
Path: pt,
Here: her,
})
return files, nil return files, nil
} }

View File

@ -4,56 +4,237 @@ 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", "_fixtures", "testdata"} var defaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "testdata"}
func Parse(her here.Info) (Decls, error) { func New(her here.Info) (*Parser, error) {
src, err := fromSource(her) return &Parser{
if err != nil { Info: her,
return nil, err decls: map[string]Decls{},
} }, nil
return src, nil
} }
func fromSource(her here.Info) (Decls, error) { type Parser struct {
root := her.Dir here.Info
fi, err := os.Stat(root) decls map[string]Decls
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
} }
if !fi.IsDir() { p.includes = includes
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",
"Create",
"Include",
"Stat",
"Open",
"Dir",
"Walk",
}
for _, pkg := range pkgs { for _, n := range orderedNames {
for name, pf := range pkg.Files { decls = append(decls, p.decls[n]...)
f := &file{
fset: fset,
astFile: pf,
filename: name,
}
x, err := f.find()
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
}

View File

@ -1,93 +1,122 @@
package parser_test package parser
import ( import (
"fmt" "fmt"
"os"
"os/exec"
"path/filepath" "path/filepath"
"sort" "strings"
"testing" "testing"
"github.com/markbates/pkger/here" "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_App(t *testing.T) { func Test_Parser_Ref(t *testing.T) {
defer func() {
c := exec.Command("go", "mod", "tidy", "-v")
c.Run()
}()
r := require.New(t) r := require.New(t)
app, err := pkgtest.App() ref, err := pkgtest.NewRef()
r.NoError(err)
defer os.RemoveAll(ref.Dir)
disk, err := stdos.New(ref.Info)
r.NoError(err) r.NoError(err)
res, err := parser.Parse(app.Info) _, err = pkgtest.LoadFiles("/", ref, disk)
r.NoError(err)
res, err := Parse(ref.Info)
r.NoError(err)
files, err := res.Files()
r.NoError(err)
for _, f := range files {
fmt.Println(f.Path)
}
r.Len(files, 25)
}
func Test_Parser_Ref_Include(t *testing.T) {
defer func() {
c := exec.Command("go", "mod", "tidy", "-v")
c.Run()
}()
r := require.New(t)
ref, err := pkgtest.NewRef()
r.NoError(err)
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) r.NoError(err)
files, err := res.Files() files, err := res.Files()
r.NoError(err) r.NoError(err)
act := make([]string, len(files)) l := len(files)
for i := 0; i < len(files); i++ { r.Equal(26, l)
act[i] = files[i].Path.String()
}
sort.Strings(act)
for _, a := range act {
fmt.Println(a)
}
r.Equal(app.Paths.Parser, act)
} }
func Test_Parse_Dynamic_Files(t *testing.T) { func Test_Parser_dotGo_Directory(t *testing.T) {
r := require.New(t) r := require.New(t)
app, err := dynamic() ref, err := pkgtest.NewRef()
r.NoError(err)
defer os.RemoveAll(ref.Dir)
err = os.Mkdir(filepath.Join(ref.Dir, ".go"), 0755)
r.NoError(err) r.NoError(err)
res, err := parser.Parse(app.Info) 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) r.NoError(err)
files, err := res.Files() files, err := res.Files()
r.NoError(err) r.NoError(err)
r.Len(files, 5)
r.Len(files, 1) for _, f := range files {
r.True(strings.HasPrefix(f.Abs, her.Dir), "%q %q", f.Abs, her.Dir)
f := files[0] r.True(strings.HasPrefix(f.Path.Name, "/public"), "%q %q", f.Path.Name, "/public")
r.Equal("/go.mod", f.Path.Name) }
}
// dynamic returns here.info that represents the
// ./internal/testdata/app. This should be used
// by tests.
func dynamic() (pkgtest.AppDetails, error) {
var app pkgtest.AppDetails
her, err := here.Package("github.com/markbates/pkger")
if err != nil {
return app, err
}
info := here.Info{
ImportPath: "dynamic",
}
ch := filepath.Join(
her.Dir,
"pkging",
"pkgtest",
"internal",
"testdata",
"dynamic")
info.Dir = ch
info, err = here.Cache(info.ImportPath, func(s string) (here.Info, error) {
return info, nil
})
if err != nil {
return app, err
}
app.Info = info
return app, nil
} }

216
parser/source.go Normal file
View File

@ -0,0 +1,216 @@
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
}

View File

@ -2,25 +2,21 @@ package parser
import ( import (
"encoding/json" "encoding/json"
"fmt"
"go/token" "go/token"
"os" "os"
"path/filepath"
"github.com/markbates/pkger"
"github.com/markbates/pkger/here"
) )
var _ Decl = StatDecl{} var _ Decl = StatDecl{}
type StatDecl struct { type StatDecl struct {
file *File file *File
pos token.Pos pos token.Position
value string value string
} }
func (d StatDecl) String() string { func (d StatDecl) String() string {
b, _ := json.Marshal(d) return fmt.Sprintf("pkger.Stat(%q)", d.value)
return string(b)
} }
func (d StatDecl) MarshalJSON() ([]byte, error) { func (d StatDecl) MarshalJSON() ([]byte, error) {
@ -39,10 +35,7 @@ func (d StatDecl) File() (*File, error) {
return d.file, nil return d.file, nil
} }
func (d StatDecl) Pos() (token.Pos, error) { func (d StatDecl) Position() (token.Position, error) {
if d.pos <= 0 {
return -1, os.ErrNotExist
}
return d.pos, nil return d.pos, nil
} }
@ -54,26 +47,11 @@ func (d StatDecl) Value() (string, error) {
} }
func (d StatDecl) Files(virtual map[string]string) ([]*File, error) { func (d StatDecl) Files(virtual map[string]string) ([]*File, error) {
if _, ok := virtual[d.value]; ok { od := OpenDecl{
return nil, nil file: d.file,
pos: d.pos,
value: d.value,
} }
pt, err := pkger.Parse(d.value) return od.Files(virtual)
if err != nil {
return nil, err
}
her, err := here.Package(pt.Pkg)
if err != nil {
return nil, err
}
var files []*File
files = append(files, &File{
Abs: filepath.Join(her.Dir, pt.Name),
Path: pt,
Here: her,
})
return files, nil
} }

View File

@ -1,343 +0,0 @@
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) {
// --- virtual calls first ---
if err := f.findMkdirAllCalls(); err != nil {
return nil, err
}
if err := f.findCreateCalls(); err != nil {
return nil, err
}
// -- physical calls second ---
if err := f.findStatCalls(); err != nil {
return nil, err
}
if err := f.findOpenCalls(); err != nil {
return nil, err
}
if err := f.findHTTPCalls(); 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) findMkdirAllCalls() 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", "MkdirAll")
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 := MkdirAllDecl{
file: pf,
pos: n.Pos(),
value: s,
}
f.decls = append(f.decls, decl)
return true
})
return err
}
func (f *file) findStatCalls() 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", "Stat")
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 := StatDecl{
file: pf,
pos: n.Pos(),
value: s,
}
f.decls = append(f.decls, decl)
return true
})
return err
}
func (f *file) findCreateCalls() 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", "Create")
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 := CreateDecl{
file: pf,
pos: n.Pos(),
value: s,
}
f.decls = append(f.decls, decl)
return true
})
return err
}
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
}
func (f *file) findHTTPCalls() 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", "Dir")
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 := HTTPDecl{
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
}

View File

@ -7,7 +7,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/markbates/pkger"
"github.com/markbates/pkger/here" "github.com/markbates/pkger/here"
) )
@ -15,7 +14,7 @@ var _ Decl = WalkDecl{}
type WalkDecl struct { type WalkDecl struct {
file *File file *File
pos token.Pos pos token.Position
value string value string
} }
@ -40,10 +39,7 @@ func (d WalkDecl) File() (*File, error) {
return d.file, nil return d.file, nil
} }
func (d WalkDecl) Pos() (token.Pos, error) { func (d WalkDecl) Position() (token.Position, error) {
if d.pos <= 0 {
return -1, os.ErrNotExist
}
return d.pos, nil return d.pos, nil
} }
@ -55,25 +51,32 @@ func (d WalkDecl) Value() (string, error) {
} }
func (d WalkDecl) Files(virtual map[string]string) ([]*File, error) { func (d WalkDecl) Files(virtual map[string]string) ([]*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 {
return err
}
if info.IsDir() {
her, err = here.Dir(path)
if err != nil {
return err
}
}
n := strings.TrimPrefix(path, her.Module.Dir)
pt, err := her.Parse(n)
if err != nil { if err != nil {
return err return err
} }
n := strings.TrimPrefix(path, cur.Dir)
if _, ok := virtual[n]; ok { if _, ok := virtual[n]; ok {
if info.IsDir() { if info.IsDir() {
return filepath.SkipDir return filepath.SkipDir
@ -81,16 +84,10 @@ func (d WalkDecl) Files(virtual map[string]string) ([]*File, error) {
return nil return nil
} }
pt, err := pkger.Parse(n)
if err != nil {
return err
}
pt.Pkg = cur.ImportPath
files = append(files, &File{ files = append(files, &File{
Abs: path, Abs: path,
Path: pt, Path: pt,
Here: cur, Here: her,
}) })
return nil return nil
}) })

View File

@ -1,7 +1,6 @@
package pkger package pkger
import ( import (
"log"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -16,14 +15,8 @@ var current pkging.Pkger
var gil = &sync.RWMutex{} var gil = &sync.RWMutex{}
var disk = func() pkging.Pkger { var disk = func() pkging.Pkger {
her, err := here.Current() her, _ := here.Current()
if err != nil { n, _ := stdos.New(her)
log.Println(err)
}
n, err := stdos.New(her)
if err != nil {
log.Println(err)
}
return n return n
}() }()
@ -39,7 +32,7 @@ func impl() pkging.Pkger {
type Dir string type Dir string
func (d Dir) Open(name string) (http.File, error) { func (d Dir) Open(name string) (http.File, error) {
f, err := Open(string(d)) f, err := impl().Open(string(d))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -51,16 +44,6 @@ 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()
@ -105,3 +88,8 @@ 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
}

View File

@ -2,10 +2,8 @@ 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"
) )
@ -18,31 +16,6 @@ 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)
@ -96,7 +69,7 @@ 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/internal/testdata/app", func(path string, info os.FileInfo, err error) error { err := Walk("/pkging/pkgtest/testdata/ref", func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }

View File

@ -7,8 +7,6 @@ import (
"io" "io"
"github.com/markbates/pkger/here" "github.com/markbates/pkger/here"
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa"
"github.com/markbates/pkger/internal/takeon/github.com/markbates/hepa/filters"
) )
func Decode(src []byte) ([]byte, error) { func Decode(src []byte) ([]byte, error) {
@ -46,16 +44,7 @@ func Encode(b []byte) ([]byte, error) {
return nil, err return nil, err
} }
hep := hepa.New() s := hex.EncodeToString(bb.Bytes())
hep = hepa.With(hep, filters.Home())
hep = hepa.With(hep, filters.Golang())
b, err := hep.Filter(bb.Bytes())
if err != nil {
return nil, err
}
s := hex.EncodeToString(b)
return []byte(s), nil return []byte(s), nil
} }

View File

@ -11,9 +11,6 @@ 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

View File

@ -6,18 +6,18 @@ import (
"testing" "testing"
"time" "time"
"github.com/markbates/pkger/here"
"github.com/markbates/pkger/pkging" "github.com/markbates/pkger/pkging"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func Test_NewFileInfo(t *testing.T) { func Test_NewFileInfo(t *testing.T) {
r := require.New(t) r := require.New(t)
app, err := pkgtest.App() her, err := here.Current()
r.NoError(err) r.NoError(err)
exp, err := os.Stat(filepath.Join(app.Info.Dir, "go.mod")) exp, err := os.Stat(filepath.Join(her.Dir, "go.mod"))
r.NoError(err) r.NoError(err)
act := pkging.NewFileInfo(exp) act := pkging.NewFileInfo(exp)

View File

@ -19,13 +19,17 @@ func (fx *Pkger) Add(files ...*os.File) error {
if err != nil { if err != nil {
return err return err
} }
pt, err := fx.Parse(f.Name()) pt, err := fx.Parse(f.Name())
if err != nil { if err != nil {
return err return err
} }
her, err := here.Package(pt.Pkg) dir := f.Name()
if !info.IsDir() {
dir = filepath.Dir(dir)
}
her, err := here.Dir(dir)
if err != nil { if err != nil {
return err return err
} }

View File

@ -3,31 +3,28 @@ package mem_test
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"sort"
"testing" "testing"
"github.com/markbates/pkger/here"
"github.com/markbates/pkger/pkging/mem" "github.com/markbates/pkger/pkging/mem"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func Test_Pkger_Add(t *testing.T) { func Test_Pkger_Add(t *testing.T) {
r := require.New(t) r := require.New(t)
app, err := pkgtest.App() cur, err := here.Package("github.com/markbates/pkger")
r.NoError(err) r.NoError(err)
pkg, err := mem.New(app.Info) pkg, err := mem.New(cur)
r.NoError(err) r.NoError(err)
root := app.Info.Dir
var exp []os.FileInfo 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 { err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
exp = append(exp, info)
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
@ -35,16 +32,11 @@ func Test_Pkger_Add(t *testing.T) {
} }
defer f.Close() defer f.Close()
exp = append(exp, info)
return pkg.Add(f) return pkg.Add(f)
}) })
r.NoError(err) r.NoError(err)
sort.Slice(exp, func(i, j int) bool {
return exp[i].Name() < exp[j].Name()
})
var act []os.FileInfo var act []os.FileInfo
err = pkg.Walk("/", func(path string, info os.FileInfo, err error) error { err = pkg.Walk("/", func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
@ -55,10 +47,6 @@ func Test_Pkger_Add(t *testing.T) {
}) })
r.NoError(err) r.NoError(err)
sort.Slice(act, func(i, j int) bool {
return act[i].Name() < act[j].Name()
})
r.Len(act, len(exp)) r.Len(act, len(exp))
for i, e := range exp { for i, e := range exp {

22
pkging/mem/create_test.go Normal file
View File

@ -0,0 +1,22 @@
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)
}

View File

@ -0,0 +1,22 @@
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)
}

View File

@ -31,6 +31,10 @@ type File struct {
// Seek sets the offset for the next Read or Write on file to offset, interpreted according to whence: 0 means relative to the origin of the file, 1 means relative to the current offset, and 2 means relative to the end. It returns the new offset and an error, if any. // Seek sets the offset for the next Read or Write on file to offset, interpreted according to whence: 0 means relative to the origin of the file, 1 means relative to the current offset, and 2 means relative to the end. It returns the new offset and an error, if any.
func (f *File) Seek(ofpkginget int64, whence int) (int64, error) { func (f *File) Seek(ofpkginget int64, whence int) (int64, error) {
if len(f.data) > 0 && f.reader == nil {
f.reader = bytes.NewReader(f.data)
}
if sk, ok := f.reader.(io.Seeker); ok { if sk, ok := f.reader.(io.Seeker); ok {
return sk.Seek(ofpkginget, whence) return sk.Seek(ofpkginget, whence)
} }
@ -104,11 +108,6 @@ func (f File) Name() string {
return f.path.String() return f.path.String()
} }
// 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.
func (f File) Abs() (string, error) {
return f.pkging.AbsPath(f.Path())
}
// Path returns the here.Path of the file // Path returns the here.Path of the file
func (f File) Path() here.Path { func (f File) Path() here.Path {
return f.path return f.path

View File

@ -27,6 +27,16 @@ func Test_File_Seek(t *testing.T) {
f, err = pkg.Open(":/wilco.band") f, err = pkg.Open(":/wilco.band")
r.NoError(err) r.NoError(err)
// seek to end of file before read
pos, err := f.Seek(0, 2)
r.NoError(err)
r.Equal(int64(len(data)), pos)
// reset seek
pos, err = f.Seek(0, 0)
r.NoError(err)
r.Equal(int64(0), pos)
b, err := ioutil.ReadAll(f) b, err := ioutil.ReadAll(f)
r.NoError(err) r.NoError(err)
r.Equal(data, b) r.Equal(data, b)

22
pkging/mem/http_test.go Normal file
View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_HTTP(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.HTTPTest(t, ref, pkg)
}

22
pkging/mem/info_test.go Normal file
View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_Info(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.InfoTest(t, ref, pkg)
}

View File

@ -32,20 +32,6 @@ type Pkger struct {
files *maps.Files files *maps.Files
} }
// 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 (f *Pkger) Abs(p string) (string, error) {
pt, err := f.Parse(p)
if err != nil {
return "", err
}
return f.AbsPath(pt)
}
// 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 (f *Pkger) AbsPath(pt here.Path) (string, error) {
return pt.String(), nil
}
// Current returns the here.Info representing the current Pkger implementation. // Current returns the here.Info representing the current Pkger implementation.
func (f *Pkger) Current() (here.Info, error) { func (f *Pkger) Current() (here.Info, error) {
return f.Here, nil return f.Here, nil

View File

@ -9,22 +9,7 @@ import (
) )
func Test_Pkger(t *testing.T) { func Test_Pkger(t *testing.T) {
suite, err := pkgtest.NewSuite("memos", func() (pkging.Pkger, error) { pkgtest.All(t, func(ref *pkgtest.Ref) (pkging.Pkger, error) {
app, err := pkgtest.App() return mem.New(ref.Info)
if err != nil {
return nil, err
}
pkg, err := mem.New(app.Info)
if err != nil {
return nil, err
}
return pkg, nil
}) })
if err != nil {
t.Fatal(err)
}
suite.Test(t)
} }

View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_MkdirAll(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.MkdirAllTest(t, ref, pkg)
}

22
pkging/mem/open_test.go Normal file
View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_Open(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.OpenTest(t, ref, pkg)
}

22
pkging/mem/remove_test.go Normal file
View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_Remove(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.RemoveTest(t, ref, pkg)
}

View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_RemoveAll(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.RemoveAllTest(t, ref, pkg)
}

22
pkging/mem/stat_test.go Normal file
View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_Stat(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.StatTest(t, ref, pkg)
}

22
pkging/mem/walk_test.go Normal file
View File

@ -0,0 +1,22 @@
package mem
import (
"os"
"testing"
"github.com/markbates/pkger/pkging/pkgtest"
"github.com/stretchr/testify/require"
)
func Test_Pkger_Walk(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.WalkTest(t, ref, pkg)
}

27
pkging/mod_time_test.go Normal file
View File

@ -0,0 +1,27 @@
package pkging
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func Test_ModTime(t *testing.T) {
r := require.New(t)
now := time.Now()
mt := ModTime(now)
b, err := mt.MarshalJSON()
r.NoError(err)
var mt2 ModTime
r.NoError(json.Unmarshal(b, &mt2))
at := time.Time(mt).Format(time.RFC3339)
bt := time.Time(mt2).Format(time.RFC3339)
r.Equal(at, bt)
}

View File

@ -11,12 +11,6 @@ type Pkger interface {
// Parse the string in here.Path format. // Parse the string in here.Path format.
Parse(p string) (here.Path, error) Parse(p string) (here.Path, error)
// 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.
Abs(p string) (string, error)
// 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.
AbsPath(here.Path) (string, error)
// Current returns the here.Info representing the current Pkger implementation. // Current returns the here.Info representing the current Pkger implementation.
Current() (here.Info, error) Current() (here.Info, error)
@ -30,12 +24,15 @@ type Pkger interface {
MkdirAll(p string, perm os.FileMode) error MkdirAll(p string, perm os.FileMode) error
// Open opens the named file for reading. If successful, methods on the returned file can be used for reading; the associated file descriptor has mode O_RDONLY. // Open opens the named file for reading. If successful, methods on the returned file can be used for reading; the associated file descriptor has mode O_RDONLY.
// @Parser Directive
Open(name string) (File, error) Open(name string) (File, error)
// Stat returns a FileInfo describing the named file. // Stat returns a FileInfo describing the named file.
// @Parser Directive
Stat(name string) (os.FileInfo, error) Stat(name string) (os.FileInfo, error)
// Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root. All errors that arise visiting files and directories are filtered by walkFn. The files are walked in lexical order, which makes the output deterministic but means that for very large directories Walk can be inefficient. Walk does not follow symbolic links. - That is from the standard library. I know. Their grammar teachers can not be happy with them right now. // Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root. All errors that arise visiting files and directories are filtered by walkFn. The files are walked in lexical order, which makes the output deterministic but means that for very large directories Walk can be inefficient. Walk does not follow symbolic links. - That is from the standard library. I know. Their grammar teachers can not be happy with them right now.
// @Parser Directive
Walk(p string, wf filepath.WalkFunc) error Walk(p string, wf filepath.WalkFunc) error
// Remove removes the named file or (empty) directory. // Remove removes the named file or (empty) directory.

View File

@ -1,129 +0,0 @@
package pkgtest
import (
"path/filepath"
"github.com/markbates/pkger/here"
)
type AppDetails struct {
here.Info
Paths struct {
Root []string
Parser []string
Public []string
}
}
// App returns here.info that represents the
// ./internal/testdata/app. This should be used
// by tests.
func App() (AppDetails, error) {
var app AppDetails
her, err := here.Package("github.com/markbates/pkger")
if err != nil {
return app, err
}
info := here.Info{
ImportPath: "app",
}
x := make([]string, len(rootPaths))
copy(x, rootPaths)
app.Paths.Root = x
x = make([]string, len(parserPaths))
copy(x, parserPaths)
app.Paths.Parser = x
x = make([]string, len(publicPaths))
copy(x, publicPaths)
app.Paths.Public = x
ch := filepath.Join(
her.Dir,
"pkging",
"pkgtest",
"internal",
"testdata",
"app")
info.Dir = ch
info, err = here.Cache(info.ImportPath, func(s string) (here.Info, error) {
return info, nil
})
if err != nil {
return app, err
}
app.Info = info
return app, nil
}
var rootPaths = []string{
"app:/",
"app:/go.mod",
"app:/go.sum",
"app:/main.go",
"app:/public",
"app:/public/images",
"app:/public/images/img1.png",
"app:/public/images/img2.png",
"app:/public/index.html",
"app:/templates",
"app:/templates/a.txt",
"app:/templates/b",
"app:/templates/b/b.txt",
}
var publicPaths = []string{
"app:/public",
"app:/public/images",
"app:/public/images/img1.png",
"app:/public/images/img2.png",
"app:/public/index.html",
}
var parserPaths = []string{
"app:/public",
"app:/public/images",
"app:/public/images/img1.png",
"app:/public/images/img2.png",
"app:/public/index.html",
"github.com/gobuffalo/buffalo:/render",
"github.com/gobuffalo/buffalo:/render/auto.go",
"github.com/gobuffalo/buffalo:/render/auto_test.go",
"github.com/gobuffalo/buffalo:/render/download.go",
"github.com/gobuffalo/buffalo:/render/download_test.go",
"github.com/gobuffalo/buffalo:/render/func.go",
"github.com/gobuffalo/buffalo:/render/func_test.go",
"github.com/gobuffalo/buffalo:/render/helpers.go",
"github.com/gobuffalo/buffalo:/render/html.go",
"github.com/gobuffalo/buffalo:/render/html_test.go",
"github.com/gobuffalo/buffalo:/render/js.go",
"github.com/gobuffalo/buffalo:/render/js_test.go",
"github.com/gobuffalo/buffalo:/render/json.go",
"github.com/gobuffalo/buffalo:/render/json_test.go",
"github.com/gobuffalo/buffalo:/render/markdown_test.go",
"github.com/gobuffalo/buffalo:/render/options.go",
"github.com/gobuffalo/buffalo:/render/partials_test.go",
"github.com/gobuffalo/buffalo:/render/plain.go",
"github.com/gobuffalo/buffalo:/render/plain_test.go",
"github.com/gobuffalo/buffalo:/render/render.go",
"github.com/gobuffalo/buffalo:/render/render_test.go",
"github.com/gobuffalo/buffalo:/render/renderer.go",
"github.com/gobuffalo/buffalo:/render/sse.go",
"github.com/gobuffalo/buffalo:/render/string.go",
"github.com/gobuffalo/buffalo:/render/string_map.go",
"github.com/gobuffalo/buffalo:/render/string_map_test.go",
"github.com/gobuffalo/buffalo:/render/string_test.go",
"github.com/gobuffalo/buffalo:/render/template.go",
"github.com/gobuffalo/buffalo:/render/template_engine.go",
"github.com/gobuffalo/buffalo:/render/template_helpers.go",
"github.com/gobuffalo/buffalo:/render/template_helpers_test.go",
"github.com/gobuffalo/buffalo:/render/template_test.go",
"github.com/gobuffalo/buffalo:/render/xml.go",
"github.com/gobuffalo/buffalo:/render/xml_test.go",
}

42
pkging/pkgtest/create.go Normal file
View File

@ -0,0 +1,42 @@
package pkgtest
import (
"io/ioutil"
"strings"
"testing"
"github.com/markbates/pkger/pkging"
"github.com/stretchr/testify/require"
)
func CreateTest(t *testing.T, ref *Ref, pkg pkging.Pkger) {
r := require.New(t)
const name = "/create.test"
_, err := pkg.Stat(name)
r.Error(err)
data := []byte(strings.ToUpper(name))
f, err := pkg.Create(name)
r.NoError(err)
_, err = f.Write(data)
r.NoError(err)
r.NoError(f.Close())
f, err = pkg.Open(name)
r.NoError(err)
info, err := f.Stat()
r.NoError(err)
b, err := ioutil.ReadAll(f)
r.NoError(err)
r.NoError(f.Close())
r.Equal(data, b)
r.Equal("create.test", info.Name())
}

16
pkging/pkgtest/current.go Normal file
View File

@ -0,0 +1,16 @@
package pkgtest
import (
"testing"
"github.com/markbates/pkger/pkging"
)
func CurrentTest(t *testing.T, ref *Ref, pkg pkging.Pkger) {
cur, err := pkg.Current()
if err != nil {
t.Fatal(err)
}
cmpHereInfo(t, ref.Info, cur)
}

View File

@ -1,64 +0,0 @@
package pkgtest
import (
"sort"
"testing"
"github.com/stretchr/testify/require"
)
func (s Suite) Test_File_Readdir(t *testing.T) {
r := require.New(t)
pkg, err := s.Make()
r.NoError(err)
cur, err := pkg.Current()
r.NoError(err)
ip := cur.ImportPath
table := []struct {
in string
}{
{in: ":/public"},
{in: ip + ":/public"},
}
r.NoError(s.LoadFolder(pkg))
for _, tt := range table {
s.Run(t, tt.in, func(st *testing.T) {
r := require.New(st)
dir, err := pkg.Open(tt.in)
r.NoError(err)
defer dir.Close()
infos, err := dir.Readdir(-1)
r.NoError(err)
r.Len(infos, 2)
sort.Slice(infos, func(i, j int) bool {
return infos[i].Name() < infos[j].Name()
})
r.Equal("images", infos[0].Name())
r.Equal("index.html", infos[1].Name())
dir, err = pkg.Open(tt.in + "/images")
r.NoError(err)
infos, err = dir.Readdir(-1)
r.NoError(err)
r.Len(infos, 2)
sort.Slice(infos, func(i, j int) bool {
return infos[i].Name() < infos[j].Name()
})
r.Equal("img1.png", infos[0].Name())
r.Equal("img2.png", infos[1].Name())
})
}
}

Some files were not shown because too many files have changed in this diff Show More