mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Use vendor when building (#201)
* Use vendor code for all go calls * Add missing vendor dependencies * Add travis_retry to yarn install * Fix go test call
This commit is contained in:
committed by
StashAppDev
parent
3e13103264
commit
6a75d5551f
@@ -9,14 +9,14 @@ env:
|
|||||||
- GO111MODULE=on
|
- GO111MODULE=on
|
||||||
before_install:
|
before_install:
|
||||||
- echo -e "machine github.com\n login $CI_USER_TOKEN" > ~/.netrc
|
- echo -e "machine github.com\n login $CI_USER_TOKEN" > ~/.netrc
|
||||||
- yarn --cwd ui/v2 install
|
- travis_retry yarn --cwd ui/v2 install
|
||||||
- make generate
|
- make generate
|
||||||
- CI=false yarn --cwd ui/v2 build # TODO: Fix warnings
|
- CI=false yarn --cwd ui/v2 build # TODO: Fix warnings
|
||||||
#- go get -v github.com/mgechev/revive
|
#- go get -v github.com/mgechev/revive
|
||||||
script:
|
script:
|
||||||
#- make lint
|
#- make lint
|
||||||
#- make vet
|
#- make vet
|
||||||
- go test
|
- go test -mod=vendor
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- docker pull stashappdev/compiler
|
- docker pull stashappdev/compiler
|
||||||
- sh ./scripts/cross-compile.sh
|
- sh ./scripts/cross-compile.sh
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -17,7 +17,7 @@ clean:
|
|||||||
# Regenerates GraphQL files
|
# Regenerates GraphQL files
|
||||||
.PHONY: generate
|
.PHONY: generate
|
||||||
generate:
|
generate:
|
||||||
go generate
|
go generate -mod=vendor
|
||||||
cd ui/v2 && yarn run gqlgen
|
cd ui/v2 && yarn run gqlgen
|
||||||
|
|
||||||
# Runs gofmt -w on the project's source code, modifying any files that do not match its style.
|
# Runs gofmt -w on the project's source code, modifying any files that do not match its style.
|
||||||
@@ -28,7 +28,7 @@ fmt:
|
|||||||
# Runs go vet on the project's source code.
|
# Runs go vet on the project's source code.
|
||||||
.PHONY: vet
|
.PHONY: vet
|
||||||
vet:
|
vet:
|
||||||
go vet ./...
|
go vet -mod=vendor ./...
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -5,7 +5,6 @@ require (
|
|||||||
github.com/PuerkitoBio/goquery v1.5.0
|
github.com/PuerkitoBio/goquery v1.5.0
|
||||||
github.com/bmatcuk/doublestar v1.1.5
|
github.com/bmatcuk/doublestar v1.1.5
|
||||||
github.com/disintegration/imaging v1.6.0
|
github.com/disintegration/imaging v1.6.0
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
|
||||||
github.com/go-chi/chi v4.0.2+incompatible
|
github.com/go-chi/chi v4.0.2+incompatible
|
||||||
github.com/gobuffalo/packr/v2 v2.0.2
|
github.com/gobuffalo/packr/v2 v2.0.2
|
||||||
github.com/golang-migrate/migrate/v4 v4.3.1
|
github.com/golang-migrate/migrate/v4 v4.3.1
|
||||||
|
|||||||
1
go.sum
1
go.sum
@@ -605,6 +605,7 @@ github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IA
|
|||||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||||
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||||
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
||||||
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -1,4 +1,4 @@
|
|||||||
//go:generate go run github.com/99designs/gqlgen
|
//go:generate go run -mod=vendor github.com/99designs/gqlgen
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
DATE=`go run scripts/getDate.go`
|
DATE=`go run -mod=vendor scripts/getDate.go`
|
||||||
GITHASH=`git rev-parse --short HEAD`
|
GITHASH=`git rev-parse --short HEAD`
|
||||||
VERSION_FLAGS="-X 'github.com/stashapp/stash/pkg/api.buildstamp=$DATE' -X 'github.com/stashapp/stash/pkg/api.githash=$GITHASH'"
|
VERSION_FLAGS="-X 'github.com/stashapp/stash/pkg/api.buildstamp=$DATE' -X 'github.com/stashapp/stash/pkg/api.githash=$GITHASH'"
|
||||||
|
|
||||||
|
|||||||
7
tools.go
Normal file
7
tools.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// +build tools
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/99designs/gqlgen"
|
||||||
|
)
|
||||||
3
vendor/github.com/99designs/gqlgen/.dockerignore
generated
vendored
Normal file
3
vendor/github.com/99designs/gqlgen/.dockerignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/**/node_modules
|
||||||
|
/codegen/tests/gen
|
||||||
|
/vendor
|
||||||
20
vendor/github.com/99designs/gqlgen/.editorconfig
generated
vendored
Normal file
20
vendor/github.com/99designs/gqlgen/.editorconfig
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{go,gotpl}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# These often end up with go code inside, so lets keep tabs
|
||||||
|
[*.{html,md}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = tab
|
||||||
3
vendor/github.com/99designs/gqlgen/.gitattributes
generated
vendored
Normal file
3
vendor/github.com/99designs/gqlgen/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/codegen/templates/data.go linguist-generated
|
||||||
|
/example/dataloader/*_gen.go linguist-generated
|
||||||
|
generated.go linguist-generated
|
||||||
12
vendor/github.com/99designs/gqlgen/.gitignore
generated
vendored
Normal file
12
vendor/github.com/99designs/gqlgen/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/vendor
|
||||||
|
/docs/public
|
||||||
|
/example/chat/node_modules
|
||||||
|
/integration/node_modules
|
||||||
|
/integration/schema-fetched.graphql
|
||||||
|
/example/chat/package-lock.json
|
||||||
|
/codegen/gen
|
||||||
|
/gen
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
*.test
|
||||||
|
*.out
|
||||||
3
vendor/github.com/99designs/gqlgen/.golangci.yml
generated
vendored
Normal file
3
vendor/github.com/99designs/gqlgen/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
linters-settings:
|
||||||
|
errcheck:
|
||||||
|
ignore: fmt:.*,[rR]ead|[wW]rite|[cC]lose,io:Copy
|
||||||
27
vendor/github.com/99designs/gqlgen/CONTRIBUTING.md
generated
vendored
Normal file
27
vendor/github.com/99designs/gqlgen/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Contribution Guidelines
|
||||||
|
|
||||||
|
Want to contribute to gqlgen? Here are some guidelines for how we accept help.
|
||||||
|
|
||||||
|
## Getting in Touch
|
||||||
|
|
||||||
|
Our [gitter](https://gitter.im/gqlgen/Lobby) channel is the best place to ask questions or get advice on using gqlgen.
|
||||||
|
|
||||||
|
## Reporting Bugs and Issues
|
||||||
|
|
||||||
|
We use [GitHub Issues](https://github.com/99designs/gqlgen/issues) to track bugs, so please do a search before submitting to ensure your problem isn't already tracked.
|
||||||
|
|
||||||
|
### New Issues
|
||||||
|
|
||||||
|
Please provide the expected and observed behaviours in your issue. A minimal GraphQL schema or configuration file should be provided where appropriate.
|
||||||
|
|
||||||
|
## Proposing a Change
|
||||||
|
|
||||||
|
If you intend to implement a feature for gqlgen, or make a non-trivial change to the current implementation, we recommend [first filing an issue](https://github.com/99designs/gqlgen/issues/new) marked with the `proposal` tag, so that the engineering team can provide guidance and feedback on the direction of an implementation. This also help ensure that other people aren't also working on the same thing.
|
||||||
|
|
||||||
|
Bug fixes are welcome and should come with appropriate test coverage.
|
||||||
|
|
||||||
|
New features should be made against the `next` branch.
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
By contributing to gqlgen, you agree that your contributions will be licensed under its MIT license.
|
||||||
31
vendor/github.com/99designs/gqlgen/README.md
generated
vendored
Normal file
31
vendor/github.com/99designs/gqlgen/README.md
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# gqlgen [](https://circleci.com/gh/99designs/gqlgen) [](http://gqlgen.com/)
|
||||||
|
|
||||||
|
## What is gqlgen?
|
||||||
|
|
||||||
|
[gqlgen](https://github.com/99designs/gqlgen) is a Go library for building GraphQL servers without any fuss. gqlgen is:
|
||||||
|
|
||||||
|
- **Schema first** — Define your API using the GraphQL [Schema Definition Language](http://graphql.org/learn/schema/).
|
||||||
|
- **Type safe** — You should never see `map[string]interface{}` here.
|
||||||
|
- **Codegen** — Let us generate the boring bits, so you can build your app quickly.
|
||||||
|
|
||||||
|
[Feature Comparison](https://gqlgen.com/feature-comparison/)
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First work your way through the [Getting Started](https://gqlgen.com/getting-started/) tutorial.
|
||||||
|
|
||||||
|
If you can't find what your looking for, look at our [examples](https://github.com/99designs/gqlgen/tree/master/example) for example usage of gqlgen.
|
||||||
|
|
||||||
|
## Reporting Issues
|
||||||
|
|
||||||
|
If you think you've found a bug, or something isn't behaving the way you think it should, please raise an [issue](https://github.com/99designs/gqlgen/issues) on GitHub.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Read our [Contribution Guidelines](https://github.com/99designs/gqlgen/blob/master/CONTRIBUTING.md) for information on how you can help out gqlgen.
|
||||||
|
|
||||||
|
## Other Resources
|
||||||
|
|
||||||
|
- [Christopher Biscardi @ Gophercon UK 2018](https://youtu.be/FdURVezcdcw)
|
||||||
|
- [Introducing gqlgen: a GraphQL Server Generator for Go](https://99designs.com.au/blog/engineering/gqlgen-a-graphql-server-generator-for-go/)
|
||||||
|
- [GraphQL workshop for Golang developers by Iván Corrales Solera](https://graphql-go.wesovilabs.com)
|
||||||
40
vendor/github.com/99designs/gqlgen/TESTING.md
generated
vendored
Normal file
40
vendor/github.com/99designs/gqlgen/TESTING.md
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
How to write tests for gqlgen
|
||||||
|
===
|
||||||
|
|
||||||
|
Testing generated code is a little tricky, heres how its currently set up.
|
||||||
|
|
||||||
|
### Testing responses from a server
|
||||||
|
|
||||||
|
There is a server in `codegen/testserver` that is generated as part
|
||||||
|
of `go generate ./...`, and tests written against it.
|
||||||
|
|
||||||
|
There are also a bunch of tests in against the examples, feel free to take examples from there.
|
||||||
|
|
||||||
|
|
||||||
|
### Testing the errors generated by the binary
|
||||||
|
|
||||||
|
These tests are **really** slow, because they need to run the whole codegen step. Use them very sparingly. If you can, find a way to unit test it instead.
|
||||||
|
|
||||||
|
Take a look at `codegen/input_test.go` for an example.
|
||||||
|
|
||||||
|
### Testing introspection
|
||||||
|
|
||||||
|
Introspection is tested by diffing the output of `graphql get-schema` against an expected output.
|
||||||
|
|
||||||
|
Setting up the integration environment is a little tricky:
|
||||||
|
```bash
|
||||||
|
cd integration
|
||||||
|
go generate ./...
|
||||||
|
go run ./server/server.go
|
||||||
|
```
|
||||||
|
in another terminal
|
||||||
|
```bash
|
||||||
|
cd integration
|
||||||
|
npm install
|
||||||
|
SERVER_URL=http://localhost:8080/query ./node_modules/.bin/graphql get-schema
|
||||||
|
```
|
||||||
|
|
||||||
|
will write the schema to `integration/schema-fetched.graphql`, compare that with `schema-expected.graphql`
|
||||||
|
|
||||||
|
CI will run this and fail the build if the two files dont match.
|
||||||
|
|
||||||
76
vendor/github.com/99designs/gqlgen/api/generate.go
generated
vendored
Normal file
76
vendor/github.com/99designs/gqlgen/api/generate.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen"
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/99designs/gqlgen/plugin"
|
||||||
|
"github.com/99designs/gqlgen/plugin/modelgen"
|
||||||
|
"github.com/99designs/gqlgen/plugin/resolvergen"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Generate(cfg *config.Config, option ...Option) error {
|
||||||
|
_ = syscall.Unlink(cfg.Exec.Filename)
|
||||||
|
_ = syscall.Unlink(cfg.Model.Filename)
|
||||||
|
|
||||||
|
plugins := []plugin.Plugin{
|
||||||
|
modelgen.New(),
|
||||||
|
resolvergen.New(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range option {
|
||||||
|
o(cfg, &plugins)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range plugins {
|
||||||
|
if mut, ok := p.(plugin.ConfigMutator); ok {
|
||||||
|
err := mut.MutateConfig(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, p.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Merge again now that the generated models have been injected into the typemap
|
||||||
|
data, err := codegen.BuildData(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "merging failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = codegen.GenerateCode(data); err != nil {
|
||||||
|
return errors.Wrap(err, "generating core failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range plugins {
|
||||||
|
if mut, ok := p.(plugin.CodeGenerator); ok {
|
||||||
|
err := mut.GenerateCode(data)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, p.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validate(cfg); err != nil {
|
||||||
|
return errors.Wrap(err, "validation failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validate(cfg *config.Config) error {
|
||||||
|
roots := []string{cfg.Exec.ImportPath()}
|
||||||
|
if cfg.Model.IsDefined() {
|
||||||
|
roots = append(roots, cfg.Model.ImportPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Resolver.IsDefined() {
|
||||||
|
roots = append(roots, cfg.Resolver.ImportPath())
|
||||||
|
}
|
||||||
|
_, err := packages.Load(&packages.Config{Mode: packages.LoadTypes | packages.LoadSyntax}, roots...)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "validation failed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
20
vendor/github.com/99designs/gqlgen/api/option.go
generated
vendored
Normal file
20
vendor/github.com/99designs/gqlgen/api/option.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/99designs/gqlgen/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Option func(cfg *config.Config, plugins *[]plugin.Plugin)
|
||||||
|
|
||||||
|
func NoPlugins() Option {
|
||||||
|
return func(cfg *config.Config, plugins *[]plugin.Plugin) {
|
||||||
|
*plugins = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddPlugin(p plugin.Plugin) Option {
|
||||||
|
return func(cfg *config.Config, plugins *[]plugin.Plugin) {
|
||||||
|
*plugins = append(*plugins, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
32
vendor/github.com/99designs/gqlgen/appveyor.yml
generated
vendored
Normal file
32
vendor/github.com/99designs/gqlgen/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
# Source Config
|
||||||
|
|
||||||
|
skip_branch_with_pr: true
|
||||||
|
clone_folder: c:\projects\gqlgen
|
||||||
|
|
||||||
|
# Build host
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: c:\gopath
|
||||||
|
GOVERSION: 1.11.5
|
||||||
|
PATH: '%PATH%;c:\gopath\bin'
|
||||||
|
|
||||||
|
init:
|
||||||
|
- git config --global core.autocrlf input
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Install the specific Go version.
|
||||||
|
- rmdir c:\go /s /q
|
||||||
|
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
|
||||||
|
- msiexec /i go%GOVERSION%.windows-amd64.msi /q
|
||||||
|
- go version
|
||||||
|
|
||||||
|
build: false
|
||||||
|
deploy: false
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- go generate ./...
|
||||||
|
- go test -timeout 20m ./...
|
||||||
10
vendor/github.com/99designs/gqlgen/cmd/ambient.go
generated
vendored
Normal file
10
vendor/github.com/99designs/gqlgen/cmd/ambient.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
// Import and ignore the ambient imports listed below so dependency managers
|
||||||
|
// don't prune unused code for us. Both lists should be kept in sync.
|
||||||
|
_ "github.com/99designs/gqlgen/graphql"
|
||||||
|
_ "github.com/99designs/gqlgen/graphql/introspection"
|
||||||
|
_ "github.com/vektah/gqlparser"
|
||||||
|
_ "github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
44
vendor/github.com/99designs/gqlgen/cmd/gen.go
generated
vendored
Normal file
44
vendor/github.com/99designs/gqlgen/cmd/gen.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/api"
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var genCmd = cli.Command{
|
||||||
|
Name: "generate",
|
||||||
|
Usage: "generate a graphql server based on schema",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.BoolFlag{Name: "verbose, v", Usage: "show logs"},
|
||||||
|
cli.StringFlag{Name: "config, c", Usage: "the config filename"},
|
||||||
|
},
|
||||||
|
Action: func(ctx *cli.Context) {
|
||||||
|
var cfg *config.Config
|
||||||
|
var err error
|
||||||
|
if configFilename := ctx.String("config"); configFilename != "" {
|
||||||
|
cfg, err = config.LoadConfig(configFilename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg, err = config.LoadConfigFromDefaultLocations()
|
||||||
|
if os.IsNotExist(errors.Cause(err)) {
|
||||||
|
cfg = config.DefaultConfig()
|
||||||
|
} else if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = api.Generate(cfg); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
144
vendor/github.com/99designs/gqlgen/cmd/init.go
generated
vendored
Normal file
144
vendor/github.com/99designs/gqlgen/cmd/init.go
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/api"
|
||||||
|
"github.com/99designs/gqlgen/plugin/servergen"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configComment = `
|
||||||
|
# .gqlgen.yml example
|
||||||
|
#
|
||||||
|
# Refer to https://gqlgen.com/config/
|
||||||
|
# for detailed .gqlgen.yml documentation.
|
||||||
|
`
|
||||||
|
|
||||||
|
var schemaDefault = `
|
||||||
|
# GraphQL schema example
|
||||||
|
#
|
||||||
|
# https://gqlgen.com/getting-started/
|
||||||
|
|
||||||
|
type Todo {
|
||||||
|
id: ID!
|
||||||
|
text: String!
|
||||||
|
done: Boolean!
|
||||||
|
user: User!
|
||||||
|
}
|
||||||
|
|
||||||
|
type User {
|
||||||
|
id: ID!
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
todos: [Todo!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
input NewTodo {
|
||||||
|
text: String!
|
||||||
|
userId: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
createTodo(input: NewTodo!): Todo!
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var initCmd = cli.Command{
|
||||||
|
Name: "init",
|
||||||
|
Usage: "create a new gqlgen project",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.BoolFlag{Name: "verbose, v", Usage: "show logs"},
|
||||||
|
cli.StringFlag{Name: "config, c", Usage: "the config filename"},
|
||||||
|
cli.StringFlag{Name: "server", Usage: "where to write the server stub to", Value: "server/server.go"},
|
||||||
|
cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "schema.graphql"},
|
||||||
|
},
|
||||||
|
Action: func(ctx *cli.Context) {
|
||||||
|
initSchema(ctx.String("schema"))
|
||||||
|
config := initConfig(ctx)
|
||||||
|
|
||||||
|
GenerateGraphServer(config, ctx.String("server"))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateGraphServer(cfg *config.Config, serverFilename string) {
|
||||||
|
err := api.Generate(cfg, api.AddPlugin(servergen.New(serverFilename)))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stdout, "Exec \"go run ./%s\" to start GraphQL server\n", serverFilename)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig(ctx *cli.Context) *config.Config {
|
||||||
|
var cfg *config.Config
|
||||||
|
var err error
|
||||||
|
configFilename := ctx.String("config")
|
||||||
|
if configFilename != "" {
|
||||||
|
cfg, err = config.LoadConfig(configFilename)
|
||||||
|
} else {
|
||||||
|
cfg, err = config.LoadConfigFromDefaultLocations()
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "init failed: a configuration file already exists\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !os.IsNotExist(errors.Cause(err)) {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if configFilename == "" {
|
||||||
|
configFilename = "gqlgen.yml"
|
||||||
|
}
|
||||||
|
cfg = config.DefaultConfig()
|
||||||
|
|
||||||
|
cfg.Resolver = config.PackageConfig{
|
||||||
|
Filename: "resolver.go",
|
||||||
|
Type: "Resolver",
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString(strings.TrimSpace(configComment))
|
||||||
|
buf.WriteString("\n\n")
|
||||||
|
var b []byte
|
||||||
|
b, err = yaml.Marshal(cfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "unable to marshal yaml: "+err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
buf.Write(b)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(configFilename, buf.Bytes(), 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "unable to write cfg file: "+err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func initSchema(schemaFilename string) {
|
||||||
|
_, err := os.Stat(schemaFilename)
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(schemaFilename, []byte(strings.TrimSpace(schemaDefault)), 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "unable to write schema file: "+err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
44
vendor/github.com/99designs/gqlgen/cmd/root.go
generated
vendored
Normal file
44
vendor/github.com/99designs/gqlgen/cmd/root.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/graphql"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
|
// Required since otherwise dep will prune away these unused packages before codegen has a chance to run
|
||||||
|
_ "github.com/99designs/gqlgen/handler"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Name = "gqlgen"
|
||||||
|
app.Usage = genCmd.Usage
|
||||||
|
app.Description = "This is a library for quickly creating strictly typed graphql servers in golang. See https://gqlgen.com/ for a getting started guide."
|
||||||
|
app.HideVersion = true
|
||||||
|
app.Flags = genCmd.Flags
|
||||||
|
app.Version = graphql.Version
|
||||||
|
app.Before = func(context *cli.Context) error {
|
||||||
|
if context.Bool("verbose") {
|
||||||
|
log.SetFlags(0)
|
||||||
|
} else {
|
||||||
|
log.SetOutput(ioutil.Discard)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Action = genCmd.Action
|
||||||
|
app.Commands = []cli.Command{
|
||||||
|
genCmd,
|
||||||
|
initCmd,
|
||||||
|
versionCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
fmt.Fprint(os.Stderr, err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
16
vendor/github.com/99designs/gqlgen/cmd/version.go
generated
vendored
Normal file
16
vendor/github.com/99designs/gqlgen/cmd/version.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/graphql"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var versionCmd = cli.Command{
|
||||||
|
Name: "version",
|
||||||
|
Usage: "print the version string",
|
||||||
|
Action: func(ctx *cli.Context) {
|
||||||
|
fmt.Println(graphql.Version)
|
||||||
|
},
|
||||||
|
}
|
||||||
104
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
Normal file
104
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ArgSet struct {
|
||||||
|
Args []*FieldArgument
|
||||||
|
FuncDecl string
|
||||||
|
}
|
||||||
|
|
||||||
|
type FieldArgument struct {
|
||||||
|
*ast.ArgumentDefinition
|
||||||
|
TypeReference *config.TypeReference
|
||||||
|
VarName string // The name of the var in go
|
||||||
|
Object *Object // A link back to the parent object
|
||||||
|
Default interface{} // The default value
|
||||||
|
Directives []*Directive
|
||||||
|
Value interface{} // value set in Data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FieldArgument) Stream() bool {
|
||||||
|
return f.Object != nil && f.Object.Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgument, error) {
|
||||||
|
tr, err := b.Binder.TypeReference(arg.Type, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
argDirs, err := b.getDirectives(arg.Directives)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newArg := FieldArgument{
|
||||||
|
ArgumentDefinition: arg,
|
||||||
|
TypeReference: tr,
|
||||||
|
Object: obj,
|
||||||
|
VarName: templates.ToGoPrivate(arg.Name),
|
||||||
|
Directives: argDirs,
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.DefaultValue != nil {
|
||||||
|
newArg.Default, err = arg.DefaultValue.Value(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("default value is not valid: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &newArg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) bindArgs(field *Field, params *types.Tuple) error {
|
||||||
|
var newArgs []*FieldArgument
|
||||||
|
|
||||||
|
nextArg:
|
||||||
|
for j := 0; j < params.Len(); j++ {
|
||||||
|
param := params.At(j)
|
||||||
|
for _, oldArg := range field.Args {
|
||||||
|
if strings.EqualFold(oldArg.Name, param.Name()) {
|
||||||
|
tr, err := b.Binder.TypeReference(oldArg.Type, param.Type())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldArg.TypeReference = tr
|
||||||
|
|
||||||
|
newArgs = append(newArgs, oldArg)
|
||||||
|
continue nextArg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no matching arg found, abort
|
||||||
|
return fmt.Errorf("arg %s not in schema", param.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Args = newArgs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Data) Args() map[string][]*FieldArgument {
|
||||||
|
ret := map[string][]*FieldArgument{}
|
||||||
|
for _, o := range a.Objects {
|
||||||
|
for _, f := range o.Fields {
|
||||||
|
if len(f.Args) > 0 {
|
||||||
|
ret[f.ArgsFunc()] = f.Args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d := range a.Directives {
|
||||||
|
if len(d.Args) > 0 {
|
||||||
|
ret[d.ArgsFunc()] = d.Args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
43
vendor/github.com/99designs/gqlgen/codegen/args.gotpl
generated
vendored
Normal file
43
vendor/github.com/99designs/gqlgen/codegen/args.gotpl
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{{ range $name, $args := .Args }}
|
||||||
|
func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]interface{}{}
|
||||||
|
{{- range $i, $arg := . }}
|
||||||
|
var arg{{$i}} {{ $arg.TypeReference.GO | ref}}
|
||||||
|
if tmp, ok := rawArgs[{{$arg.Name|quote}}]; ok {
|
||||||
|
{{- if $arg.Directives }}
|
||||||
|
getArg0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp) }
|
||||||
|
|
||||||
|
{{- range $i, $directive := $arg.Directives }}
|
||||||
|
getArg{{add $i 1}} := func(ctx context.Context) (res interface{}, err error) {
|
||||||
|
{{- range $dArg := $directive.Args }}
|
||||||
|
{{- if and $dArg.TypeReference.IsPtr ( notNil "Value" $dArg ) }}
|
||||||
|
{{ $dArg.VarName }} := {{ $dArg.Value | dump }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
n := getArg{{$i}}
|
||||||
|
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs "tmp" "n" }})
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
tmp, err = getArg{{$arg.Directives|len}}(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if data, ok := tmp.({{ $arg.TypeReference.GO | ref }}) ; ok {
|
||||||
|
arg{{$i}} = data
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf(`unexpected type %T from directive, should be {{ $arg.TypeReference.GO }}`, tmp)
|
||||||
|
}
|
||||||
|
{{- else }}
|
||||||
|
arg{{$i}}, err = ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
args[{{$arg.Name|quote}}] = arg{{$i}}
|
||||||
|
{{- end }}
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
11
vendor/github.com/99designs/gqlgen/codegen/complexity.go
generated
vendored
Normal file
11
vendor/github.com/99designs/gqlgen/codegen/complexity.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
func (o *Object) UniqueFields() map[string][]*Field {
|
||||||
|
m := map[string][]*Field{}
|
||||||
|
|
||||||
|
for _, f := range o.Fields {
|
||||||
|
m[f.GoFieldName] = append(m[f.GoFieldName], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
436
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
Normal file
436
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
Normal file
@@ -0,0 +1,436 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/99designs/gqlgen/internal/code"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Binder connects graphql types to golang types using static analysis
|
||||||
|
type Binder struct {
|
||||||
|
pkgs []*packages.Package
|
||||||
|
schema *ast.Schema
|
||||||
|
cfg *Config
|
||||||
|
References []*TypeReference
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) NewBinder(s *ast.Schema) (*Binder, error) {
|
||||||
|
pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadTypes | packages.LoadSyntax}, c.Models.ReferencedPackages()...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range pkgs {
|
||||||
|
for _, e := range p.Errors {
|
||||||
|
if e.Kind == packages.ListError {
|
||||||
|
return nil, p.Errors[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Binder{
|
||||||
|
pkgs: pkgs,
|
||||||
|
schema: s,
|
||||||
|
cfg: c,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) TypePosition(typ types.Type) token.Position {
|
||||||
|
named, isNamed := typ.(*types.Named)
|
||||||
|
if !isNamed {
|
||||||
|
return token.Position{
|
||||||
|
Filename: "unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.ObjectPosition(named.Obj())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) ObjectPosition(typ types.Object) token.Position {
|
||||||
|
if typ == nil {
|
||||||
|
return token.Position{
|
||||||
|
Filename: "unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkg := b.getPkg(typ.Pkg().Path())
|
||||||
|
return pkg.Fset.Position(typ.Pos())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) {
|
||||||
|
obj, err := b.FindObject(pkgName, typeName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fun, isFunc := obj.(*types.Func); isFunc {
|
||||||
|
return fun.Type().(*types.Signature).Params().At(0).Type(), nil
|
||||||
|
}
|
||||||
|
return obj.Type(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) getPkg(find string) *packages.Package {
|
||||||
|
for _, p := range b.pkgs {
|
||||||
|
if code.NormalizeVendor(find) == code.NormalizeVendor(p.PkgPath) {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var MapType = types.NewMap(types.Typ[types.String], types.NewInterfaceType(nil, nil).Complete())
|
||||||
|
var InterfaceType = types.NewInterfaceType(nil, nil)
|
||||||
|
|
||||||
|
func (b *Binder) DefaultUserObject(name string) (types.Type, error) {
|
||||||
|
models := b.cfg.Models[name].Model
|
||||||
|
if len(models) == 0 {
|
||||||
|
return nil, fmt.Errorf(name + " not found in typemap")
|
||||||
|
}
|
||||||
|
|
||||||
|
if models[0] == "map[string]interface{}" {
|
||||||
|
return MapType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if models[0] == "interface{}" {
|
||||||
|
return InterfaceType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgName, typeName := code.PkgAndType(models[0])
|
||||||
|
if pkgName == "" {
|
||||||
|
return nil, fmt.Errorf("missing package name for %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err := b.FindObject(pkgName, typeName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj.Type(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) FindObject(pkgName string, typeName string) (types.Object, error) {
|
||||||
|
if pkgName == "" {
|
||||||
|
return nil, fmt.Errorf("package cannot be nil")
|
||||||
|
}
|
||||||
|
fullName := typeName
|
||||||
|
if pkgName != "" {
|
||||||
|
fullName = pkgName + "." + typeName
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg := b.getPkg(pkgName)
|
||||||
|
if pkg == nil {
|
||||||
|
return nil, errors.Errorf("required package was not loaded: %s", fullName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// function based marshalers take precedence
|
||||||
|
for astNode, def := range pkg.TypesInfo.Defs {
|
||||||
|
// only look at defs in the top scope
|
||||||
|
if def == nil || def.Parent() == nil || def.Parent() != pkg.Types.Scope() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if astNode.Name == "Marshal"+typeName {
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then look for types directly
|
||||||
|
for astNode, def := range pkg.TypesInfo.Defs {
|
||||||
|
// only look at defs in the top scope
|
||||||
|
if def == nil || def.Parent() == nil || def.Parent() != pkg.Types.Scope() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if astNode.Name == typeName {
|
||||||
|
return def, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.Errorf("unable to find type %s\n", fullName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) PointerTo(ref *TypeReference) *TypeReference {
|
||||||
|
newRef := &TypeReference{
|
||||||
|
GO: types.NewPointer(ref.GO),
|
||||||
|
GQL: ref.GQL,
|
||||||
|
CastType: ref.CastType,
|
||||||
|
Definition: ref.Definition,
|
||||||
|
Unmarshaler: ref.Unmarshaler,
|
||||||
|
Marshaler: ref.Marshaler,
|
||||||
|
IsMarshaler: ref.IsMarshaler,
|
||||||
|
}
|
||||||
|
|
||||||
|
b.References = append(b.References, newRef)
|
||||||
|
return newRef
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeReference is used by args and field types. The Definition can refer to both input and output types.
|
||||||
|
type TypeReference struct {
|
||||||
|
Definition *ast.Definition
|
||||||
|
GQL *ast.Type
|
||||||
|
GO types.Type
|
||||||
|
CastType types.Type // Before calling marshalling functions cast from/to this base type
|
||||||
|
Marshaler *types.Func // When using external marshalling functions this will point to the Marshal function
|
||||||
|
Unmarshaler *types.Func // When using external marshalling functions this will point to the Unmarshal function
|
||||||
|
IsMarshaler bool // Does the type implement graphql.Marshaler and graphql.Unmarshaler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ref *TypeReference) Elem() *TypeReference {
|
||||||
|
if p, isPtr := ref.GO.(*types.Pointer); isPtr {
|
||||||
|
return &TypeReference{
|
||||||
|
GO: p.Elem(),
|
||||||
|
GQL: ref.GQL,
|
||||||
|
CastType: ref.CastType,
|
||||||
|
Definition: ref.Definition,
|
||||||
|
Unmarshaler: ref.Unmarshaler,
|
||||||
|
Marshaler: ref.Marshaler,
|
||||||
|
IsMarshaler: ref.IsMarshaler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ref.IsSlice() {
|
||||||
|
return &TypeReference{
|
||||||
|
GO: ref.GO.(*types.Slice).Elem(),
|
||||||
|
GQL: ref.GQL.Elem,
|
||||||
|
CastType: ref.CastType,
|
||||||
|
Definition: ref.Definition,
|
||||||
|
Unmarshaler: ref.Unmarshaler,
|
||||||
|
Marshaler: ref.Marshaler,
|
||||||
|
IsMarshaler: ref.IsMarshaler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) IsPtr() bool {
|
||||||
|
_, isPtr := t.GO.(*types.Pointer)
|
||||||
|
return isPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) IsNilable() bool {
|
||||||
|
_, isPtr := t.GO.(*types.Pointer)
|
||||||
|
_, isMap := t.GO.(*types.Map)
|
||||||
|
_, isInterface := t.GO.(*types.Interface)
|
||||||
|
return isPtr || isMap || isInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) IsSlice() bool {
|
||||||
|
_, isSlice := t.GO.(*types.Slice)
|
||||||
|
return t.GQL.Elem != nil && isSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) IsNamed() bool {
|
||||||
|
_, isSlice := t.GO.(*types.Named)
|
||||||
|
return isSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) IsStruct() bool {
|
||||||
|
_, isStruct := t.GO.Underlying().(*types.Struct)
|
||||||
|
return isStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) IsScalar() bool {
|
||||||
|
return t.Definition.Kind == ast.Scalar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) UniquenessKey() string {
|
||||||
|
var nullability = "O"
|
||||||
|
if t.GQL.NonNull {
|
||||||
|
nullability = "N"
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullability + t.Definition.Name + "2" + templates.TypeIdentifier(t.GO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) MarshalFunc() string {
|
||||||
|
if t.Definition == nil {
|
||||||
|
panic(errors.New("Definition missing for " + t.GQL.Name()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Definition.Kind == ast.InputObject {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return "marshal" + t.UniquenessKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeReference) UnmarshalFunc() string {
|
||||||
|
if t.Definition == nil {
|
||||||
|
panic(errors.New("Definition missing for " + t.GQL.Name()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !t.Definition.IsInputType() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unmarshal" + t.UniquenessKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) PushRef(ret *TypeReference) {
|
||||||
|
b.References = append(b.References, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMap(t types.Type) bool {
|
||||||
|
if t == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_, ok := t.(*types.Map)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func isIntf(t types.Type) bool {
|
||||||
|
if t == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_, ok := t.(*types.Interface)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret *TypeReference, err error) {
|
||||||
|
var pkgName, typeName string
|
||||||
|
def := b.schema.Types[schemaType.Name()]
|
||||||
|
defer func() {
|
||||||
|
if err == nil && ret != nil {
|
||||||
|
b.PushRef(ret)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if len(b.cfg.Models[schemaType.Name()].Model) == 0 {
|
||||||
|
return nil, fmt.Errorf("%s was not found", schemaType.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, model := range b.cfg.Models[schemaType.Name()].Model {
|
||||||
|
if model == "map[string]interface{}" {
|
||||||
|
if !isMap(bindTarget) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return &TypeReference{
|
||||||
|
Definition: def,
|
||||||
|
GQL: schemaType,
|
||||||
|
GO: MapType,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if model == "interface{}" {
|
||||||
|
if !isIntf(bindTarget) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return &TypeReference{
|
||||||
|
Definition: def,
|
||||||
|
GQL: schemaType,
|
||||||
|
GO: InterfaceType,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgName, typeName = code.PkgAndType(model)
|
||||||
|
if pkgName == "" {
|
||||||
|
return nil, fmt.Errorf("missing package name for %s", schemaType.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
ref := &TypeReference{
|
||||||
|
Definition: def,
|
||||||
|
GQL: schemaType,
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err := b.FindObject(pkgName, typeName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fun, isFunc := obj.(*types.Func); isFunc {
|
||||||
|
ref.GO = fun.Type().(*types.Signature).Params().At(0).Type()
|
||||||
|
ref.Marshaler = fun
|
||||||
|
ref.Unmarshaler = types.NewFunc(0, fun.Pkg(), "Unmarshal"+typeName, nil)
|
||||||
|
} else if hasMethod(obj.Type(), "MarshalGQL") && hasMethod(obj.Type(), "UnmarshalGQL") {
|
||||||
|
ref.GO = obj.Type()
|
||||||
|
ref.IsMarshaler = true
|
||||||
|
} else if underlying := basicUnderlying(obj.Type()); def.IsLeafType() && underlying != nil && underlying.Kind() == types.String {
|
||||||
|
// Special case for named types wrapping strings. Used by default enum implementations.
|
||||||
|
|
||||||
|
ref.GO = obj.Type()
|
||||||
|
ref.CastType = underlying
|
||||||
|
|
||||||
|
underlyingRef, err := b.TypeReference(&ast.Type{NamedType: "String"}, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.Marshaler = underlyingRef.Marshaler
|
||||||
|
ref.Unmarshaler = underlyingRef.Unmarshaler
|
||||||
|
} else {
|
||||||
|
ref.GO = obj.Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.GO = b.CopyModifiersFromAst(schemaType, ref.GO)
|
||||||
|
|
||||||
|
if bindTarget != nil {
|
||||||
|
if err = code.CompatibleTypes(ref.GO, bindTarget); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ref.GO = bindTarget
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("%s has type compatible with %s", schemaType.Name(), bindTarget.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Binder) CopyModifiersFromAst(t *ast.Type, base types.Type) types.Type {
|
||||||
|
if t.Elem != nil {
|
||||||
|
child := b.CopyModifiersFromAst(t.Elem, base)
|
||||||
|
if _, isStruct := child.Underlying().(*types.Struct); isStruct {
|
||||||
|
child = types.NewPointer(child)
|
||||||
|
}
|
||||||
|
return types.NewSlice(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
var isInterface bool
|
||||||
|
if named, ok := base.(*types.Named); ok {
|
||||||
|
_, isInterface = named.Underlying().(*types.Interface)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isInterface && !t.NonNull {
|
||||||
|
return types.NewPointer(base)
|
||||||
|
}
|
||||||
|
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasMethod(it types.Type, name string) bool {
|
||||||
|
if ptr, isPtr := it.(*types.Pointer); isPtr {
|
||||||
|
it = ptr.Elem()
|
||||||
|
}
|
||||||
|
namedType, ok := it.(*types.Named)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < namedType.NumMethods(); i++ {
|
||||||
|
if namedType.Method(i).Name() == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func basicUnderlying(it types.Type) *types.Basic {
|
||||||
|
if ptr, isPtr := it.(*types.Pointer); isPtr {
|
||||||
|
it = ptr.Elem()
|
||||||
|
}
|
||||||
|
namedType, ok := it.(*types.Named)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if basic, ok := namedType.Underlying().(*types.Basic); ok {
|
||||||
|
return basic
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
410
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
Normal file
410
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/internal/code"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
SchemaFilename StringList `yaml:"schema,omitempty"`
|
||||||
|
Exec PackageConfig `yaml:"exec"`
|
||||||
|
Model PackageConfig `yaml:"model"`
|
||||||
|
Resolver PackageConfig `yaml:"resolver,omitempty"`
|
||||||
|
Models TypeMap `yaml:"models,omitempty"`
|
||||||
|
StructTag string `yaml:"struct_tag,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfgFilenames = []string{".gqlgen.yml", "gqlgen.yml", "gqlgen.yaml"}
|
||||||
|
|
||||||
|
// DefaultConfig creates a copy of the default config
|
||||||
|
func DefaultConfig() *Config {
|
||||||
|
return &Config{
|
||||||
|
SchemaFilename: StringList{"schema.graphql"},
|
||||||
|
Model: PackageConfig{Filename: "models_gen.go"},
|
||||||
|
Exec: PackageConfig{Filename: "generated.go"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConfigFromDefaultLocations looks for a config file in the current directory, and all parent directories
|
||||||
|
// walking up the tree. The closest config file will be returned.
|
||||||
|
func LoadConfigFromDefaultLocations() (*Config, error) {
|
||||||
|
cfgFile, err := findCfg()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Chdir(filepath.Dir(cfgFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to enter config dir")
|
||||||
|
}
|
||||||
|
return LoadConfig(cfgFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConfig reads the gqlgen.yml config file
|
||||||
|
func LoadConfig(filename string) (*Config, error) {
|
||||||
|
config := DefaultConfig()
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to read config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := yaml.UnmarshalStrict(b, config); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to parse config")
|
||||||
|
}
|
||||||
|
|
||||||
|
preGlobbing := config.SchemaFilename
|
||||||
|
config.SchemaFilename = StringList{}
|
||||||
|
for _, f := range preGlobbing {
|
||||||
|
matches, err := filepath.Glob(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to glob schema filename %s", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range matches {
|
||||||
|
if config.SchemaFilename.Has(m) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
config.SchemaFilename = append(config.SchemaFilename, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PackageConfig struct {
|
||||||
|
Filename string `yaml:"filename,omitempty"`
|
||||||
|
Package string `yaml:"package,omitempty"`
|
||||||
|
Type string `yaml:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TypeMapEntry struct {
|
||||||
|
Model StringList `yaml:"model"`
|
||||||
|
Fields map[string]TypeMapField `yaml:"fields,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TypeMapField struct {
|
||||||
|
Resolver bool `yaml:"resolver"`
|
||||||
|
FieldName string `yaml:"fieldName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StringList []string
|
||||||
|
|
||||||
|
func (a *StringList) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var single string
|
||||||
|
err := unmarshal(&single)
|
||||||
|
if err == nil {
|
||||||
|
*a = []string{single}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var multi []string
|
||||||
|
err = unmarshal(&multi)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*a = multi
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a StringList) Has(file string) bool {
|
||||||
|
for _, existing := range a {
|
||||||
|
if existing == file {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PackageConfig) normalize() error {
|
||||||
|
if c.Filename == "" {
|
||||||
|
return errors.New("Filename is required")
|
||||||
|
}
|
||||||
|
c.Filename = abs(c.Filename)
|
||||||
|
// If Package is not set, first attempt to load the package at the output dir. If that fails
|
||||||
|
// fallback to just the base dir name of the output filename.
|
||||||
|
if c.Package == "" {
|
||||||
|
c.Package = code.NameForDir(c.Dir())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PackageConfig) ImportPath() string {
|
||||||
|
return code.ImportPathForDir(c.Dir())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PackageConfig) Dir() string {
|
||||||
|
return filepath.Dir(c.Filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PackageConfig) Check() error {
|
||||||
|
if strings.ContainsAny(c.Package, "./\\") {
|
||||||
|
return fmt.Errorf("package should be the output package name only, do not include the output filename")
|
||||||
|
}
|
||||||
|
if c.Filename != "" && !strings.HasSuffix(c.Filename, ".go") {
|
||||||
|
return fmt.Errorf("filename should be path to a go source file")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PackageConfig) Pkg() *types.Package {
|
||||||
|
return types.NewPackage(c.ImportPath(), c.Dir())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PackageConfig) IsDefined() bool {
|
||||||
|
return c.Filename != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) Check() error {
|
||||||
|
if err := c.Models.Check(); err != nil {
|
||||||
|
return errors.Wrap(err, "config.models")
|
||||||
|
}
|
||||||
|
if err := c.Exec.Check(); err != nil {
|
||||||
|
return errors.Wrap(err, "config.exec")
|
||||||
|
}
|
||||||
|
if err := c.Model.Check(); err != nil {
|
||||||
|
return errors.Wrap(err, "config.model")
|
||||||
|
}
|
||||||
|
if c.Resolver.IsDefined() {
|
||||||
|
if err := c.Resolver.Check(); err != nil {
|
||||||
|
return errors.Wrap(err, "config.resolver")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check packages names against conflict, if present in the same dir
|
||||||
|
// and check filenames for uniqueness
|
||||||
|
packageConfigList := []PackageConfig{
|
||||||
|
c.Model,
|
||||||
|
c.Exec,
|
||||||
|
c.Resolver,
|
||||||
|
}
|
||||||
|
filesMap := make(map[string]bool)
|
||||||
|
pkgConfigsByDir := make(map[string]PackageConfig)
|
||||||
|
for _, current := range packageConfigList {
|
||||||
|
_, fileFound := filesMap[current.Filename]
|
||||||
|
if fileFound {
|
||||||
|
return fmt.Errorf("filename %s defined more than once", current.Filename)
|
||||||
|
}
|
||||||
|
filesMap[current.Filename] = true
|
||||||
|
previous, inSameDir := pkgConfigsByDir[current.Dir()]
|
||||||
|
if inSameDir && current.Package != previous.Package {
|
||||||
|
return fmt.Errorf("filenames %s and %s are in the same directory but have different package definitions", stripPath(current.Filename), stripPath(previous.Filename))
|
||||||
|
}
|
||||||
|
pkgConfigsByDir[current.Dir()] = current
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stripPath(path string) string {
|
||||||
|
return filepath.Base(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TypeMap map[string]TypeMapEntry
|
||||||
|
|
||||||
|
func (tm TypeMap) Exists(typeName string) bool {
|
||||||
|
_, ok := tm[typeName]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm TypeMap) UserDefined(typeName string) bool {
|
||||||
|
m, ok := tm[typeName]
|
||||||
|
return ok && len(m.Model) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm TypeMap) Check() error {
|
||||||
|
for typeName, entry := range tm {
|
||||||
|
for _, model := range entry.Model {
|
||||||
|
if strings.LastIndex(model, ".") < strings.LastIndex(model, "/") {
|
||||||
|
return fmt.Errorf("model %s: invalid type specifier \"%s\" - you need to specify a struct to map to", typeName, entry.Model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm TypeMap) ReferencedPackages() []string {
|
||||||
|
var pkgs []string
|
||||||
|
|
||||||
|
for _, typ := range tm {
|
||||||
|
for _, model := range typ.Model {
|
||||||
|
if model == "map[string]interface{}" || model == "interface{}" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pkg, _ := code.PkgAndType(model)
|
||||||
|
if pkg == "" || inStrSlice(pkgs, pkg) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pkgs = append(pkgs, code.QualifyPackagePath(pkg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(pkgs, func(i, j int) bool {
|
||||||
|
return pkgs[i] > pkgs[j]
|
||||||
|
})
|
||||||
|
return pkgs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm TypeMap) Add(Name string, goType string) {
|
||||||
|
modelCfg := tm[Name]
|
||||||
|
modelCfg.Model = append(modelCfg.Model, goType)
|
||||||
|
tm[Name] = modelCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func inStrSlice(haystack []string, needle string) bool {
|
||||||
|
for _, v := range haystack {
|
||||||
|
if needle == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// findCfg searches for the config file in this directory and all parents up the tree
|
||||||
|
// looking for the closest match
|
||||||
|
func findCfg() (string, error) {
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "unable to get working dir to findCfg")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := findCfgInDir(dir)
|
||||||
|
|
||||||
|
for cfg == "" && dir != filepath.Dir(dir) {
|
||||||
|
dir = filepath.Dir(dir)
|
||||||
|
cfg = findCfgInDir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg == "" {
|
||||||
|
return "", os.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findCfgInDir(dir string) string {
|
||||||
|
for _, cfgName := range cfgFilenames {
|
||||||
|
path := filepath.Join(dir, cfgName)
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) normalize() error {
|
||||||
|
if err := c.Model.normalize(); err != nil {
|
||||||
|
return errors.Wrap(err, "model")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Exec.normalize(); err != nil {
|
||||||
|
return errors.Wrap(err, "exec")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Resolver.IsDefined() {
|
||||||
|
if err := c.Resolver.normalize(); err != nil {
|
||||||
|
return errors.Wrap(err, "resolver")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Models == nil {
|
||||||
|
c.Models = TypeMap{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) InjectBuiltins(s *ast.Schema) {
|
||||||
|
builtins := TypeMap{
|
||||||
|
"__Directive": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}},
|
||||||
|
"__DirectiveLocation": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||||
|
"__Type": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Type"}},
|
||||||
|
"__TypeKind": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||||
|
"__Field": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Field"}},
|
||||||
|
"__EnumValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.EnumValue"}},
|
||||||
|
"__InputValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.InputValue"}},
|
||||||
|
"__Schema": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Schema"}},
|
||||||
|
"Float": {Model: StringList{"github.com/99designs/gqlgen/graphql.Float"}},
|
||||||
|
"String": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||||
|
"Boolean": {Model: StringList{"github.com/99designs/gqlgen/graphql.Boolean"}},
|
||||||
|
"Int": {Model: StringList{
|
||||||
|
"github.com/99designs/gqlgen/graphql.Int",
|
||||||
|
"github.com/99designs/gqlgen/graphql.Int32",
|
||||||
|
"github.com/99designs/gqlgen/graphql.Int64",
|
||||||
|
}},
|
||||||
|
"ID": {
|
||||||
|
Model: StringList{
|
||||||
|
"github.com/99designs/gqlgen/graphql.ID",
|
||||||
|
"github.com/99designs/gqlgen/graphql.IntID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for typeName, entry := range builtins {
|
||||||
|
if !c.Models.Exists(typeName) {
|
||||||
|
c.Models[typeName] = entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are additional types that are injected if defined in the schema as scalars.
|
||||||
|
extraBuiltins := TypeMap{
|
||||||
|
"Time": {Model: StringList{"github.com/99designs/gqlgen/graphql.Time"}},
|
||||||
|
"Map": {Model: StringList{"github.com/99designs/gqlgen/graphql.Map"}},
|
||||||
|
"Upload": {Model: StringList{"github.com/99designs/gqlgen/graphql.Upload"}},
|
||||||
|
"Any": {Model: StringList{"github.com/99designs/gqlgen/graphql.Any"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for typeName, entry := range extraBuiltins {
|
||||||
|
if t, ok := s.Types[typeName]; !c.Models.Exists(typeName) && ok && t.Kind == ast.Scalar {
|
||||||
|
c.Models[typeName] = entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
|
||||||
|
schemaStrings := map[string]string{}
|
||||||
|
|
||||||
|
var sources []*ast.Source
|
||||||
|
|
||||||
|
for _, filename := range c.SchemaFilename {
|
||||||
|
filename = filepath.ToSlash(filename)
|
||||||
|
var err error
|
||||||
|
var schemaRaw []byte
|
||||||
|
schemaRaw, err = ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
schemaStrings[filename] = string(schemaRaw)
|
||||||
|
sources = append(sources, &ast.Source{Name: filename, Input: schemaStrings[filename]})
|
||||||
|
}
|
||||||
|
|
||||||
|
schema, err := gqlparser.LoadSchema(sources...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return schema, schemaStrings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func abs(path string) string {
|
||||||
|
absPath, err := filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return filepath.ToSlash(absPath)
|
||||||
|
}
|
||||||
168
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
Normal file
168
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement
|
||||||
|
// resolvers or directives automatically (eg grpc, validation)
|
||||||
|
type Data struct {
|
||||||
|
Config *config.Config
|
||||||
|
Schema *ast.Schema
|
||||||
|
SchemaStr map[string]string
|
||||||
|
Directives map[string]*Directive
|
||||||
|
Objects Objects
|
||||||
|
Inputs Objects
|
||||||
|
Interfaces map[string]*Interface
|
||||||
|
ReferencedTypes map[string]*config.TypeReference
|
||||||
|
ComplexityRoots map[string]*Object
|
||||||
|
|
||||||
|
QueryRoot *Object
|
||||||
|
MutationRoot *Object
|
||||||
|
SubscriptionRoot *Object
|
||||||
|
}
|
||||||
|
|
||||||
|
type builder struct {
|
||||||
|
Config *config.Config
|
||||||
|
Schema *ast.Schema
|
||||||
|
SchemaStr map[string]string
|
||||||
|
Binder *config.Binder
|
||||||
|
Directives map[string]*Directive
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildData(cfg *config.Config) (*Data, error) {
|
||||||
|
b := builder{
|
||||||
|
Config: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
b.Schema, b.SchemaStr, err = cfg.LoadSchema()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cfg.Check()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.InjectBuiltins(b.Schema)
|
||||||
|
|
||||||
|
b.Binder, err = b.Config.NewBinder(b.Schema)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Directives, err = b.buildDirectives()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dataDirectives := make(map[string]*Directive)
|
||||||
|
for name, d := range b.Directives {
|
||||||
|
if !d.Builtin {
|
||||||
|
dataDirectives[name] = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := Data{
|
||||||
|
Config: cfg,
|
||||||
|
Directives: dataDirectives,
|
||||||
|
Schema: b.Schema,
|
||||||
|
SchemaStr: b.SchemaStr,
|
||||||
|
Interfaces: map[string]*Interface{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, schemaType := range b.Schema.Types {
|
||||||
|
switch schemaType.Kind {
|
||||||
|
case ast.Object:
|
||||||
|
obj, err := b.buildObject(schemaType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to build object definition")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Objects = append(s.Objects, obj)
|
||||||
|
case ast.InputObject:
|
||||||
|
input, err := b.buildObject(schemaType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to build input definition")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Inputs = append(s.Inputs, input)
|
||||||
|
|
||||||
|
case ast.Union, ast.Interface:
|
||||||
|
s.Interfaces[schemaType.Name] = b.buildInterface(schemaType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Schema.Query != nil {
|
||||||
|
s.QueryRoot = s.Objects.ByName(s.Schema.Query.Name)
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("query entry point missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Schema.Mutation != nil {
|
||||||
|
s.MutationRoot = s.Objects.ByName(s.Schema.Mutation.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Schema.Subscription != nil {
|
||||||
|
s.SubscriptionRoot = s.Objects.ByName(s.Schema.Subscription.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := b.injectIntrospectionRoots(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.ReferencedTypes, err = b.buildTypes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(s.Objects, func(i, j int) bool {
|
||||||
|
return s.Objects[i].Definition.Name < s.Objects[j].Definition.Name
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(s.Inputs, func(i, j int) bool {
|
||||||
|
return s.Inputs[i].Definition.Name < s.Inputs[j].Definition.Name
|
||||||
|
})
|
||||||
|
|
||||||
|
return &s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) injectIntrospectionRoots(s *Data) error {
|
||||||
|
obj := s.Objects.ByName(b.Schema.Query.Name)
|
||||||
|
if obj == nil {
|
||||||
|
return fmt.Errorf("root query type must be defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
__type, err := b.buildField(obj, &ast.FieldDefinition{
|
||||||
|
Name: "__type",
|
||||||
|
Type: ast.NamedType("__Type", nil),
|
||||||
|
Arguments: []*ast.ArgumentDefinition{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: ast.NonNullNamedType("String", nil),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
__schema, err := b.buildField(obj, &ast.FieldDefinition{
|
||||||
|
Name: "__schema",
|
||||||
|
Type: ast.NamedType("__Schema", nil),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Fields = append(obj.Fields, __type, __schema)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
152
vendor/github.com/99designs/gqlgen/codegen/directive.go
generated
vendored
Normal file
152
vendor/github.com/99designs/gqlgen/codegen/directive.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Directive struct {
|
||||||
|
Name string
|
||||||
|
Args []*FieldArgument
|
||||||
|
Builtin bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) buildDirectives() (map[string]*Directive, error) {
|
||||||
|
directives := make(map[string]*Directive, len(b.Schema.Directives))
|
||||||
|
|
||||||
|
for name, dir := range b.Schema.Directives {
|
||||||
|
if _, ok := directives[name]; ok {
|
||||||
|
return nil, errors.Errorf("directive with name %s already exists", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
var builtin bool
|
||||||
|
if name == "skip" || name == "include" || name == "deprecated" {
|
||||||
|
builtin = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var args []*FieldArgument
|
||||||
|
for _, arg := range dir.Arguments {
|
||||||
|
tr, err := b.Binder.TypeReference(arg.Type, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newArg := &FieldArgument{
|
||||||
|
ArgumentDefinition: arg,
|
||||||
|
TypeReference: tr,
|
||||||
|
VarName: templates.ToGoPrivate(arg.Name),
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg.DefaultValue != nil {
|
||||||
|
var err error
|
||||||
|
newArg.Default, err = arg.DefaultValue.Value(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("default value for directive argument %s(%s) is not valid: %s", dir.Name, arg.Name, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args = append(args, newArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
directives[name] = &Directive{
|
||||||
|
Name: name,
|
||||||
|
Args: args,
|
||||||
|
Builtin: builtin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return directives, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) getDirectives(list ast.DirectiveList) ([]*Directive, error) {
|
||||||
|
dirs := make([]*Directive, len(list))
|
||||||
|
for i, d := range list {
|
||||||
|
argValues := make(map[string]interface{}, len(d.Arguments))
|
||||||
|
for _, da := range d.Arguments {
|
||||||
|
val, err := da.Value.Value(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
argValues[da.Name] = val
|
||||||
|
}
|
||||||
|
def, ok := b.Directives[d.Name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("directive %s not found", d.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
var args []*FieldArgument
|
||||||
|
for _, a := range def.Args {
|
||||||
|
value := a.Default
|
||||||
|
if argValue, ok := argValues[a.Name]; ok {
|
||||||
|
value = argValue
|
||||||
|
}
|
||||||
|
args = append(args, &FieldArgument{
|
||||||
|
ArgumentDefinition: a.ArgumentDefinition,
|
||||||
|
Value: value,
|
||||||
|
VarName: a.VarName,
|
||||||
|
TypeReference: a.TypeReference,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
dirs[i] = &Directive{
|
||||||
|
Name: d.Name,
|
||||||
|
Args: args,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) ArgsFunc() string {
|
||||||
|
if len(d.Args) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return "dir_" + d.Name + "_args"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) CallArgs() string {
|
||||||
|
args := []string{"ctx", "obj", "n"}
|
||||||
|
|
||||||
|
for _, arg := range d.Args {
|
||||||
|
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(args, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) ResolveArgs(obj string, next string) string {
|
||||||
|
args := []string{"ctx", obj, next}
|
||||||
|
|
||||||
|
for _, arg := range d.Args {
|
||||||
|
dArg := "&" + arg.VarName
|
||||||
|
if !arg.TypeReference.IsPtr() {
|
||||||
|
if arg.Value != nil {
|
||||||
|
dArg = templates.Dump(arg.Value)
|
||||||
|
} else {
|
||||||
|
dArg = templates.Dump(arg.Default)
|
||||||
|
}
|
||||||
|
} else if arg.Value == nil && arg.Default == nil {
|
||||||
|
dArg = "nil"
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, dArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(args, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Directive) Declaration() string {
|
||||||
|
res := ucFirst(d.Name) + " func(ctx context.Context, obj interface{}, next graphql.Resolver"
|
||||||
|
|
||||||
|
for _, arg := range d.Args {
|
||||||
|
res += fmt.Sprintf(", %s %s", arg.Name, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||||
|
}
|
||||||
|
|
||||||
|
res += ") (res interface{}, err error)"
|
||||||
|
return res
|
||||||
|
}
|
||||||
394
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
Normal file
394
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
*ast.FieldDefinition
|
||||||
|
|
||||||
|
TypeReference *config.TypeReference
|
||||||
|
GoFieldType GoFieldType // The field type in go, if any
|
||||||
|
GoReceiverName string // The name of method & var receiver in go, if any
|
||||||
|
GoFieldName string // The name of the method or var in go, if any
|
||||||
|
IsResolver bool // Does this field need a resolver
|
||||||
|
Args []*FieldArgument // A list of arguments to be passed to this field
|
||||||
|
MethodHasContext bool // If this is bound to a go method, does the method also take a context
|
||||||
|
NoErr bool // If this is bound to a go method, does that method have an error as the second argument
|
||||||
|
Object *Object // A link back to the parent object
|
||||||
|
Default interface{} // The default value
|
||||||
|
Directives []*Directive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, error) {
|
||||||
|
dirs, err := b.getDirectives(field.Directives)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f := Field{
|
||||||
|
FieldDefinition: field,
|
||||||
|
Object: obj,
|
||||||
|
Directives: dirs,
|
||||||
|
GoFieldName: templates.ToGo(field.Name),
|
||||||
|
GoFieldType: GoFieldVariable,
|
||||||
|
GoReceiverName: "obj",
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.DefaultValue != nil {
|
||||||
|
var err error
|
||||||
|
f.Default, err = field.DefaultValue.Value(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("default value %s is not valid: %s", field.Name, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, arg := range field.Arguments {
|
||||||
|
newArg, err := b.buildArg(obj, arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Args = append(f.Args, newArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = b.bindField(obj, &f); err != nil {
|
||||||
|
f.IsResolver = true
|
||||||
|
log.Println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.IsResolver && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() {
|
||||||
|
f.TypeReference = b.Binder.PointerTo(f.TypeReference)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) bindField(obj *Object, f *Field) error {
|
||||||
|
defer func() {
|
||||||
|
if f.TypeReference == nil {
|
||||||
|
tr, err := b.Binder.TypeReference(f.Type, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
f.TypeReference = tr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case f.Name == "__schema":
|
||||||
|
f.GoFieldType = GoFieldMethod
|
||||||
|
f.GoReceiverName = "ec"
|
||||||
|
f.GoFieldName = "introspectSchema"
|
||||||
|
return nil
|
||||||
|
case f.Name == "__type":
|
||||||
|
f.GoFieldType = GoFieldMethod
|
||||||
|
f.GoReceiverName = "ec"
|
||||||
|
f.GoFieldName = "introspectType"
|
||||||
|
return nil
|
||||||
|
case obj.Root:
|
||||||
|
f.IsResolver = true
|
||||||
|
return nil
|
||||||
|
case b.Config.Models[obj.Name].Fields[f.Name].Resolver:
|
||||||
|
f.IsResolver = true
|
||||||
|
return nil
|
||||||
|
case obj.Type == config.MapType:
|
||||||
|
f.GoFieldType = GoFieldMap
|
||||||
|
return nil
|
||||||
|
case b.Config.Models[obj.Name].Fields[f.Name].FieldName != "":
|
||||||
|
f.GoFieldName = b.Config.Models[obj.Name].Fields[f.Name].FieldName
|
||||||
|
}
|
||||||
|
|
||||||
|
target, err := b.findBindTarget(obj.Type.(*types.Named), f.GoFieldName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := b.Binder.ObjectPosition(target)
|
||||||
|
|
||||||
|
switch target := target.(type) {
|
||||||
|
case nil:
|
||||||
|
objPos := b.Binder.TypePosition(obj.Type)
|
||||||
|
return fmt.Errorf(
|
||||||
|
"%s:%d adding resolver method for %s.%s, nothing matched",
|
||||||
|
objPos.Filename,
|
||||||
|
objPos.Line,
|
||||||
|
obj.Name,
|
||||||
|
f.Name,
|
||||||
|
)
|
||||||
|
|
||||||
|
case *types.Func:
|
||||||
|
sig := target.Type().(*types.Signature)
|
||||||
|
if sig.Results().Len() == 1 {
|
||||||
|
f.NoErr = true
|
||||||
|
} else if sig.Results().Len() != 2 {
|
||||||
|
return fmt.Errorf("method has wrong number of args")
|
||||||
|
}
|
||||||
|
params := sig.Params()
|
||||||
|
// If the first argument is the context, remove it from the comparison and set
|
||||||
|
// the MethodHasContext flag so that the context will be passed to this model's method
|
||||||
|
if params.Len() > 0 && params.At(0).Type().String() == "context.Context" {
|
||||||
|
f.MethodHasContext = true
|
||||||
|
vars := make([]*types.Var, params.Len()-1)
|
||||||
|
for i := 1; i < params.Len(); i++ {
|
||||||
|
vars[i-1] = params.At(i)
|
||||||
|
}
|
||||||
|
params = types.NewTuple(vars...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = b.bindArgs(f, params); err != nil {
|
||||||
|
return errors.Wrapf(err, "%s:%d", pos.Filename, pos.Line)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := sig.Results().At(0)
|
||||||
|
tr, err := b.Binder.TypeReference(f.Type, result.Type())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// success, args and return type match. Bind to method
|
||||||
|
f.GoFieldType = GoFieldMethod
|
||||||
|
f.GoReceiverName = "obj"
|
||||||
|
f.GoFieldName = target.Name()
|
||||||
|
f.TypeReference = tr
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case *types.Var:
|
||||||
|
tr, err := b.Binder.TypeReference(f.Type, target.Type())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// success, bind to var
|
||||||
|
f.GoFieldType = GoFieldVariable
|
||||||
|
f.GoReceiverName = "obj"
|
||||||
|
f.GoFieldName = target.Name()
|
||||||
|
f.TypeReference = tr
|
||||||
|
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown bind target %T for %s", target, f.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// findField attempts to match the name to a struct field with the following
|
||||||
|
// priorites:
|
||||||
|
// 1. Any method with a matching name
|
||||||
|
// 2. Any Fields with a struct tag (see config.StructTag)
|
||||||
|
// 3. Any fields with a matching name
|
||||||
|
// 4. Same logic again for embedded fields
|
||||||
|
func (b *builder) findBindTarget(named *types.Named, name string) (types.Object, error) {
|
||||||
|
for i := 0; i < named.NumMethods(); i++ {
|
||||||
|
method := named.Method(i)
|
||||||
|
if !method.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.EqualFold(method.Name(), name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return method, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
strukt, ok := named.Underlying().(*types.Struct)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("not a struct")
|
||||||
|
}
|
||||||
|
return b.findBindStructTarget(strukt, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) findBindStructTarget(strukt *types.Struct, name string) (types.Object, error) {
|
||||||
|
// struct tags have the highest priority
|
||||||
|
if b.Config.StructTag != "" {
|
||||||
|
var foundField *types.Var
|
||||||
|
for i := 0; i < strukt.NumFields(); i++ {
|
||||||
|
field := strukt.Field(i)
|
||||||
|
if !field.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tags := reflect.StructTag(strukt.Tag(i))
|
||||||
|
if val, ok := tags.Lookup(b.Config.StructTag); ok && equalFieldName(val, name) {
|
||||||
|
if foundField != nil {
|
||||||
|
return nil, errors.Errorf("tag %s is ambigious; multiple fields have the same tag value of %s", b.Config.StructTag, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundField = field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if foundField != nil {
|
||||||
|
return foundField, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then matching field names
|
||||||
|
for i := 0; i < strukt.NumFields(); i++ {
|
||||||
|
field := strukt.Field(i)
|
||||||
|
if !field.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if equalFieldName(field.Name(), name) { // aqui!
|
||||||
|
return field, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then look in embedded structs
|
||||||
|
for i := 0; i < strukt.NumFields(); i++ {
|
||||||
|
field := strukt.Field(i)
|
||||||
|
if !field.Exported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !field.Anonymous() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldType := field.Type()
|
||||||
|
if ptr, ok := fieldType.(*types.Pointer); ok {
|
||||||
|
fieldType = ptr.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch fieldType := fieldType.(type) {
|
||||||
|
case *types.Named:
|
||||||
|
f, err := b.findBindTarget(fieldType, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f != nil {
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
f, err := b.findBindStructTarget(fieldType, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f != nil {
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown embedded field type %T", field.Type()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) HasDirectives() bool {
|
||||||
|
return len(f.Directives) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) IsReserved() bool {
|
||||||
|
return strings.HasPrefix(f.Name, "__")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) IsMethod() bool {
|
||||||
|
return f.GoFieldType == GoFieldMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) IsVariable() bool {
|
||||||
|
return f.GoFieldType == GoFieldVariable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) IsMap() bool {
|
||||||
|
return f.GoFieldType == GoFieldMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) IsConcurrent() bool {
|
||||||
|
if f.Object.DisableConcurrency {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return f.MethodHasContext || f.IsResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) GoNameUnexported() string {
|
||||||
|
return templates.ToGoPrivate(f.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) ShortInvocation() string {
|
||||||
|
return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) ArgsFunc() string {
|
||||||
|
if len(f.Args) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return "field_" + f.Object.Definition.Name + "_" + f.Name + "_args"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) ResolverType() string {
|
||||||
|
if !f.IsResolver {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) ShortResolverDeclaration() string {
|
||||||
|
res := "(ctx context.Context"
|
||||||
|
|
||||||
|
if !f.Object.Root {
|
||||||
|
res += fmt.Sprintf(", obj *%s", templates.CurrentImports.LookupType(f.Object.Type))
|
||||||
|
}
|
||||||
|
for _, arg := range f.Args {
|
||||||
|
res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||||
|
}
|
||||||
|
|
||||||
|
result := templates.CurrentImports.LookupType(f.TypeReference.GO)
|
||||||
|
if f.Object.Stream {
|
||||||
|
result = "<-chan " + result
|
||||||
|
}
|
||||||
|
|
||||||
|
res += fmt.Sprintf(") (%s, error)", result)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) ComplexitySignature() string {
|
||||||
|
res := fmt.Sprintf("func(childComplexity int")
|
||||||
|
for _, arg := range f.Args {
|
||||||
|
res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||||
|
}
|
||||||
|
res += ") int"
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) ComplexityArgs() string {
|
||||||
|
var args []string
|
||||||
|
for _, arg := range f.Args {
|
||||||
|
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(args, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) CallArgs() string {
|
||||||
|
var args []string
|
||||||
|
|
||||||
|
if f.IsResolver {
|
||||||
|
args = append(args, "rctx")
|
||||||
|
|
||||||
|
if !f.Object.Root {
|
||||||
|
args = append(args, "obj")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if f.MethodHasContext {
|
||||||
|
args = append(args, "ctx")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, arg := range f.Args {
|
||||||
|
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(args, ", ")
|
||||||
|
}
|
||||||
100
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
Normal file
100
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{{- range $object := .Objects }}{{- range $field := $object.Fields }}
|
||||||
|
|
||||||
|
{{- if $object.Stream }}
|
||||||
|
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {
|
||||||
|
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
})
|
||||||
|
{{- if $field.Args }}
|
||||||
|
rawArgs := field.ArgumentMap(ec.Variables)
|
||||||
|
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
// FIXME: subscriptions are missing request middleware stack https://github.com/99designs/gqlgen/issues/259
|
||||||
|
// and Tracer stack
|
||||||
|
rctx := ctx
|
||||||
|
results, err := ec.resolvers.{{ $field.ShortInvocation }}
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return func() graphql.Marshaler {
|
||||||
|
res, ok := <-results
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return graphql.WriterFunc(func(w io.Writer) {
|
||||||
|
w.Write([]byte{'{'})
|
||||||
|
graphql.MarshalString(field.Alias).MarshalGQL(w)
|
||||||
|
w.Write([]byte{':'})
|
||||||
|
ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res).MarshalGQL(w)
|
||||||
|
w.Write([]byte{'}'})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{ else }}
|
||||||
|
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) graphql.Marshaler {
|
||||||
|
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||||
|
defer func () { ec.Tracer.EndFieldExecution(ctx) }()
|
||||||
|
rctx := &graphql.ResolverContext{
|
||||||
|
Object: {{$object.Name|quote}},
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: {{or $field.IsMethod $field.IsResolver}},
|
||||||
|
}
|
||||||
|
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||||
|
{{- if $field.Args }}
|
||||||
|
rawArgs := field.ArgumentMap(ec.Variables)
|
||||||
|
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
rctx.Args = args
|
||||||
|
{{- end }}
|
||||||
|
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||||
|
resTmp := ec.FieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
{{- if $field.IsResolver }}
|
||||||
|
return ec.resolvers.{{ $field.ShortInvocation }}
|
||||||
|
{{- else if $field.IsMap }}
|
||||||
|
switch v := {{$field.GoReceiverName}}[{{$field.Name|quote}}].(type) {
|
||||||
|
case {{$field.TypeReference.GO | ref}}:
|
||||||
|
return v, nil
|
||||||
|
case {{$field.TypeReference.Elem.GO | ref}}:
|
||||||
|
return &v, nil
|
||||||
|
case nil:
|
||||||
|
return ({{$field.TypeReference.GO | ref}})(nil), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unexpected type %T for field %s", v, {{ $field.Name | quote}})
|
||||||
|
}
|
||||||
|
{{- else if $field.IsMethod }}
|
||||||
|
{{- if $field.NoErr }}
|
||||||
|
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil
|
||||||
|
{{- else }}
|
||||||
|
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})
|
||||||
|
{{- end }}
|
||||||
|
{{- else if $field.IsVariable }}
|
||||||
|
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil
|
||||||
|
{{- end }}
|
||||||
|
})
|
||||||
|
if resTmp == nil {
|
||||||
|
{{- if $field.TypeReference.GQL.NonNull }}
|
||||||
|
if !ec.HasError(rctx) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.({{$field.TypeReference.GO | ref}})
|
||||||
|
rctx.Result = res
|
||||||
|
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||||
|
return ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{- end }}{{- end}}
|
||||||
15
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
Normal file
15
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenerateCode(data *Data) error {
|
||||||
|
return templates.Render(templates.Options{
|
||||||
|
PackageName: data.Config.Exec.Package,
|
||||||
|
Filename: data.Config.Exec.Filename,
|
||||||
|
Data: data,
|
||||||
|
RegionTags: true,
|
||||||
|
GeneratedHeader: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
256
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
Normal file
256
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
{{ reserveImport "context" }}
|
||||||
|
{{ reserveImport "fmt" }}
|
||||||
|
{{ reserveImport "io" }}
|
||||||
|
{{ reserveImport "strconv" }}
|
||||||
|
{{ reserveImport "time" }}
|
||||||
|
{{ reserveImport "sync" }}
|
||||||
|
{{ reserveImport "sync/atomic" }}
|
||||||
|
{{ reserveImport "errors" }}
|
||||||
|
{{ reserveImport "bytes" }}
|
||||||
|
|
||||||
|
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||||
|
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||||
|
|
||||||
|
|
||||||
|
// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.
|
||||||
|
func NewExecutableSchema(cfg Config) graphql.ExecutableSchema {
|
||||||
|
return &executableSchema{
|
||||||
|
resolvers: cfg.Resolvers,
|
||||||
|
directives: cfg.Directives,
|
||||||
|
complexity: cfg.Complexity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Resolvers ResolverRoot
|
||||||
|
Directives DirectiveRoot
|
||||||
|
Complexity ComplexityRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResolverRoot interface {
|
||||||
|
{{- range $object := .Objects -}}
|
||||||
|
{{ if $object.HasResolvers -}}
|
||||||
|
{{$object.Name}}() {{$object.Name}}Resolver
|
||||||
|
{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectiveRoot struct {
|
||||||
|
{{ range $directive := .Directives }}
|
||||||
|
{{ $directive.Declaration }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ComplexityRoot struct {
|
||||||
|
{{ range $object := .Objects }}
|
||||||
|
{{ if not $object.IsReserved -}}
|
||||||
|
{{ $object.Name|go }} struct {
|
||||||
|
{{ range $_, $fields := $object.UniqueFields }}
|
||||||
|
{{- $field := index $fields 0 -}}
|
||||||
|
{{ if not $field.IsReserved -}}
|
||||||
|
{{ $field.GoFieldName }} {{ $field.ComplexitySignature }}
|
||||||
|
{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ range $object := .Objects -}}
|
||||||
|
{{ if $object.HasResolvers }}
|
||||||
|
type {{$object.Name}}Resolver interface {
|
||||||
|
{{ range $field := $object.Fields -}}
|
||||||
|
{{- if $field.IsResolver }}
|
||||||
|
{{- $field.GoFieldName}}{{ $field.ShortResolverDeclaration }}
|
||||||
|
{{- end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
type executableSchema struct {
|
||||||
|
resolvers ResolverRoot
|
||||||
|
directives DirectiveRoot
|
||||||
|
complexity ComplexityRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executableSchema) Schema() *ast.Schema {
|
||||||
|
return parsedSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {
|
||||||
|
ec := executionContext{nil, e}
|
||||||
|
_ = ec
|
||||||
|
switch typeName + "." + field {
|
||||||
|
{{ range $object := .Objects }}
|
||||||
|
{{ if not $object.IsReserved }}
|
||||||
|
{{ range $_, $fields := $object.UniqueFields }}
|
||||||
|
{{- $len := len $fields }}
|
||||||
|
{{- range $i, $field := $fields }}
|
||||||
|
{{- $last := eq (add $i 1) $len }}
|
||||||
|
{{- if not $field.IsReserved }}
|
||||||
|
{{- if eq $i 0 }}case {{ end }}"{{$object.Name}}.{{$field.Name}}"{{ if not $last }},{{ else }}:
|
||||||
|
if e.complexity.{{$object.Name|go}}.{{$field.GoFieldName}} == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
{{ if $field.Args }}
|
||||||
|
args, err := ec.{{ $field.ArgsFunc }}(context.TODO(),rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
return e.complexity.{{$object.Name|go}}.{{$field.GoFieldName}}(childComplexity{{if $field.Args}}, {{$field.ComplexityArgs}} {{ end }}), true
|
||||||
|
{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||||
|
{{- if .QueryRoot }}
|
||||||
|
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||||
|
|
||||||
|
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||||
|
data := ec._{{.QueryRoot.Name}}(ctx, op.SelectionSet)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
data.MarshalGQL(&buf)
|
||||||
|
return buf.Bytes()
|
||||||
|
})
|
||||||
|
|
||||||
|
return &graphql.Response{
|
||||||
|
Data: buf,
|
||||||
|
Errors: ec.Errors,
|
||||||
|
Extensions: ec.Extensions,
|
||||||
|
}
|
||||||
|
{{- else }}
|
||||||
|
return graphql.ErrorResponse(ctx, "queries are not supported")
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||||
|
{{- if .MutationRoot }}
|
||||||
|
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||||
|
|
||||||
|
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||||
|
data := ec._{{.MutationRoot.Name}}(ctx, op.SelectionSet)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
data.MarshalGQL(&buf)
|
||||||
|
return buf.Bytes()
|
||||||
|
})
|
||||||
|
|
||||||
|
return &graphql.Response{
|
||||||
|
Data: buf,
|
||||||
|
Errors: ec.Errors,
|
||||||
|
Extensions: ec.Extensions,
|
||||||
|
}
|
||||||
|
{{- else }}
|
||||||
|
return graphql.ErrorResponse(ctx, "mutations are not supported")
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {
|
||||||
|
{{- if .SubscriptionRoot }}
|
||||||
|
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||||
|
|
||||||
|
next := ec._{{.SubscriptionRoot.Name}}(ctx, op.SelectionSet)
|
||||||
|
if ec.Errors != nil {
|
||||||
|
return graphql.OneShot(&graphql.Response{Data: []byte("null"), Errors: ec.Errors})
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
return func() *graphql.Response {
|
||||||
|
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||||
|
buf.Reset()
|
||||||
|
data := next()
|
||||||
|
|
||||||
|
if data == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
data.MarshalGQL(&buf)
|
||||||
|
return buf.Bytes()
|
||||||
|
})
|
||||||
|
|
||||||
|
if buf == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &graphql.Response{
|
||||||
|
Data: buf,
|
||||||
|
Errors: ec.Errors,
|
||||||
|
Extensions: ec.Extensions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- else }}
|
||||||
|
return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported"))
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
type executionContext struct {
|
||||||
|
*graphql.RequestContext
|
||||||
|
*executableSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) FieldMiddleware(ctx context.Context, obj interface{}, next graphql.Resolver) (ret interface{}) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
{{- if .Directives }}
|
||||||
|
rctx := graphql.GetResolverContext(ctx)
|
||||||
|
for _, d := range rctx.Field.Definition.Directives {
|
||||||
|
switch d.Name {
|
||||||
|
{{- range $directive := .Directives }}
|
||||||
|
case "{{$directive.Name}}":
|
||||||
|
if ec.directives.{{$directive.Name|ucFirst}} != nil {
|
||||||
|
{{- if $directive.Args }}
|
||||||
|
rawArgs := d.ArgumentMap(ec.Variables)
|
||||||
|
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
n := next
|
||||||
|
next = func(ctx context.Context) (interface{}, error) {
|
||||||
|
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
res, err := ec.ResolverMiddleware(ctx, next)
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) introspectSchema() (*introspection.Schema, error) {
|
||||||
|
if ec.DisableIntrospection {
|
||||||
|
return nil, errors.New("introspection disabled")
|
||||||
|
}
|
||||||
|
return introspection.WrapSchema(parsedSchema), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) introspectType(name string) (*introspection.Type, error) {
|
||||||
|
if ec.DisableIntrospection {
|
||||||
|
return nil, errors.New("introspection disabled")
|
||||||
|
}
|
||||||
|
return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedSchema = gqlparser.MustLoadSchema(
|
||||||
|
{{- range $filename, $schema := .SchemaStr }}
|
||||||
|
&ast.Source{Name: {{$filename|quote}}, Input: {{$schema|rawQuote}}},
|
||||||
|
{{- end }}
|
||||||
|
)
|
||||||
56
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
Normal file
56
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{{- range $input := .Inputs }}
|
||||||
|
{{- if not .HasUnmarshal }}
|
||||||
|
func (ec *executionContext) unmarshalInput{{ .Name }}(ctx context.Context, v interface{}) ({{.Type | ref}}, error) {
|
||||||
|
var it {{.Type | ref}}
|
||||||
|
var asMap = v.(map[string]interface{})
|
||||||
|
{{ range $field := .Fields}}
|
||||||
|
{{- if $field.Default}}
|
||||||
|
if _, present := asMap[{{$field.Name|quote}}] ; !present {
|
||||||
|
asMap[{{$field.Name|quote}}] = {{ $field.Default | dump }}
|
||||||
|
}
|
||||||
|
{{- end}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
for k, v := range asMap {
|
||||||
|
switch k {
|
||||||
|
{{- range $field := .Fields }}
|
||||||
|
case {{$field.Name|quote}}:
|
||||||
|
var err error
|
||||||
|
{{- if $field.Directives }}
|
||||||
|
getField0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v) }
|
||||||
|
|
||||||
|
{{- range $i, $directive := $field.Directives }}
|
||||||
|
getField{{add $i 1}} := func(ctx context.Context) (res interface{}, err error) {
|
||||||
|
{{- range $dArg := $directive.Args }}
|
||||||
|
{{- if and $dArg.TypeReference.IsPtr ( notNil "Value" $dArg ) }}
|
||||||
|
{{ $dArg.VarName }} := {{ $dArg.Value | dump }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
n := getField{{$i}}
|
||||||
|
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs "it" "n" }})
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
tmp, err := getField{{$field.Directives|len}}(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
if data, ok := tmp.({{ $field.TypeReference.GO | ref }}) ; ok {
|
||||||
|
it.{{$field.GoFieldName}} = data
|
||||||
|
} else {
|
||||||
|
return it, fmt.Errorf(`unexpected type %T from directive, should be {{ $field.TypeReference.GO }}`, tmp)
|
||||||
|
}
|
||||||
|
{{- else }}
|
||||||
|
it.{{$field.GoFieldName}}, err = ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return it, nil
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
{{ end }}
|
||||||
63
vendor/github.com/99designs/gqlgen/codegen/interface.go
generated
vendored
Normal file
63
vendor/github.com/99designs/gqlgen/codegen/interface.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Interface struct {
|
||||||
|
*ast.Definition
|
||||||
|
Type types.Type
|
||||||
|
Implementors []InterfaceImplementor
|
||||||
|
InTypemap bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type InterfaceImplementor struct {
|
||||||
|
*ast.Definition
|
||||||
|
|
||||||
|
Interface *Interface
|
||||||
|
Type types.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) buildInterface(typ *ast.Definition) *Interface {
|
||||||
|
obj, err := b.Binder.DefaultUserObject(typ.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
i := &Interface{
|
||||||
|
Definition: typ,
|
||||||
|
Type: obj,
|
||||||
|
InTypemap: b.Config.Models.UserDefined(typ.Name),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, implementor := range b.Schema.GetPossibleTypes(typ) {
|
||||||
|
obj, err := b.Binder.DefaultUserObject(implementor.Name)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
i.Implementors = append(i.Implementors, InterfaceImplementor{
|
||||||
|
Definition: implementor,
|
||||||
|
Type: obj,
|
||||||
|
Interface: i,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InterfaceImplementor) ValueReceiver() bool {
|
||||||
|
interfaceType, err := findGoInterface(i.Interface.Type)
|
||||||
|
if interfaceType == nil || err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
implementorType, err := findGoNamedType(i.Type)
|
||||||
|
if implementorType == nil || err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.Implements(implementorType, interfaceType)
|
||||||
|
}
|
||||||
20
vendor/github.com/99designs/gqlgen/codegen/interface.gotpl
generated
vendored
Normal file
20
vendor/github.com/99designs/gqlgen/codegen/interface.gotpl
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{{- range $interface := .Interfaces }}
|
||||||
|
|
||||||
|
func (ec *executionContext) _{{$interface.Name}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.Type | ref}}) graphql.Marshaler {
|
||||||
|
switch obj := (*obj).(type) {
|
||||||
|
case nil:
|
||||||
|
return graphql.Null
|
||||||
|
{{- range $implementor := $interface.Implementors }}
|
||||||
|
{{- if $implementor.ValueReceiver }}
|
||||||
|
case {{$implementor.Type | ref}}:
|
||||||
|
return ec._{{$implementor.Name}}(ctx, sel, &obj)
|
||||||
|
{{- end}}
|
||||||
|
case *{{$implementor.Type | ref}}:
|
||||||
|
return ec._{{$implementor.Name}}(ctx, sel, obj)
|
||||||
|
{{- end }}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unexpected type %T", obj))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
172
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
Normal file
172
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GoFieldType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
GoFieldUndefined GoFieldType = iota
|
||||||
|
GoFieldMethod
|
||||||
|
GoFieldVariable
|
||||||
|
GoFieldMap
|
||||||
|
)
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
*ast.Definition
|
||||||
|
|
||||||
|
Type types.Type
|
||||||
|
ResolverInterface types.Type
|
||||||
|
Root bool
|
||||||
|
Fields []*Field
|
||||||
|
Implements []*ast.Definition
|
||||||
|
DisableConcurrency bool
|
||||||
|
Stream bool
|
||||||
|
Directives []*Directive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) buildObject(typ *ast.Definition) (*Object, error) {
|
||||||
|
dirs, err := b.getDirectives(typ.Directives)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, typ.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := &Object{
|
||||||
|
Definition: typ,
|
||||||
|
Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ,
|
||||||
|
DisableConcurrency: typ == b.Schema.Mutation,
|
||||||
|
Stream: typ == b.Schema.Subscription,
|
||||||
|
Directives: dirs,
|
||||||
|
ResolverInterface: types.NewNamed(
|
||||||
|
types.NewTypeName(0, b.Config.Exec.Pkg(), typ.Name+"Resolver", nil),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !obj.Root {
|
||||||
|
goObject, err := b.Binder.DefaultUserObject(typ.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
obj.Type = goObject
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, intf := range b.Schema.GetImplements(typ) {
|
||||||
|
obj.Implements = append(obj.Implements, b.Schema.Types[intf.Name])
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range typ.Fields {
|
||||||
|
if strings.HasPrefix(field.Name, "__") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var f *Field
|
||||||
|
f, err = b.buildField(obj, field)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Fields = append(obj.Fields, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) Reference() types.Type {
|
||||||
|
switch o.Type.(type) {
|
||||||
|
case *types.Pointer, *types.Slice, *types.Map:
|
||||||
|
return o.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewPointer(o.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Objects []*Object
|
||||||
|
|
||||||
|
func (o *Object) Implementors() string {
|
||||||
|
satisfiedBy := strconv.Quote(o.Name)
|
||||||
|
for _, s := range o.Implements {
|
||||||
|
satisfiedBy += ", " + strconv.Quote(s.Name)
|
||||||
|
}
|
||||||
|
return "[]string{" + satisfiedBy + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) HasResolvers() bool {
|
||||||
|
for _, f := range o.Fields {
|
||||||
|
if f.IsResolver {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) HasUnmarshal() bool {
|
||||||
|
if o.Type == config.MapType {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ {
|
||||||
|
switch o.Type.(*types.Named).Method(i).Name() {
|
||||||
|
case "UnmarshalGQL":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) HasDirectives() bool {
|
||||||
|
if len(o.Directives) > 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, f := range o.Fields {
|
||||||
|
if f.HasDirectives() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) IsConcurrent() bool {
|
||||||
|
for _, f := range o.Fields {
|
||||||
|
if f.IsConcurrent() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) IsReserved() bool {
|
||||||
|
return strings.HasPrefix(o.Definition.Name, "__")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) Description() string {
|
||||||
|
return o.Definition.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
func (os Objects) ByName(name string) *Object {
|
||||||
|
for i, o := range os {
|
||||||
|
if strings.EqualFold(o.Definition.Name, name) {
|
||||||
|
return os[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ucFirst(s string) string {
|
||||||
|
if s == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
r := []rune(s)
|
||||||
|
r[0] = unicode.ToUpper(r[0])
|
||||||
|
return string(r)
|
||||||
|
}
|
||||||
85
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
Normal file
85
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{{- range $object := .Objects }}
|
||||||
|
|
||||||
|
var {{ $object.Name|lcFirst}}Implementors = {{$object.Implementors}}
|
||||||
|
|
||||||
|
{{- if .Stream }}
|
||||||
|
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.RequestContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||||
|
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||||
|
Object: {{$object.Name|quote}},
|
||||||
|
})
|
||||||
|
if len(fields) != 1 {
|
||||||
|
ec.Errorf(ctx, "must subscribe to exactly one stream")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch fields[0].Name {
|
||||||
|
{{- range $field := $object.Fields }}
|
||||||
|
case "{{$field.Name}}":
|
||||||
|
return ec._{{$object.Name}}_{{$field.Name}}(ctx, fields[0])
|
||||||
|
{{- end }}
|
||||||
|
default:
|
||||||
|
panic("unknown field " + strconv.Quote(fields[0].Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- else }}
|
||||||
|
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet{{ if not $object.Root }},obj {{$object.Reference | ref }}{{ end }}) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.RequestContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||||
|
{{if $object.Root}}
|
||||||
|
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||||
|
Object: {{$object.Name|quote}},
|
||||||
|
})
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
out := graphql.NewFieldSet(fields)
|
||||||
|
var invalids uint32
|
||||||
|
for i, field := range fields {
|
||||||
|
switch field.Name {
|
||||||
|
case "__typename":
|
||||||
|
out.Values[i] = graphql.MarshalString({{$object.Name|quote}})
|
||||||
|
{{- range $field := $object.Fields }}
|
||||||
|
case "{{$field.Name}}":
|
||||||
|
{{- if $field.IsConcurrent }}
|
||||||
|
field := field
|
||||||
|
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
res = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||||
|
{{- if $field.TypeReference.GQL.NonNull }}
|
||||||
|
if res == graphql.Null {
|
||||||
|
{{- if $object.IsConcurrent }}
|
||||||
|
atomic.AddUint32(&invalids, 1)
|
||||||
|
{{- else }}
|
||||||
|
invalids++
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
{{- else }}
|
||||||
|
out.Values[i] = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||||
|
{{- if $field.TypeReference.GQL.NonNull }}
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
{{- if $object.IsConcurrent }}
|
||||||
|
atomic.AddUint32(&invalids, 1)
|
||||||
|
{{- else }}
|
||||||
|
invalids++
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
default:
|
||||||
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Dispatch()
|
||||||
|
if invalids > 0 { return graphql.Null }
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
137
vendor/github.com/99designs/gqlgen/codegen/templates/import.go
generated
vendored
Normal file
137
vendor/github.com/99designs/gqlgen/codegen/templates/import.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/internal/code"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Import struct {
|
||||||
|
Name string
|
||||||
|
Path string
|
||||||
|
Alias string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Imports struct {
|
||||||
|
imports []*Import
|
||||||
|
destDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Import) String() string {
|
||||||
|
if i.Alias == i.Name {
|
||||||
|
return strconv.Quote(i.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.Alias + " " + strconv.Quote(i.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Imports) String() string {
|
||||||
|
res := ""
|
||||||
|
for i, imp := range s.imports {
|
||||||
|
if i != 0 {
|
||||||
|
res += "\n"
|
||||||
|
}
|
||||||
|
res += imp.String()
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Imports) Reserve(path string, aliases ...string) (string, error) {
|
||||||
|
if path == "" {
|
||||||
|
panic("empty ambient import")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we are referencing our own package we dont need an import
|
||||||
|
if code.ImportPathForDir(s.destDir) == path {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
name := code.NameForPackage(path)
|
||||||
|
var alias string
|
||||||
|
if len(aliases) != 1 {
|
||||||
|
alias = name
|
||||||
|
} else {
|
||||||
|
alias = aliases[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing := s.findByPath(path); existing != nil {
|
||||||
|
if existing.Alias == alias {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("ambient import already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
if alias := s.findByAlias(alias); alias != nil {
|
||||||
|
return "", fmt.Errorf("ambient import collides on an alias")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.imports = append(s.imports, &Import{
|
||||||
|
Name: name,
|
||||||
|
Path: path,
|
||||||
|
Alias: alias,
|
||||||
|
})
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Imports) Lookup(path string) string {
|
||||||
|
if path == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
path = code.NormalizeVendor(path)
|
||||||
|
|
||||||
|
// if we are referencing our own package we dont need an import
|
||||||
|
if code.ImportPathForDir(s.destDir) == path {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing := s.findByPath(path); existing != nil {
|
||||||
|
return existing.Alias
|
||||||
|
}
|
||||||
|
|
||||||
|
imp := &Import{
|
||||||
|
Name: code.NameForPackage(path),
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
s.imports = append(s.imports, imp)
|
||||||
|
|
||||||
|
alias := imp.Name
|
||||||
|
i := 1
|
||||||
|
for s.findByAlias(alias) != nil {
|
||||||
|
alias = imp.Name + strconv.Itoa(i)
|
||||||
|
i++
|
||||||
|
if i > 10 {
|
||||||
|
panic(fmt.Errorf("too many collisions, last attempt was %s", alias))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imp.Alias = alias
|
||||||
|
|
||||||
|
return imp.Alias
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Imports) LookupType(t types.Type) string {
|
||||||
|
return types.TypeString(t, func(i *types.Package) string {
|
||||||
|
return s.Lookup(i.Path())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Imports) findByPath(importPath string) *Import {
|
||||||
|
for _, imp := range s.imports {
|
||||||
|
if imp.Path == importPath {
|
||||||
|
return imp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Imports) findByAlias(alias string) *Import {
|
||||||
|
for _, imp := range s.imports {
|
||||||
|
if imp.Alias == alias {
|
||||||
|
return imp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
570
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
Normal file
570
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
Normal file
@@ -0,0 +1,570 @@
|
|||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/internal/imports"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CurrentImports keeps track of all the import declarations that are needed during the execution of a plugin.
|
||||||
|
// this is done with a global because subtemplates currently get called in functions. Lets aim to remove this eventually.
|
||||||
|
var CurrentImports *Imports
|
||||||
|
|
||||||
|
// Options specify various parameters to rendering a template.
|
||||||
|
type Options struct {
|
||||||
|
// PackageName is a helper that specifies the package header declaration.
|
||||||
|
// In other words, when you write the template you don't need to specify `package X`
|
||||||
|
// at the top of the file. By providing PackageName in the Options, the Render
|
||||||
|
// function will do that for you.
|
||||||
|
PackageName string
|
||||||
|
// Template is a string of the entire template that
|
||||||
|
// will be parsed and rendered. If it's empty,
|
||||||
|
// the plugin processor will look for .gotpl files
|
||||||
|
// in the same directory of where you wrote the plugin.
|
||||||
|
Template string
|
||||||
|
// Filename is the name of the file that will be
|
||||||
|
// written to the system disk once the template is rendered.
|
||||||
|
Filename string
|
||||||
|
RegionTags bool
|
||||||
|
GeneratedHeader bool
|
||||||
|
// Data will be passed to the template execution.
|
||||||
|
Data interface{}
|
||||||
|
Funcs template.FuncMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render renders a gql plugin template from the given Options. Render is an
|
||||||
|
// abstraction of the text/template package that makes it easier to write gqlgen
|
||||||
|
// plugins. If Options.Template is empty, the Render function will look for `.gotpl`
|
||||||
|
// files inside the directory where you wrote the plugin.
|
||||||
|
func Render(cfg Options) error {
|
||||||
|
if CurrentImports != nil {
|
||||||
|
panic(fmt.Errorf("recursive or concurrent call to RenderToFile detected"))
|
||||||
|
}
|
||||||
|
CurrentImports = &Imports{destDir: filepath.Dir(cfg.Filename)}
|
||||||
|
|
||||||
|
// load path relative to calling source file
|
||||||
|
_, callerFile, _, _ := runtime.Caller(1)
|
||||||
|
rootDir := filepath.Dir(callerFile)
|
||||||
|
|
||||||
|
funcs := Funcs()
|
||||||
|
for n, f := range cfg.Funcs {
|
||||||
|
funcs[n] = f
|
||||||
|
}
|
||||||
|
t := template.New("").Funcs(funcs)
|
||||||
|
|
||||||
|
var roots []string
|
||||||
|
if cfg.Template != "" {
|
||||||
|
var err error
|
||||||
|
t, err = t.New("template.gotpl").Parse(cfg.Template)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error with provided template")
|
||||||
|
}
|
||||||
|
roots = append(roots, "template.gotpl")
|
||||||
|
} else {
|
||||||
|
// load all the templates in the directory
|
||||||
|
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
name := filepath.ToSlash(strings.TrimPrefix(path, rootDir+string(os.PathSeparator)))
|
||||||
|
if !strings.HasSuffix(info.Name(), ".gotpl") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err = t.New(name).Parse(string(b))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, cfg.Filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
roots = append(roots, name)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "locating templates")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then execute all the important looking ones in order, adding them to the same file
|
||||||
|
sort.Slice(roots, func(i, j int) bool {
|
||||||
|
// important files go first
|
||||||
|
if strings.HasSuffix(roots[i], "!.gotpl") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(roots[j], "!.gotpl") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return roots[i] < roots[j]
|
||||||
|
})
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, root := range roots {
|
||||||
|
if cfg.RegionTags {
|
||||||
|
buf.WriteString("\n// region " + center(70, "*", " "+root+" ") + "\n")
|
||||||
|
}
|
||||||
|
err := t.Lookup(root).Execute(&buf, cfg.Data)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, root)
|
||||||
|
}
|
||||||
|
if cfg.RegionTags {
|
||||||
|
buf.WriteString("\n// endregion " + center(70, "*", " "+root+" ") + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result bytes.Buffer
|
||||||
|
if cfg.GeneratedHeader {
|
||||||
|
result.WriteString("// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\n")
|
||||||
|
}
|
||||||
|
result.WriteString("package ")
|
||||||
|
result.WriteString(cfg.PackageName)
|
||||||
|
result.WriteString("\n\n")
|
||||||
|
result.WriteString("import (\n")
|
||||||
|
result.WriteString(CurrentImports.String())
|
||||||
|
result.WriteString(")\n")
|
||||||
|
_, err := buf.WriteTo(&result)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
CurrentImports = nil
|
||||||
|
|
||||||
|
return write(cfg.Filename, result.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func center(width int, pad string, s string) string {
|
||||||
|
if len(s)+2 > width {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
lpad := (width - len(s)) / 2
|
||||||
|
rpad := width - (lpad + len(s))
|
||||||
|
return strings.Repeat(pad, lpad) + s + strings.Repeat(pad, rpad)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Funcs() template.FuncMap {
|
||||||
|
return template.FuncMap{
|
||||||
|
"ucFirst": ucFirst,
|
||||||
|
"lcFirst": lcFirst,
|
||||||
|
"quote": strconv.Quote,
|
||||||
|
"rawQuote": rawQuote,
|
||||||
|
"dump": Dump,
|
||||||
|
"ref": ref,
|
||||||
|
"ts": TypeIdentifier,
|
||||||
|
"call": Call,
|
||||||
|
"prefixLines": prefixLines,
|
||||||
|
"notNil": notNil,
|
||||||
|
"reserveImport": CurrentImports.Reserve,
|
||||||
|
"lookupImport": CurrentImports.Lookup,
|
||||||
|
"go": ToGo,
|
||||||
|
"goPrivate": ToGoPrivate,
|
||||||
|
"add": func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
},
|
||||||
|
"render": func(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||||
|
return render(resolveName(filename, 0), tpldata)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ucFirst(s string) string {
|
||||||
|
if s == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
r := []rune(s)
|
||||||
|
r[0] = unicode.ToUpper(r[0])
|
||||||
|
return string(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lcFirst(s string) string {
|
||||||
|
if s == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
r := []rune(s)
|
||||||
|
r[0] = unicode.ToLower(r[0])
|
||||||
|
return string(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDelimiter(c rune) bool {
|
||||||
|
return c == '-' || c == '_' || unicode.IsSpace(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ref(p types.Type) string {
|
||||||
|
return CurrentImports.LookupType(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkgReplacer = strings.NewReplacer(
|
||||||
|
"/", "ᚋ",
|
||||||
|
".", "ᚗ",
|
||||||
|
"-", "ᚑ",
|
||||||
|
)
|
||||||
|
|
||||||
|
func TypeIdentifier(t types.Type) string {
|
||||||
|
res := ""
|
||||||
|
for {
|
||||||
|
switch it := t.(type) {
|
||||||
|
case *types.Pointer:
|
||||||
|
t.Underlying()
|
||||||
|
res += "ᚖ"
|
||||||
|
t = it.Elem()
|
||||||
|
case *types.Slice:
|
||||||
|
res += "ᚕ"
|
||||||
|
t = it.Elem()
|
||||||
|
case *types.Named:
|
||||||
|
res += pkgReplacer.Replace(it.Obj().Pkg().Path())
|
||||||
|
res += "ᚐ"
|
||||||
|
res += it.Obj().Name()
|
||||||
|
return res
|
||||||
|
case *types.Basic:
|
||||||
|
res += it.Name()
|
||||||
|
return res
|
||||||
|
case *types.Map:
|
||||||
|
res += "map"
|
||||||
|
return res
|
||||||
|
case *types.Interface:
|
||||||
|
res += "interface"
|
||||||
|
return res
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unexpected type %T", it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Call(p *types.Func) string {
|
||||||
|
pkg := CurrentImports.Lookup(p.Pkg().Path())
|
||||||
|
|
||||||
|
if pkg != "" {
|
||||||
|
pkg += "."
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Type() != nil {
|
||||||
|
// make sure the returned type is listed in our imports.
|
||||||
|
ref(p.Type().(*types.Signature).Results().At(0).Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkg + p.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToGo(name string) string {
|
||||||
|
runes := make([]rune, 0, len(name))
|
||||||
|
|
||||||
|
wordWalker(name, func(info *wordInfo) {
|
||||||
|
word := info.Word
|
||||||
|
if info.MatchCommonInitial {
|
||||||
|
word = strings.ToUpper(word)
|
||||||
|
} else if !info.HasCommonInitial {
|
||||||
|
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||||
|
// FOO or foo → Foo
|
||||||
|
// FOo → FOo
|
||||||
|
word = ucFirst(strings.ToLower(word))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runes = append(runes, []rune(word)...)
|
||||||
|
})
|
||||||
|
|
||||||
|
return string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToGoPrivate(name string) string {
|
||||||
|
runes := make([]rune, 0, len(name))
|
||||||
|
|
||||||
|
first := true
|
||||||
|
wordWalker(name, func(info *wordInfo) {
|
||||||
|
word := info.Word
|
||||||
|
if first {
|
||||||
|
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||||
|
// ID → id, CAMEL → camel
|
||||||
|
word = strings.ToLower(info.Word)
|
||||||
|
} else {
|
||||||
|
// ITicket → iTicket
|
||||||
|
word = lcFirst(info.Word)
|
||||||
|
}
|
||||||
|
first = false
|
||||||
|
} else if info.MatchCommonInitial {
|
||||||
|
word = strings.ToUpper(word)
|
||||||
|
} else if !info.HasCommonInitial {
|
||||||
|
word = ucFirst(strings.ToLower(word))
|
||||||
|
}
|
||||||
|
runes = append(runes, []rune(word)...)
|
||||||
|
})
|
||||||
|
|
||||||
|
return sanitizeKeywords(string(runes))
|
||||||
|
}
|
||||||
|
|
||||||
|
type wordInfo struct {
|
||||||
|
Word string
|
||||||
|
MatchCommonInitial bool
|
||||||
|
HasCommonInitial bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is based on the following code.
|
||||||
|
// https://github.com/golang/lint/blob/06c8688daad7faa9da5a0c2f163a3d14aac986ca/lint.go#L679
|
||||||
|
func wordWalker(str string, f func(*wordInfo)) {
|
||||||
|
runes := []rune(str)
|
||||||
|
w, i := 0, 0 // index of start of word, scan
|
||||||
|
hasCommonInitial := false
|
||||||
|
for i+1 <= len(runes) {
|
||||||
|
eow := false // whether we hit the end of a word
|
||||||
|
if i+1 == len(runes) {
|
||||||
|
eow = true
|
||||||
|
} else if isDelimiter(runes[i+1]) {
|
||||||
|
// underscore; shift the remainder forward over any run of underscores
|
||||||
|
eow = true
|
||||||
|
n := 1
|
||||||
|
for i+n+1 < len(runes) && isDelimiter(runes[i+n+1]) {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leave at most one underscore if the underscore is between two digits
|
||||||
|
if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(runes[i+1:], runes[i+n+1:])
|
||||||
|
runes = runes[:len(runes)-n]
|
||||||
|
} else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
|
||||||
|
// lower->non-lower
|
||||||
|
eow = true
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
|
||||||
|
// [w,i) is a word.
|
||||||
|
word := string(runes[w:i])
|
||||||
|
if !eow && commonInitialisms[word] && !unicode.IsLower(runes[i]) {
|
||||||
|
// through
|
||||||
|
// split IDFoo → ID, Foo
|
||||||
|
// but URLs → URLs
|
||||||
|
} else if !eow {
|
||||||
|
if commonInitialisms[word] {
|
||||||
|
hasCommonInitial = true
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
matchCommonInitial := false
|
||||||
|
if commonInitialisms[strings.ToUpper(word)] {
|
||||||
|
hasCommonInitial = true
|
||||||
|
matchCommonInitial = true
|
||||||
|
}
|
||||||
|
|
||||||
|
f(&wordInfo{
|
||||||
|
Word: word,
|
||||||
|
MatchCommonInitial: matchCommonInitial,
|
||||||
|
HasCommonInitial: hasCommonInitial,
|
||||||
|
})
|
||||||
|
hasCommonInitial = false
|
||||||
|
w = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var keywords = []string{
|
||||||
|
"break",
|
||||||
|
"default",
|
||||||
|
"func",
|
||||||
|
"interface",
|
||||||
|
"select",
|
||||||
|
"case",
|
||||||
|
"defer",
|
||||||
|
"go",
|
||||||
|
"map",
|
||||||
|
"struct",
|
||||||
|
"chan",
|
||||||
|
"else",
|
||||||
|
"goto",
|
||||||
|
"package",
|
||||||
|
"switch",
|
||||||
|
"const",
|
||||||
|
"fallthrough",
|
||||||
|
"if",
|
||||||
|
"range",
|
||||||
|
"type",
|
||||||
|
"continue",
|
||||||
|
"for",
|
||||||
|
"import",
|
||||||
|
"return",
|
||||||
|
"var",
|
||||||
|
"_",
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanitizeKeywords prevents collisions with go keywords for arguments to resolver functions
|
||||||
|
func sanitizeKeywords(name string) string {
|
||||||
|
for _, k := range keywords {
|
||||||
|
if name == k {
|
||||||
|
return name + "Arg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonInitialisms is a set of common initialisms.
|
||||||
|
// Only add entries that are highly unlikely to be non-initialisms.
|
||||||
|
// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
|
||||||
|
var commonInitialisms = map[string]bool{
|
||||||
|
"ACL": true,
|
||||||
|
"API": true,
|
||||||
|
"ASCII": true,
|
||||||
|
"CPU": true,
|
||||||
|
"CSS": true,
|
||||||
|
"DNS": true,
|
||||||
|
"EOF": true,
|
||||||
|
"GUID": true,
|
||||||
|
"HTML": true,
|
||||||
|
"HTTP": true,
|
||||||
|
"HTTPS": true,
|
||||||
|
"ID": true,
|
||||||
|
"IP": true,
|
||||||
|
"JSON": true,
|
||||||
|
"LHS": true,
|
||||||
|
"QPS": true,
|
||||||
|
"RAM": true,
|
||||||
|
"RHS": true,
|
||||||
|
"RPC": true,
|
||||||
|
"SLA": true,
|
||||||
|
"SMTP": true,
|
||||||
|
"SQL": true,
|
||||||
|
"SSH": true,
|
||||||
|
"TCP": true,
|
||||||
|
"TLS": true,
|
||||||
|
"TTL": true,
|
||||||
|
"UDP": true,
|
||||||
|
"UI": true,
|
||||||
|
"UID": true,
|
||||||
|
"UUID": true,
|
||||||
|
"URI": true,
|
||||||
|
"URL": true,
|
||||||
|
"UTF8": true,
|
||||||
|
"VM": true,
|
||||||
|
"XML": true,
|
||||||
|
"XMPP": true,
|
||||||
|
"XSRF": true,
|
||||||
|
"XSS": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawQuote(s string) string {
|
||||||
|
return "`" + strings.Replace(s, "`", "`+\"`\"+`", -1) + "`"
|
||||||
|
}
|
||||||
|
|
||||||
|
func notNil(field string, data interface{}) bool {
|
||||||
|
v := reflect.ValueOf(data)
|
||||||
|
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
if v.Kind() != reflect.Struct {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val := v.FieldByName(field)
|
||||||
|
|
||||||
|
return val.IsValid() && !val.IsNil()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Dump(val interface{}) string {
|
||||||
|
switch val := val.(type) {
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(val)
|
||||||
|
case int64:
|
||||||
|
return fmt.Sprintf("%d", val)
|
||||||
|
case float64:
|
||||||
|
return fmt.Sprintf("%f", val)
|
||||||
|
case string:
|
||||||
|
return strconv.Quote(val)
|
||||||
|
case bool:
|
||||||
|
return strconv.FormatBool(val)
|
||||||
|
case nil:
|
||||||
|
return "nil"
|
||||||
|
case []interface{}:
|
||||||
|
var parts []string
|
||||||
|
for _, part := range val {
|
||||||
|
parts = append(parts, Dump(part))
|
||||||
|
}
|
||||||
|
return "[]interface{}{" + strings.Join(parts, ",") + "}"
|
||||||
|
case map[string]interface{}:
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
buf.WriteString("map[string]interface{}{")
|
||||||
|
var keys []string
|
||||||
|
for key := range val {
|
||||||
|
keys = append(keys, key)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
data := val[key]
|
||||||
|
|
||||||
|
buf.WriteString(strconv.Quote(key))
|
||||||
|
buf.WriteString(":")
|
||||||
|
buf.WriteString(Dump(data))
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
buf.WriteString("}")
|
||||||
|
return buf.String()
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unsupported type %T", val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prefixLines(prefix, s string) string {
|
||||||
|
return prefix + strings.Replace(s, "\n", "\n"+prefix, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveName(name string, skip int) string {
|
||||||
|
if name[0] == '.' {
|
||||||
|
// load path relative to calling source file
|
||||||
|
_, callerFile, _, _ := runtime.Caller(skip + 1)
|
||||||
|
return filepath.Join(filepath.Dir(callerFile), name[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// load path relative to this directory
|
||||||
|
_, callerFile, _, _ := runtime.Caller(0)
|
||||||
|
return filepath.Join(filepath.Dir(callerFile), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func render(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||||
|
t := template.New("").Funcs(Funcs())
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err = t.New(filepath.Base(filename)).Parse(string(b))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
return buf, t.Execute(buf, tpldata)
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(filename string, b []byte) error {
|
||||||
|
err := os.MkdirAll(filepath.Dir(filename), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
formatted, err := imports.Prune(filename, b)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "gofmt failed on %s: %s\n", filepath.Base(filename), err.Error())
|
||||||
|
formatted = b
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filename, formatted, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to write %s", filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
18
vendor/github.com/99designs/gqlgen/codegen/type.go
generated
vendored
Normal file
18
vendor/github.com/99designs/gqlgen/codegen/type.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *builder) buildTypes() (map[string]*config.TypeReference, error) {
|
||||||
|
ret := map[string]*config.TypeReference{}
|
||||||
|
|
||||||
|
for _, ref := range b.Binder.References {
|
||||||
|
for ref != nil {
|
||||||
|
ret[ref.UniquenessKey()] = ref
|
||||||
|
|
||||||
|
ref = ref.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
130
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
Normal file
130
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{{- range $type := .ReferencedTypes }}
|
||||||
|
{{ with $type.UnmarshalFunc }}
|
||||||
|
func (ec *executionContext) {{ . }}(ctx context.Context, v interface{}) ({{ $type.GO | ref }}, error) {
|
||||||
|
{{- if $type.IsNilable }}
|
||||||
|
if v == nil { return nil, nil }
|
||||||
|
{{- end }}
|
||||||
|
{{- if $type.IsPtr }}
|
||||||
|
res, err := ec.{{ $type.Elem.UnmarshalFunc }}(ctx, v)
|
||||||
|
return &res, err
|
||||||
|
{{- else if $type.IsSlice }}
|
||||||
|
var vSlice []interface{}
|
||||||
|
if v != nil {
|
||||||
|
if tmp1, ok := v.([]interface{}); ok {
|
||||||
|
vSlice = tmp1
|
||||||
|
} else {
|
||||||
|
vSlice = []interface{}{ v }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
res := make([]{{$type.GO.Elem | ref}}, len(vSlice))
|
||||||
|
for i := range vSlice {
|
||||||
|
res[i], err = ec.{{ $type.Elem.UnmarshalFunc }}(ctx, vSlice[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
{{- else }}
|
||||||
|
{{- if $type.Unmarshaler }}
|
||||||
|
{{- if $type.CastType }}
|
||||||
|
tmp, err := {{ $type.Unmarshaler | call }}(v)
|
||||||
|
return {{ $type.GO | ref }}(tmp), err
|
||||||
|
{{- else}}
|
||||||
|
return {{ $type.Unmarshaler | call }}(v)
|
||||||
|
{{- end }}
|
||||||
|
{{- else if eq ($type.GO | ref) "map[string]interface{}" }}
|
||||||
|
return v.(map[string]interface{}), nil
|
||||||
|
{{- else if $type.IsMarshaler -}}
|
||||||
|
var res {{ $type.GO | ref }}
|
||||||
|
return res, res.UnmarshalGQL(v)
|
||||||
|
{{- else }}
|
||||||
|
return ec.unmarshalInput{{ $type.GQL.Name }}(ctx, v)
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ with $type.MarshalFunc }}
|
||||||
|
func (ec *executionContext) {{ . }}(ctx context.Context, sel ast.SelectionSet, v {{ $type.GO | ref }}) graphql.Marshaler {
|
||||||
|
{{- if $type.IsNilable }}
|
||||||
|
if v == nil {
|
||||||
|
{{- if $type.GQL.NonNull }}
|
||||||
|
if !ec.HasError(graphql.GetResolverContext(ctx)) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if $type.IsSlice }}
|
||||||
|
{{- if not $type.GQL.NonNull }}
|
||||||
|
if v == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
ret := make(graphql.Array, len(v))
|
||||||
|
{{- if not $type.IsScalar }}
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
isLen1 := len(v) == 1
|
||||||
|
if !isLen1 {
|
||||||
|
wg.Add(len(v))
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
for i := range v {
|
||||||
|
{{- if not $type.IsScalar }}
|
||||||
|
i := i
|
||||||
|
rctx := &graphql.ResolverContext{
|
||||||
|
Index: &i,
|
||||||
|
Result: &v[i],
|
||||||
|
}
|
||||||
|
ctx := graphql.WithResolverContext(ctx, rctx)
|
||||||
|
f := func(i int) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if !isLen1 {
|
||||||
|
defer wg.Done()
|
||||||
|
}
|
||||||
|
ret[i] = ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, v[i])
|
||||||
|
}
|
||||||
|
if isLen1 {
|
||||||
|
f(i)
|
||||||
|
} else {
|
||||||
|
go f(i)
|
||||||
|
}
|
||||||
|
{{ else }}
|
||||||
|
ret[i] = ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, v[i])
|
||||||
|
{{- end}}
|
||||||
|
}
|
||||||
|
{{ if not $type.IsScalar }} wg.Wait() {{ end }}
|
||||||
|
return ret
|
||||||
|
{{- else }}
|
||||||
|
|
||||||
|
{{- if $type.IsMarshaler }}
|
||||||
|
return v
|
||||||
|
{{- else if $type.Marshaler }}
|
||||||
|
{{- if $type.IsPtr }}
|
||||||
|
return ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, *v)
|
||||||
|
{{- else if $type.GQL.NonNull }}
|
||||||
|
res := {{ $type.Marshaler | call }}({{- if $type.CastType }}{{ $type.CastType | ref }}(v){{else}}v{{- end }})
|
||||||
|
if res == graphql.Null {
|
||||||
|
if !ec.HasError(graphql.GetResolverContext(ctx)) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
{{- else }}
|
||||||
|
return {{ $type.Marshaler | call }}({{- if $type.CastType }}{{ $type.CastType | ref }}(v){{else}}v{{- end }})
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
return ec._{{$type.Definition.Name}}(ctx, sel, {{ if not $type.IsNilable}}&{{end}} v)
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
47
vendor/github.com/99designs/gqlgen/codegen/util.go
generated
vendored
Normal file
47
vendor/github.com/99designs/gqlgen/codegen/util.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func findGoNamedType(def types.Type) (*types.Named, error) {
|
||||||
|
if def == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
namedType, ok := def.(*types.Named)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("expected %s to be a named type, instead found %T\n", def.String(), def)
|
||||||
|
}
|
||||||
|
|
||||||
|
return namedType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findGoInterface(def types.Type) (*types.Interface, error) {
|
||||||
|
if def == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
namedType, err := findGoNamedType(def)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if namedType == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
underlying, ok := namedType.Underlying().(*types.Interface)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("expected %s to be a named interface, instead found %s", def.String(), namedType.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return underlying, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func equalFieldName(source, target string) bool {
|
||||||
|
source = strings.Replace(source, "_", "", -1)
|
||||||
|
target = strings.Replace(target, "_", "", -1)
|
||||||
|
return strings.EqualFold(source, target)
|
||||||
|
}
|
||||||
28
vendor/github.com/99designs/gqlgen/go.mod
generated
vendored
Normal file
28
vendor/github.com/99designs/gqlgen/go.mod
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
module github.com/99designs/gqlgen
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/go-chi/chi v3.3.2+incompatible
|
||||||
|
github.com/gogo/protobuf v1.0.0 // indirect
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect
|
||||||
|
github.com/gorilla/mux v1.6.1 // indirect
|
||||||
|
github.com/gorilla/websocket v1.2.0
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0
|
||||||
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047
|
||||||
|
github.com/opentracing/basictracer-go v1.0.0 // indirect
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
|
github.com/rs/cors v1.6.0
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 // indirect
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0 // indirect
|
||||||
|
github.com/stretchr/testify v1.3.0
|
||||||
|
github.com/urfave/cli v1.20.0
|
||||||
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e
|
||||||
|
github.com/vektah/gqlparser v1.1.2
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755
|
||||||
|
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 // indirect
|
||||||
|
)
|
||||||
81
vendor/github.com/99designs/gqlgen/go.sum
generated
vendored
Normal file
81
vendor/github.com/99designs/gqlgen/go.sum
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
|
||||||
|
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||||
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||||
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
|
||||||
|
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
|
github.com/gogo/protobuf v1.0.0 h1:2jyBKDKU/8v3v2xVR2PtiWQviFUyiaGk2rpfyFT8rTM=
|
||||||
|
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkHBdPZU4jo9bSmrLpII768arSyMFgk=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.1 h1:KOwqsTYZdeuMacU7CxjMNYEKeBvLbxW+psodrbcEa3A=
|
||||||
|
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||||
|
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
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/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
|
||||||
|
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||||
|
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
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/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
|
||||||
|
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0 h1:JJV9CsgM9EC9w2iVkwuz+sMx8yRFe89PJRUrv6hPCIA=
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
|
||||||
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/vektah/dataloaden v0.2.0 h1:lhynDrG7c8mNLahboCo0Wq82tMjmu5yOUv2ds/tBmss=
|
||||||
|
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||||
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||||
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||||
|
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||||
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6 h1:mge3qS/eMvcfyIAzTMOAy0XUzWG6Lk0N4M8zjuSmdco=
|
||||||
|
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY=
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190125232054-dbeab5af4b8d3204d444b78cafaba18a9a062a50/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190511041617-99f201b6807e h1:wTxRxdzKt8fn3IQa3+kVlPJMxK2hJj2Orm+M2Mzw9eg=
|
||||||
|
golang.org/x/tools v0.0.0-20190511041617-99f201b6807e/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
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 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755 h1:d2maSb13hr/ArmfK3rW+wNUKKfytCol7W1/vDHxMPiE=
|
||||||
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
|
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 h1:e1sMhtVq9AfcEy8AXNb8eSg6gbzfdpYhoNqnPJa+GzI=
|
||||||
|
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||||
163
vendor/github.com/99designs/gqlgen/internal/code/compare.go
generated
vendored
Normal file
163
vendor/github.com/99designs/gqlgen/internal/code/compare.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
package code
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompatibleTypes isnt a strict comparison, it allows for pointer differences
|
||||||
|
func CompatibleTypes(expected types.Type, actual types.Type) error {
|
||||||
|
//fmt.Println("Comparing ", expected.String(), actual.String())
|
||||||
|
|
||||||
|
// Special case to deal with pointer mismatches
|
||||||
|
{
|
||||||
|
expectedPtr, expectedIsPtr := expected.(*types.Pointer)
|
||||||
|
actualPtr, actualIsPtr := actual.(*types.Pointer)
|
||||||
|
|
||||||
|
if expectedIsPtr && actualIsPtr {
|
||||||
|
return CompatibleTypes(expectedPtr.Elem(), actualPtr.Elem())
|
||||||
|
}
|
||||||
|
if expectedIsPtr && !actualIsPtr {
|
||||||
|
return CompatibleTypes(expectedPtr.Elem(), actual)
|
||||||
|
}
|
||||||
|
if !expectedIsPtr && actualIsPtr {
|
||||||
|
return CompatibleTypes(expected, actualPtr.Elem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch expected := expected.(type) {
|
||||||
|
case *types.Slice:
|
||||||
|
if actual, ok := actual.(*types.Slice); ok {
|
||||||
|
return CompatibleTypes(expected.Elem(), actual.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
if actual, ok := actual.(*types.Array); ok {
|
||||||
|
if expected.Len() != actual.Len() {
|
||||||
|
return fmt.Errorf("array length differs")
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompatibleTypes(expected.Elem(), actual.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Basic:
|
||||||
|
if actual, ok := actual.(*types.Basic); ok {
|
||||||
|
if actual.Kind() != expected.Kind() {
|
||||||
|
return fmt.Errorf("basic kind differs, %s != %s", expected.Name(), actual.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
if actual, ok := actual.(*types.Struct); ok {
|
||||||
|
if expected.NumFields() != actual.NumFields() {
|
||||||
|
return fmt.Errorf("number of struct fields differ")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < expected.NumFields(); i++ {
|
||||||
|
if expected.Field(i).Name() != actual.Field(i).Name() {
|
||||||
|
return fmt.Errorf("struct field %d name differs, %s != %s", i, expected.Field(i).Name(), actual.Field(i).Name())
|
||||||
|
}
|
||||||
|
if err := CompatibleTypes(expected.Field(i).Type(), actual.Field(i).Type()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
if actual, ok := actual.(*types.Tuple); ok {
|
||||||
|
if expected.Len() != actual.Len() {
|
||||||
|
return fmt.Errorf("tuple length differs, %d != %d", expected.Len(), actual.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < expected.Len(); i++ {
|
||||||
|
if err := CompatibleTypes(expected.At(i).Type(), actual.At(i).Type()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
if actual, ok := actual.(*types.Signature); ok {
|
||||||
|
if err := CompatibleTypes(expected.Params(), actual.Params()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := CompatibleTypes(expected.Results(), actual.Results()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case *types.Interface:
|
||||||
|
if actual, ok := actual.(*types.Interface); ok {
|
||||||
|
if expected.NumMethods() != actual.NumMethods() {
|
||||||
|
return fmt.Errorf("interface method count differs, %d != %d", expected.NumMethods(), actual.NumMethods())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < expected.NumMethods(); i++ {
|
||||||
|
if expected.Method(i).Name() != actual.Method(i).Name() {
|
||||||
|
return fmt.Errorf("interface method %d name differs, %s != %s", i, expected.Method(i).Name(), actual.Method(i).Name())
|
||||||
|
}
|
||||||
|
if err := CompatibleTypes(expected.Method(i).Type(), actual.Method(i).Type()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
if actual, ok := actual.(*types.Map); ok {
|
||||||
|
if err := CompatibleTypes(expected.Key(), actual.Key()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := CompatibleTypes(expected.Elem(), actual.Elem()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
if actual, ok := actual.(*types.Chan); ok {
|
||||||
|
return CompatibleTypes(expected.Elem(), actual.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
if actual, ok := actual.(*types.Named); ok {
|
||||||
|
if NormalizeVendor(expected.Obj().Pkg().Path()) != NormalizeVendor(actual.Obj().Pkg().Path()) {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"package name of named type differs, %s != %s",
|
||||||
|
NormalizeVendor(expected.Obj().Pkg().Path()),
|
||||||
|
NormalizeVendor(actual.Obj().Pkg().Path()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected.Obj().Name() != actual.Obj().Name() {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"named type name differs, %s != %s",
|
||||||
|
NormalizeVendor(expected.Obj().Name()),
|
||||||
|
NormalizeVendor(actual.Obj().Name()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before models are generated all missing references will be Invalid Basic references.
|
||||||
|
// lets assume these are valid too.
|
||||||
|
if actual, ok := actual.(*types.Basic); ok && actual.Kind() == types.Invalid {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("missing support for %T", expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("type mismatch %T != %T", expected, actual)
|
||||||
|
}
|
||||||
114
vendor/github.com/99designs/gqlgen/internal/code/imports.go
generated
vendored
Normal file
114
vendor/github.com/99designs/gqlgen/internal/code/imports.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package code
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"go/build"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
|
)
|
||||||
|
|
||||||
|
var nameForPackageCache = sync.Map{}
|
||||||
|
|
||||||
|
var gopaths []string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
gopaths = filepath.SplitList(build.Default.GOPATH)
|
||||||
|
for i, p := range gopaths {
|
||||||
|
gopaths[i] = filepath.ToSlash(filepath.Join(p, "src"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameForDir manually looks for package stanzas in files located in the given directory. This can be
|
||||||
|
// much faster than having to consult go list, because we already know exactly where to look.
|
||||||
|
func NameForDir(dir string) string {
|
||||||
|
dir, err := filepath.Abs(dir)
|
||||||
|
if err != nil {
|
||||||
|
return SanitizePackageName(filepath.Base(dir))
|
||||||
|
}
|
||||||
|
files, err := ioutil.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return SanitizePackageName(filepath.Base(dir))
|
||||||
|
}
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
for _, file := range files {
|
||||||
|
if !strings.HasSuffix(strings.ToLower(file.Name()), ".go") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := filepath.Join(dir, file.Name())
|
||||||
|
if src, err := parser.ParseFile(fset, filename, nil, parser.PackageClauseOnly); err == nil {
|
||||||
|
return src.Name.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SanitizePackageName(filepath.Base(dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportPathForDir takes a path and returns a golang import path for the package
|
||||||
|
func ImportPathForDir(dir string) (res string) {
|
||||||
|
dir, err := filepath.Abs(dir)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dir = filepath.ToSlash(dir)
|
||||||
|
|
||||||
|
modDir := dir
|
||||||
|
assumedPart := ""
|
||||||
|
for {
|
||||||
|
f, err := ioutil.ReadFile(filepath.Join(modDir, "/", "go.mod"))
|
||||||
|
if err == nil {
|
||||||
|
// found it, stop searching
|
||||||
|
return string(modregex.FindSubmatch(f)[1]) + assumedPart
|
||||||
|
}
|
||||||
|
|
||||||
|
assumedPart = "/" + filepath.Base(modDir) + assumedPart
|
||||||
|
modDir, err = filepath.Abs(filepath.Join(modDir, ".."))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walked all the way to the root and didnt find anything :'(
|
||||||
|
if modDir == "/" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, gopath := range gopaths {
|
||||||
|
if len(gopath) < len(dir) && strings.EqualFold(gopath, dir[0:len(gopath)]) {
|
||||||
|
return dir[len(gopath)+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var modregex = regexp.MustCompile("module (.*)\n")
|
||||||
|
|
||||||
|
// NameForPackage returns the package name for a given import path. This can be really slow.
|
||||||
|
func NameForPackage(importPath string) string {
|
||||||
|
if importPath == "" {
|
||||||
|
panic(errors.New("import path can not be empty"))
|
||||||
|
}
|
||||||
|
if v, ok := nameForPackageCache.Load(importPath); ok {
|
||||||
|
return v.(string)
|
||||||
|
}
|
||||||
|
importPath = QualifyPackagePath(importPath)
|
||||||
|
p, _ := packages.Load(&packages.Config{
|
||||||
|
Mode: packages.NeedName,
|
||||||
|
}, importPath)
|
||||||
|
|
||||||
|
if len(p) != 1 || p[0].Name == "" {
|
||||||
|
return SanitizePackageName(filepath.Base(importPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
nameForPackageCache.Store(importPath, p[0].Name)
|
||||||
|
|
||||||
|
return p[0].Name
|
||||||
|
}
|
||||||
56
vendor/github.com/99designs/gqlgen/internal/code/util.go
generated
vendored
Normal file
56
vendor/github.com/99designs/gqlgen/internal/code/util.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package code
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/build"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// take a string in the form github.com/package/blah.Type and split it into package and type
|
||||||
|
func PkgAndType(name string) (string, string) {
|
||||||
|
parts := strings.Split(name, ".")
|
||||||
|
if len(parts) == 1 {
|
||||||
|
return "", name
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(parts[:len(parts)-1], "."), parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
var modsRegex = regexp.MustCompile(`^(\*|\[\])*`)
|
||||||
|
|
||||||
|
// NormalizeVendor takes a qualified package path and turns it into normal one.
|
||||||
|
// eg .
|
||||||
|
// github.com/foo/vendor/github.com/99designs/gqlgen/graphql becomes
|
||||||
|
// github.com/99designs/gqlgen/graphql
|
||||||
|
func NormalizeVendor(pkg string) string {
|
||||||
|
modifiers := modsRegex.FindAllString(pkg, 1)[0]
|
||||||
|
pkg = strings.TrimPrefix(pkg, modifiers)
|
||||||
|
parts := strings.Split(pkg, "/vendor/")
|
||||||
|
return modifiers + parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// QualifyPackagePath takes an import and fully qualifies it with a vendor dir, if one is required.
|
||||||
|
// eg .
|
||||||
|
// github.com/99designs/gqlgen/graphql becomes
|
||||||
|
// github.com/foo/vendor/github.com/99designs/gqlgen/graphql
|
||||||
|
//
|
||||||
|
// x/tools/packages only supports 'qualified package paths' so this will need to be done prior to calling it
|
||||||
|
// See https://github.com/golang/go/issues/30289
|
||||||
|
func QualifyPackagePath(importPath string) string {
|
||||||
|
wd, _ := os.Getwd()
|
||||||
|
|
||||||
|
pkg, err := build.Import(importPath, wd, 0)
|
||||||
|
if err != nil {
|
||||||
|
return importPath
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkg.ImportPath
|
||||||
|
}
|
||||||
|
|
||||||
|
var invalidPackageNameChar = regexp.MustCompile(`[^\w]`)
|
||||||
|
|
||||||
|
func SanitizePackageName(pkg string) string {
|
||||||
|
return invalidPackageNameChar.ReplaceAllLiteralString(filepath.Base(pkg), "_")
|
||||||
|
}
|
||||||
103
vendor/github.com/99designs/gqlgen/internal/imports/prune.go
generated
vendored
Normal file
103
vendor/github.com/99designs/gqlgen/internal/imports/prune.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// Wrapper around x/tools/imports that only removes imports, never adds new ones.
|
||||||
|
|
||||||
|
package imports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/printer"
|
||||||
|
"go/token"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/internal/code"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/ast/astutil"
|
||||||
|
"golang.org/x/tools/imports"
|
||||||
|
)
|
||||||
|
|
||||||
|
type visitFn func(node ast.Node)
|
||||||
|
|
||||||
|
func (fn visitFn) Visit(node ast.Node) ast.Visitor {
|
||||||
|
fn(node)
|
||||||
|
return fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prune removes any unused imports
|
||||||
|
func Prune(filename string, src []byte) ([]byte, error) {
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
|
||||||
|
file, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.AllErrors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
unused, err := getUnusedImports(file, filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for ipath, name := range unused {
|
||||||
|
astutil.DeleteNamedImport(fset, file, name, ipath)
|
||||||
|
}
|
||||||
|
printConfig := &printer.Config{Mode: printer.TabIndent, Tabwidth: 8}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := printConfig.Fprint(&buf, fset, file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return imports.Process(filename, buf.Bytes(), &imports.Options{FormatOnly: true, Comments: true, TabIndent: true, TabWidth: 8})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUnusedImports(file ast.Node, filename string) (map[string]string, error) {
|
||||||
|
imported := map[string]*ast.ImportSpec{}
|
||||||
|
used := map[string]bool{}
|
||||||
|
|
||||||
|
ast.Walk(visitFn(func(node ast.Node) {
|
||||||
|
if node == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch v := node.(type) {
|
||||||
|
case *ast.ImportSpec:
|
||||||
|
if v.Name != nil {
|
||||||
|
imported[v.Name.Name] = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ipath := strings.Trim(v.Path.Value, `"`)
|
||||||
|
if ipath == "C" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
local := code.NameForPackage(ipath)
|
||||||
|
|
||||||
|
imported[local] = v
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
xident, ok := v.X.(*ast.Ident)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if xident.Obj != nil {
|
||||||
|
// if the parser can resolve it, it's not a package ref
|
||||||
|
break
|
||||||
|
}
|
||||||
|
used[xident.Name] = true
|
||||||
|
}
|
||||||
|
}), file)
|
||||||
|
|
||||||
|
for pkg := range used {
|
||||||
|
delete(imported, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
unusedImport := map[string]string{}
|
||||||
|
for pkg, is := range imported {
|
||||||
|
if !used[pkg] && pkg != "_" && pkg != "." {
|
||||||
|
name := ""
|
||||||
|
if is.Name != nil {
|
||||||
|
name = is.Name.Name
|
||||||
|
}
|
||||||
|
unusedImport[strings.Trim(is.Path.Value, `"`)] = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unusedImport, nil
|
||||||
|
}
|
||||||
9
vendor/github.com/99designs/gqlgen/main.go
generated
vendored
Normal file
9
vendor/github.com/99designs/gqlgen/main.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/99designs/gqlgen/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
||||||
232
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go
generated
vendored
Normal file
232
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
package modelgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/99designs/gqlgen/internal/code"
|
||||||
|
"github.com/99designs/gqlgen/plugin"
|
||||||
|
"github.com/vektah/gqlparser/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ModelBuild struct {
|
||||||
|
PackageName string
|
||||||
|
Interfaces []*Interface
|
||||||
|
Models []*Object
|
||||||
|
Enums []*Enum
|
||||||
|
Scalars []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Interface struct {
|
||||||
|
Description string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
Description string
|
||||||
|
Name string
|
||||||
|
Fields []*Field
|
||||||
|
Implements []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
Description string
|
||||||
|
Name string
|
||||||
|
Type types.Type
|
||||||
|
Tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Enum struct {
|
||||||
|
Description string
|
||||||
|
Name string
|
||||||
|
Values []*EnumValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnumValue struct {
|
||||||
|
Description string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() plugin.Plugin {
|
||||||
|
return &Plugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin struct{}
|
||||||
|
|
||||||
|
var _ plugin.ConfigMutator = &Plugin{}
|
||||||
|
|
||||||
|
func (m *Plugin) Name() string {
|
||||||
|
return "modelgen"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
||||||
|
if err := cfg.Check(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
schema, _, err := cfg.LoadSchema()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.InjectBuiltins(schema)
|
||||||
|
|
||||||
|
binder, err := cfg.NewBinder(schema)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &ModelBuild{
|
||||||
|
PackageName: cfg.Model.Package,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, schemaType := range schema.Types {
|
||||||
|
if cfg.Models.UserDefined(schemaType.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch schemaType.Kind {
|
||||||
|
case ast.Interface, ast.Union:
|
||||||
|
it := &Interface{
|
||||||
|
Description: schemaType.Description,
|
||||||
|
Name: schemaType.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Interfaces = append(b.Interfaces, it)
|
||||||
|
case ast.Object, ast.InputObject:
|
||||||
|
if schemaType == schema.Query || schemaType == schema.Mutation || schemaType == schema.Subscription {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
it := &Object{
|
||||||
|
Description: schemaType.Description,
|
||||||
|
Name: schemaType.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, implementor := range schema.GetImplements(schemaType) {
|
||||||
|
it.Implements = append(it.Implements, implementor.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range schemaType.Fields {
|
||||||
|
var typ types.Type
|
||||||
|
fieldDef := schema.Types[field.Type.Name()]
|
||||||
|
|
||||||
|
if cfg.Models.UserDefined(field.Type.Name()) {
|
||||||
|
pkg, typeName := code.PkgAndType(cfg.Models[field.Type.Name()].Model[0])
|
||||||
|
typ, err = binder.FindType(pkg, typeName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch fieldDef.Kind {
|
||||||
|
case ast.Scalar:
|
||||||
|
// no user defined model, referencing a default scalar
|
||||||
|
typ = types.NewNamed(
|
||||||
|
types.NewTypeName(0, cfg.Model.Pkg(), "string", nil),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
case ast.Interface, ast.Union:
|
||||||
|
// no user defined model, referencing a generated interface type
|
||||||
|
typ = types.NewNamed(
|
||||||
|
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||||
|
types.NewInterfaceType([]*types.Func{}, []types.Type{}),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
case ast.Enum:
|
||||||
|
// no user defined model, must reference a generated enum
|
||||||
|
typ = types.NewNamed(
|
||||||
|
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
case ast.Object, ast.InputObject:
|
||||||
|
// no user defined model, must reference a generated struct
|
||||||
|
typ = types.NewNamed(
|
||||||
|
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||||
|
types.NewStruct(nil, nil),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown ast type %s", fieldDef.Kind))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name := field.Name
|
||||||
|
if nameOveride := cfg.Models[schemaType.Name].Fields[field.Name].FieldName; nameOveride != "" {
|
||||||
|
name = nameOveride
|
||||||
|
}
|
||||||
|
|
||||||
|
typ = binder.CopyModifiersFromAst(field.Type, typ)
|
||||||
|
|
||||||
|
if isStruct(typ) && (fieldDef.Kind == ast.Object || fieldDef.Kind == ast.InputObject) {
|
||||||
|
typ = types.NewPointer(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Fields = append(it.Fields, &Field{
|
||||||
|
Name: name,
|
||||||
|
Type: typ,
|
||||||
|
Description: field.Description,
|
||||||
|
Tag: `json:"` + field.Name + `"`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Models = append(b.Models, it)
|
||||||
|
case ast.Enum:
|
||||||
|
it := &Enum{
|
||||||
|
Name: schemaType.Name,
|
||||||
|
Description: schemaType.Description,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range schemaType.EnumValues {
|
||||||
|
it.Values = append(it.Values, &EnumValue{
|
||||||
|
Name: v.Name,
|
||||||
|
Description: v.Description,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Enums = append(b.Enums, it)
|
||||||
|
case ast.Scalar:
|
||||||
|
b.Scalars = append(b.Scalars, schemaType.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(b.Enums, func(i, j int) bool { return b.Enums[i].Name < b.Enums[j].Name })
|
||||||
|
sort.Slice(b.Models, func(i, j int) bool { return b.Models[i].Name < b.Models[j].Name })
|
||||||
|
sort.Slice(b.Interfaces, func(i, j int) bool { return b.Interfaces[i].Name < b.Interfaces[j].Name })
|
||||||
|
|
||||||
|
for _, it := range b.Enums {
|
||||||
|
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||||
|
}
|
||||||
|
for _, it := range b.Models {
|
||||||
|
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||||
|
}
|
||||||
|
for _, it := range b.Interfaces {
|
||||||
|
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||||
|
}
|
||||||
|
for _, it := range b.Scalars {
|
||||||
|
cfg.Models.Add(it, "github.com/99designs/gqlgen/graphql.String")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b.Models) == 0 && len(b.Enums) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return templates.Render(templates.Options{
|
||||||
|
PackageName: cfg.Model.Package,
|
||||||
|
Filename: cfg.Model.Filename,
|
||||||
|
Data: b,
|
||||||
|
GeneratedHeader: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func isStruct(t types.Type) bool {
|
||||||
|
_, is := t.Underlying().(*types.Struct)
|
||||||
|
return is
|
||||||
|
}
|
||||||
85
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl
generated
vendored
Normal file
85
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{{ reserveImport "context" }}
|
||||||
|
{{ reserveImport "fmt" }}
|
||||||
|
{{ reserveImport "io" }}
|
||||||
|
{{ reserveImport "strconv" }}
|
||||||
|
{{ reserveImport "time" }}
|
||||||
|
{{ reserveImport "sync" }}
|
||||||
|
{{ reserveImport "errors" }}
|
||||||
|
{{ reserveImport "bytes" }}
|
||||||
|
|
||||||
|
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||||
|
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||||
|
|
||||||
|
{{- range $model := .Interfaces }}
|
||||||
|
{{ with .Description }} {{.|prefixLines "// "}} {{ end }}
|
||||||
|
type {{.Name|go }} interface {
|
||||||
|
Is{{.Name|go }}()
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ range $model := .Models }}
|
||||||
|
{{with .Description }} {{.|prefixLines "// "}} {{end}}
|
||||||
|
type {{ .Name|go }} struct {
|
||||||
|
{{- range $field := .Fields }}
|
||||||
|
{{- with .Description }}
|
||||||
|
{{.|prefixLines "// "}}
|
||||||
|
{{- end}}
|
||||||
|
{{ $field.Name|go }} {{$field.Type | ref}} `{{$field.Tag}}`
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{- range $iface := .Implements }}
|
||||||
|
func ({{ $model.Name|go }}) Is{{ $iface|go }}() {}
|
||||||
|
{{- end }}
|
||||||
|
{{- end}}
|
||||||
|
|
||||||
|
{{ range $enum := .Enums }}
|
||||||
|
{{ with .Description|go }} {{.|prefixLines "// "}} {{end}}
|
||||||
|
type {{.Name|go }} string
|
||||||
|
const (
|
||||||
|
{{- range $value := .Values}}
|
||||||
|
{{- with .Description}}
|
||||||
|
{{.|prefixLines "// "}}
|
||||||
|
{{- end}}
|
||||||
|
{{ $enum.Name|go }}{{ .Name|go }} {{$enum.Name|go }} = {{.Name|quote}}
|
||||||
|
{{- end }}
|
||||||
|
)
|
||||||
|
|
||||||
|
var All{{.Name|go }} = []{{ .Name|go }}{
|
||||||
|
{{- range $value := .Values}}
|
||||||
|
{{$enum.Name|go }}{{ .Name|go }},
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e {{.Name|go }}) IsValid() bool {
|
||||||
|
switch e {
|
||||||
|
case {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.Name|go }}{{ $element.Name|go }}{{end}}:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e {{.Name|go }}) String() string {
|
||||||
|
return string(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *{{.Name|go }}) UnmarshalGQL(v interface{}) error {
|
||||||
|
str, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("enums must be strings")
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = {{ .Name|go }}(str)
|
||||||
|
if !e.IsValid() {
|
||||||
|
return fmt.Errorf("%s is not a valid {{ .Name }}", str)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e {{.Name|go }}) MarshalGQL(w io.Writer) {
|
||||||
|
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
20
vendor/github.com/99designs/gqlgen/plugin/plugin.go
generated
vendored
Normal file
20
vendor/github.com/99designs/gqlgen/plugin/plugin.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// plugin package interfaces are EXPERIMENTAL.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/99designs/gqlgen/codegen"
|
||||||
|
"github.com/99designs/gqlgen/codegen/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Plugin interface {
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigMutator interface {
|
||||||
|
MutateConfig(cfg *config.Config) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type CodeGenerator interface {
|
||||||
|
GenerateCode(cfg *codegen.Data) error
|
||||||
|
}
|
||||||
53
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go
generated
vendored
Normal file
53
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package resolvergen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen"
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/99designs/gqlgen/plugin"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() plugin.Plugin {
|
||||||
|
return &Plugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin struct{}
|
||||||
|
|
||||||
|
var _ plugin.CodeGenerator = &Plugin{}
|
||||||
|
|
||||||
|
func (m *Plugin) Name() string {
|
||||||
|
return "resovlergen"
|
||||||
|
}
|
||||||
|
func (m *Plugin) GenerateCode(data *codegen.Data) error {
|
||||||
|
if !data.Config.Resolver.IsDefined() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resolverBuild := &ResolverBuild{
|
||||||
|
Data: data,
|
||||||
|
PackageName: data.Config.Resolver.Package,
|
||||||
|
ResolverType: data.Config.Resolver.Type,
|
||||||
|
}
|
||||||
|
filename := data.Config.Resolver.Filename
|
||||||
|
|
||||||
|
if _, err := os.Stat(filename); os.IsNotExist(errors.Cause(err)) {
|
||||||
|
return templates.Render(templates.Options{
|
||||||
|
PackageName: data.Config.Resolver.Package,
|
||||||
|
Filename: data.Config.Resolver.Filename,
|
||||||
|
Data: resolverBuild,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Skipped resolver: %s already exists\n", filename)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResolverBuild struct {
|
||||||
|
*codegen.Data
|
||||||
|
|
||||||
|
PackageName string
|
||||||
|
ResolverType string
|
||||||
|
}
|
||||||
40
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl
generated
vendored
Normal file
40
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.
|
||||||
|
|
||||||
|
{{ reserveImport "context" }}
|
||||||
|
{{ reserveImport "fmt" }}
|
||||||
|
{{ reserveImport "io" }}
|
||||||
|
{{ reserveImport "strconv" }}
|
||||||
|
{{ reserveImport "time" }}
|
||||||
|
{{ reserveImport "sync" }}
|
||||||
|
{{ reserveImport "errors" }}
|
||||||
|
{{ reserveImport "bytes" }}
|
||||||
|
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/handler" }}
|
||||||
|
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||||
|
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||||
|
|
||||||
|
type {{.ResolverType}} struct {}
|
||||||
|
|
||||||
|
{{ range $object := .Objects -}}
|
||||||
|
{{- if $object.HasResolvers -}}
|
||||||
|
func (r *{{$.ResolverType}}) {{$object.Name}}() {{ $object.ResolverInterface | ref }} {
|
||||||
|
return &{{lcFirst $object.Name}}Resolver{r}
|
||||||
|
}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ range $object := .Objects -}}
|
||||||
|
{{- if $object.HasResolvers -}}
|
||||||
|
type {{lcFirst $object.Name}}Resolver struct { *Resolver }
|
||||||
|
|
||||||
|
{{ range $field := $object.Fields -}}
|
||||||
|
{{- if $field.IsResolver -}}
|
||||||
|
func (r *{{lcFirst $object.Name}}Resolver) {{$field.GoFieldName}}{{ $field.ShortResolverDeclaration }} {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end }}
|
||||||
49
vendor/github.com/99designs/gqlgen/plugin/servergen/server.go
generated
vendored
Normal file
49
vendor/github.com/99designs/gqlgen/plugin/servergen/server.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package servergen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/99designs/gqlgen/codegen"
|
||||||
|
"github.com/99designs/gqlgen/codegen/templates"
|
||||||
|
"github.com/99designs/gqlgen/plugin"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(filename string) plugin.Plugin {
|
||||||
|
return &Plugin{filename}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin struct {
|
||||||
|
filename string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ plugin.CodeGenerator = &Plugin{}
|
||||||
|
|
||||||
|
func (m *Plugin) Name() string {
|
||||||
|
return "servergen"
|
||||||
|
}
|
||||||
|
func (m *Plugin) GenerateCode(data *codegen.Data) error {
|
||||||
|
serverBuild := &ServerBuild{
|
||||||
|
ExecPackageName: data.Config.Exec.ImportPath(),
|
||||||
|
ResolverPackageName: data.Config.Resolver.ImportPath(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(m.filename); os.IsNotExist(errors.Cause(err)) {
|
||||||
|
return templates.Render(templates.Options{
|
||||||
|
PackageName: "main",
|
||||||
|
Filename: m.filename,
|
||||||
|
Data: serverBuild,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Skipped server: %s already exists\n", m.filename)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerBuild struct {
|
||||||
|
codegen.Data
|
||||||
|
|
||||||
|
ExecPackageName string
|
||||||
|
ResolverPackageName string
|
||||||
|
}
|
||||||
20
vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl
generated
vendored
Normal file
20
vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{{ reserveImport "context" }}
|
||||||
|
{{ reserveImport "log" }}
|
||||||
|
{{ reserveImport "net/http" }}
|
||||||
|
{{ reserveImport "os" }}
|
||||||
|
{{ reserveImport "github.com/99designs/gqlgen/handler" }}
|
||||||
|
|
||||||
|
const defaultPort = "8080"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
port := os.Getenv("PORT")
|
||||||
|
if port == "" {
|
||||||
|
port = defaultPort
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Handle("/", handler.Playground("GraphQL playground", "/query"))
|
||||||
|
http.Handle("/query", handler.GraphQL({{ lookupImport .ExecPackageName }}.NewExecutableSchema({{ lookupImport .ExecPackageName}}.Config{Resolvers: &{{ lookupImport .ResolverPackageName}}.Resolver{}})))
|
||||||
|
|
||||||
|
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
|
||||||
|
log.Fatal(http.ListenAndServe(":" + port, nil))
|
||||||
|
}
|
||||||
5
vendor/github.com/99designs/gqlgen/tools.go
generated
vendored
Normal file
5
vendor/github.com/99designs/gqlgen/tools.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// +build tools
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "github.com/vektah/dataloaden"
|
||||||
2
vendor/github.com/urfave/cli/.flake8
generated
vendored
Normal file
2
vendor/github.com/urfave/cli/.flake8
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[flake8]
|
||||||
|
max-line-length = 120
|
||||||
2
vendor/github.com/urfave/cli/.gitignore
generated
vendored
Normal file
2
vendor/github.com/urfave/cli/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.coverprofile
|
||||||
|
node_modules/
|
||||||
27
vendor/github.com/urfave/cli/.travis.yml
generated
vendored
Normal file
27
vendor/github.com/urfave/cli/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
dist: trusty
|
||||||
|
osx_image: xcode8.3
|
||||||
|
go: 1.8.x
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- go get github.com/urfave/gfmrun/... || true
|
||||||
|
- go get golang.org/x/tools/cmd/goimports
|
||||||
|
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
|
||||||
|
npm install markdown-toc ;
|
||||||
|
fi
|
||||||
|
|
||||||
|
script:
|
||||||
|
- ./runtests gen
|
||||||
|
- ./runtests vet
|
||||||
|
- ./runtests test
|
||||||
|
- ./runtests gfmrun
|
||||||
|
- ./runtests toc
|
||||||
435
vendor/github.com/urfave/cli/CHANGELOG.md
generated
vendored
Normal file
435
vendor/github.com/urfave/cli/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## 1.20.0 - 2017-08-10
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* `HandleExitCoder` is now correctly iterates over all errors in
|
||||||
|
a `MultiError`. The exit code is the exit code of the last error or `1` if
|
||||||
|
there are no `ExitCoder`s in the `MultiError`.
|
||||||
|
* Fixed YAML file loading on Windows (previously would fail validate the file path)
|
||||||
|
* Subcommand `Usage`, `Description`, `ArgsUsage`, `OnUsageError` correctly
|
||||||
|
propogated
|
||||||
|
* `ErrWriter` is now passed downwards through command structure to avoid the
|
||||||
|
need to redefine it
|
||||||
|
* Pass `Command` context into `OnUsageError` rather than parent context so that
|
||||||
|
all fields are avaiable
|
||||||
|
* Errors occuring in `Before` funcs are no longer double printed
|
||||||
|
* Use `UsageText` in the help templates for commands and subcommands if
|
||||||
|
defined; otherwise build the usage as before (was previously ignoring this
|
||||||
|
field)
|
||||||
|
* `IsSet` and `GlobalIsSet` now correctly return whether a flag is set if
|
||||||
|
a program calls `Set` or `GlobalSet` directly after flag parsing (would
|
||||||
|
previously only return `true` if the flag was set during parsing)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* No longer exit the program on command/subcommand error if the error raised is
|
||||||
|
not an `OsExiter`. This exiting behavior was introduced in 1.19.0, but was
|
||||||
|
determined to be a regression in functionality. See [the
|
||||||
|
PR](https://github.com/urfave/cli/pull/595) for discussion.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* `CommandsByName` type was added to make it easy to sort `Command`s by name,
|
||||||
|
alphabetically
|
||||||
|
* `altsrc` now handles loading of string and int arrays from TOML
|
||||||
|
* Support for definition of custom help templates for `App` via
|
||||||
|
`CustomAppHelpTemplate`
|
||||||
|
* Support for arbitrary key/value fields on `App` to be used with
|
||||||
|
`CustomAppHelpTemplate` via `ExtraInfo`
|
||||||
|
* `HelpFlag`, `VersionFlag`, and `BashCompletionFlag` changed to explictly be
|
||||||
|
`cli.Flag`s allowing for the use of custom flags satisfying the `cli.Flag`
|
||||||
|
interface to be used.
|
||||||
|
|
||||||
|
|
||||||
|
## [1.19.1] - 2016-11-21
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixes regression introduced in 1.19.0 where using an `ActionFunc` as
|
||||||
|
the `Action` for a command would cause it to error rather than calling the
|
||||||
|
function. Should not have a affected declarative cases using `func(c
|
||||||
|
*cli.Context) err)`.
|
||||||
|
- Shell completion now handles the case where the user specifies
|
||||||
|
`--generate-bash-completion` immediately after a flag that takes an argument.
|
||||||
|
Previously it call the application with `--generate-bash-completion` as the
|
||||||
|
flag value.
|
||||||
|
|
||||||
|
## [1.19.0] - 2016-11-19
|
||||||
|
### Added
|
||||||
|
- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`)
|
||||||
|
- A `Description` field was added to `App` for a more detailed description of
|
||||||
|
the application (similar to the existing `Description` field on `Command`)
|
||||||
|
- Flag type code generation via `go generate`
|
||||||
|
- Write to stderr and exit 1 if action returns non-nil error
|
||||||
|
- Added support for TOML to the `altsrc` loader
|
||||||
|
- `SkipArgReorder` was added to allow users to skip the argument reordering.
|
||||||
|
This is useful if you want to consider all "flags" after an argument as
|
||||||
|
arguments rather than flags (the default behavior of the stdlib `flag`
|
||||||
|
library). This is backported functionality from the [removal of the flag
|
||||||
|
reordering](https://github.com/urfave/cli/pull/398) in the unreleased version
|
||||||
|
2
|
||||||
|
- For formatted errors (those implementing `ErrorFormatter`), the errors will
|
||||||
|
be formatted during output. Compatible with `pkg/errors`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Raise minimum tested/supported Go version to 1.2+
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Consider empty environment variables as set (previously environment variables
|
||||||
|
with the equivalent of `""` would be skipped rather than their value used).
|
||||||
|
- Return an error if the value in a given environment variable cannot be parsed
|
||||||
|
as the flag type. Previously these errors were silently swallowed.
|
||||||
|
- Print full error when an invalid flag is specified (which includes the invalid flag)
|
||||||
|
- `App.Writer` defaults to `stdout` when `nil`
|
||||||
|
- If no action is specified on a command or app, the help is now printed instead of `panic`ing
|
||||||
|
- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized)
|
||||||
|
- Correctly show help message if `-h` is provided to a subcommand
|
||||||
|
- `context.(Global)IsSet` now respects environment variables. Previously it
|
||||||
|
would return `false` if a flag was specified in the environment rather than
|
||||||
|
as an argument
|
||||||
|
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
||||||
|
- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This
|
||||||
|
fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well
|
||||||
|
as `altsrc` where Go would complain that the types didn't match
|
||||||
|
|
||||||
|
## [1.18.1] - 2016-08-28
|
||||||
|
### Fixed
|
||||||
|
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)
|
||||||
|
|
||||||
|
## [1.18.0] - 2016-06-27
|
||||||
|
### Added
|
||||||
|
- `./runtests` test runner with coverage tracking by default
|
||||||
|
- testing on OS X
|
||||||
|
- testing on Windows
|
||||||
|
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Use spaces for alignment in help/usage output instead of tabs, making the
|
||||||
|
output alignment consistent regardless of tab width
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Printing of command aliases in help text
|
||||||
|
- Printing of visible flags for both struct and struct pointer flags
|
||||||
|
- Display the `help` subcommand when using `CommandCategories`
|
||||||
|
- No longer swallows `panic`s that occur within the `Action`s themselves when
|
||||||
|
detecting the signature of the `Action` field
|
||||||
|
|
||||||
|
## [1.17.1] - 2016-08-28
|
||||||
|
### Fixed
|
||||||
|
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
||||||
|
|
||||||
|
## [1.17.0] - 2016-05-09
|
||||||
|
### Added
|
||||||
|
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
|
||||||
|
- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
|
||||||
|
- Support for hiding commands by setting `Hidden: true` -- this will hide the
|
||||||
|
commands in help output
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
|
||||||
|
quoted in help text output.
|
||||||
|
- All flag types now include `(default: {value})` strings following usage when a
|
||||||
|
default value can be (reasonably) detected.
|
||||||
|
- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
|
||||||
|
with non-slice flag types
|
||||||
|
- Apps now exit with a code of 3 if an unknown subcommand is specified
|
||||||
|
(previously they printed "No help topic for...", but still exited 0. This
|
||||||
|
makes it easier to script around apps built using `cli` since they can trust
|
||||||
|
that a 0 exit code indicated a successful execution.
|
||||||
|
- cleanups based on [Go Report Card
|
||||||
|
feedback](https://goreportcard.com/report/github.com/urfave/cli)
|
||||||
|
|
||||||
|
## [1.16.1] - 2016-08-28
|
||||||
|
### Fixed
|
||||||
|
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
||||||
|
|
||||||
|
## [1.16.0] - 2016-05-02
|
||||||
|
### Added
|
||||||
|
- `Hidden` field on all flag struct types to omit from generated help text
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
|
||||||
|
generated help text via the `Hidden` field
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- handling of error values in `HandleAction` and `HandleExitCoder`
|
||||||
|
|
||||||
|
## [1.15.0] - 2016-04-30
|
||||||
|
### Added
|
||||||
|
- This file!
|
||||||
|
- Support for placeholders in flag usage strings
|
||||||
|
- `App.Metadata` map for arbitrary data/state management
|
||||||
|
- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
|
||||||
|
parsing.
|
||||||
|
- Support for nested lookup of dot-delimited keys in structures loaded from
|
||||||
|
YAML.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The `App.Action` and `Command.Action` now prefer a return signature of
|
||||||
|
`func(*cli.Context) error`, as defined by `cli.ActionFunc`. If a non-nil
|
||||||
|
`error` is returned, there may be two outcomes:
|
||||||
|
- If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
|
||||||
|
automatically
|
||||||
|
- Else the error is bubbled up and returned from `App.Run`
|
||||||
|
- Specifying an `Action` with the legacy return signature of
|
||||||
|
`func(*cli.Context)` will produce a deprecation message to stderr
|
||||||
|
- Specifying an `Action` that is not a `func` type will produce a non-zero exit
|
||||||
|
from `App.Run`
|
||||||
|
- Specifying an `Action` func that has an invalid (input) signature will
|
||||||
|
produce a non-zero exit from `App.Run`
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
- <a name="deprecated-cli-app-runandexitonerror"></a>
|
||||||
|
`cli.App.RunAndExitOnError`, which should now be done by returning an error
|
||||||
|
that fulfills `cli.ExitCoder` to `cli.App.Run`.
|
||||||
|
- <a name="deprecated-cli-app-action-signature"></a> the legacy signature for
|
||||||
|
`cli.App.Action` of `func(*cli.Context)`, which should now have a return
|
||||||
|
signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Added missing `*cli.Context.GlobalFloat64` method
|
||||||
|
|
||||||
|
## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Codebeat badge
|
||||||
|
- Support for categorization via `CategorizedHelp` and `Categories` on app.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Ensure version is not shown in help text when `HideVersion` set.
|
||||||
|
|
||||||
|
## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- YAML file input support.
|
||||||
|
- `NArg` method on context.
|
||||||
|
|
||||||
|
## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Custom usage error handling.
|
||||||
|
- Custom text support in `USAGE` section of help output.
|
||||||
|
- Improved help messages for empty strings.
|
||||||
|
- AppVeyor CI configuration.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Removed `panic` from default help printer func.
|
||||||
|
- De-duping and optimizations.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Correctly handle `Before`/`After` at command level when no subcommands.
|
||||||
|
- Case of literal `-` argument causing flag reordering.
|
||||||
|
- Environment variable hints on Windows.
|
||||||
|
- Docs updates.
|
||||||
|
|
||||||
|
## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
|
||||||
|
### Changed
|
||||||
|
- Use `path.Base` in `Name` and `HelpName`
|
||||||
|
- Export `GetName` on flag types.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Flag parsing when skipping is enabled.
|
||||||
|
- Test output cleanup.
|
||||||
|
- Move completion check to account for empty input case.
|
||||||
|
|
||||||
|
## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Destination scan support for flags.
|
||||||
|
- Testing against `tip` in Travis CI config.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Go version in Travis CI config.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Removed redundant tests.
|
||||||
|
- Use correct example naming in tests.
|
||||||
|
|
||||||
|
## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
|
||||||
|
### Fixed
|
||||||
|
- Remove unused var in bash completion.
|
||||||
|
|
||||||
|
## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Coverage and reference logos in README.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Use specified values in help and version parsing.
|
||||||
|
- Only display app version and help message once.
|
||||||
|
|
||||||
|
## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- More tests for existing functionality.
|
||||||
|
- `ArgsUsage` at app and command level for help text flexibility.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Honor `HideHelp` and `HideVersion` in `App.Run`.
|
||||||
|
- Remove juvenile word from README.
|
||||||
|
|
||||||
|
## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- `FullName` on command with accompanying help output update.
|
||||||
|
- Set default `$PROG` in bash completion.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Docs formatting.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Removed self-referential imports in tests.
|
||||||
|
|
||||||
|
## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Support for `Copyright` at app level.
|
||||||
|
- `Parent` func at context level to walk up context lineage.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Global flag processing at top level.
|
||||||
|
|
||||||
|
## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Aggregate errors from `Before`/`After` funcs.
|
||||||
|
- Doc comments on flag structs.
|
||||||
|
- Include non-global flags when checking version and help.
|
||||||
|
- Travis CI config updates.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Ensure slice type flags have non-nil values.
|
||||||
|
- Collect global flags from the full command hierarchy.
|
||||||
|
- Docs prose.
|
||||||
|
|
||||||
|
## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
|
||||||
|
### Changed
|
||||||
|
- `HelpPrinter` signature includes output writer.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Specify go 1.1+ in docs.
|
||||||
|
- Set `Writer` when running command as app.
|
||||||
|
|
||||||
|
## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Multiple author support.
|
||||||
|
- `NumFlags` at context level.
|
||||||
|
- `Aliases` at command level.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
- `ShortName` at command level.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Subcommand help output.
|
||||||
|
- Backward compatible support for deprecated `Author` and `Email` fields.
|
||||||
|
- Docs regarding `Names`/`Aliases`.
|
||||||
|
|
||||||
|
## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- `After` hook func support at app and command level.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Use parsed context when running command as subcommand.
|
||||||
|
- Docs prose.
|
||||||
|
|
||||||
|
## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Support for hiding `-h / --help` flags, but not `help` subcommand.
|
||||||
|
- Stop flag parsing after `--`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Help text for generic flags to specify single value.
|
||||||
|
- Use double quotes in output for defaults.
|
||||||
|
- Use `ParseInt` instead of `ParseUint` for int environment var values.
|
||||||
|
- Use `0` as base when parsing int environment var values.
|
||||||
|
|
||||||
|
## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Support for environment variable lookup "cascade".
|
||||||
|
- Support for `Stdout` on app for output redirection.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Print command help instead of app help in `ShowCommandHelp`.
|
||||||
|
|
||||||
|
## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- Docs and example code updates.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Default `-v / --version` flag made optional.
|
||||||
|
|
||||||
|
## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
|
||||||
|
### Added
|
||||||
|
- `FlagNames` at context level.
|
||||||
|
- Exposed `VersionPrinter` var for more control over version output.
|
||||||
|
- Zsh completion hook.
|
||||||
|
- `AUTHOR` section in default app help template.
|
||||||
|
- Contribution guidelines.
|
||||||
|
- `DurationFlag` type.
|
||||||
|
|
||||||
|
## [1.2.0] - 2014-08-02
|
||||||
|
### Added
|
||||||
|
- Support for environment variable defaults on flags plus tests.
|
||||||
|
|
||||||
|
## [1.1.0] - 2014-07-15
|
||||||
|
### Added
|
||||||
|
- Bash completion.
|
||||||
|
- Optional hiding of built-in help command.
|
||||||
|
- Optional skipping of flag parsing at command level.
|
||||||
|
- `Author`, `Email`, and `Compiled` metadata on app.
|
||||||
|
- `Before` hook func support at app and command level.
|
||||||
|
- `CommandNotFound` func support at app level.
|
||||||
|
- Command reference available on context.
|
||||||
|
- `GenericFlag` type.
|
||||||
|
- `Float64Flag` type.
|
||||||
|
- `BoolTFlag` type.
|
||||||
|
- `IsSet` flag helper on context.
|
||||||
|
- More flag lookup funcs at context level.
|
||||||
|
- More tests & docs.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Help template updates to account for presence/absence of flags.
|
||||||
|
- Separated subcommand help template.
|
||||||
|
- Exposed `HelpPrinter` var for more control over help output.
|
||||||
|
|
||||||
|
## [1.0.0] - 2013-11-01
|
||||||
|
### Added
|
||||||
|
- `help` flag in default app flag set and each command flag set.
|
||||||
|
- Custom handling of argument parsing errors.
|
||||||
|
- Command lookup by name at app level.
|
||||||
|
- `StringSliceFlag` type and supporting `StringSlice` type.
|
||||||
|
- `IntSliceFlag` type and supporting `IntSlice` type.
|
||||||
|
- Slice type flag lookups by name at context level.
|
||||||
|
- Export of app and command help functions.
|
||||||
|
- More tests & docs.
|
||||||
|
|
||||||
|
## 0.1.0 - 2013-07-22
|
||||||
|
### Added
|
||||||
|
- Initial implementation.
|
||||||
|
|
||||||
|
[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
|
||||||
|
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
|
||||||
|
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
|
||||||
|
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
|
||||||
|
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
|
||||||
|
[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
|
||||||
|
[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
|
||||||
|
[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
|
||||||
|
[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
|
||||||
|
[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
|
||||||
|
[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
|
||||||
|
[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
|
||||||
|
[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
|
||||||
|
[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
|
||||||
|
[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
|
||||||
|
[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
|
||||||
|
[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
|
||||||
|
[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
|
||||||
|
[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
|
||||||
|
[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
|
||||||
|
[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
|
||||||
|
[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
|
||||||
|
[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
|
||||||
|
[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
|
||||||
|
[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
|
||||||
|
[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0
|
||||||
21
vendor/github.com/urfave/cli/LICENSE
generated
vendored
Normal file
21
vendor/github.com/urfave/cli/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Jeremy Saenz & Contributors
|
||||||
|
|
||||||
|
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.
|
||||||
1381
vendor/github.com/urfave/cli/README.md
generated
vendored
Normal file
1381
vendor/github.com/urfave/cli/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
497
vendor/github.com/urfave/cli/app.go
generated
vendored
Normal file
497
vendor/github.com/urfave/cli/app.go
generated
vendored
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
|
||||||
|
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
|
||||||
|
runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
|
||||||
|
|
||||||
|
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
|
||||||
|
|
||||||
|
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
|
||||||
|
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
|
||||||
|
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
|
||||||
|
)
|
||||||
|
|
||||||
|
// App is the main structure of a cli application. It is recommended that
|
||||||
|
// an app be created with the cli.NewApp() function
|
||||||
|
type App struct {
|
||||||
|
// The name of the program. Defaults to path.Base(os.Args[0])
|
||||||
|
Name string
|
||||||
|
// Full name of command for help, defaults to Name
|
||||||
|
HelpName string
|
||||||
|
// Description of the program.
|
||||||
|
Usage string
|
||||||
|
// Text to override the USAGE section of help
|
||||||
|
UsageText string
|
||||||
|
// Description of the program argument format.
|
||||||
|
ArgsUsage string
|
||||||
|
// Version of the program
|
||||||
|
Version string
|
||||||
|
// Description of the program
|
||||||
|
Description string
|
||||||
|
// List of commands to execute
|
||||||
|
Commands []Command
|
||||||
|
// List of flags to parse
|
||||||
|
Flags []Flag
|
||||||
|
// Boolean to enable bash completion commands
|
||||||
|
EnableBashCompletion bool
|
||||||
|
// Boolean to hide built-in help command
|
||||||
|
HideHelp bool
|
||||||
|
// Boolean to hide built-in version flag and the VERSION section of help
|
||||||
|
HideVersion bool
|
||||||
|
// Populate on app startup, only gettable through method Categories()
|
||||||
|
categories CommandCategories
|
||||||
|
// An action to execute when the bash-completion flag is set
|
||||||
|
BashComplete BashCompleteFunc
|
||||||
|
// An action to execute before any subcommands are run, but after the context is ready
|
||||||
|
// If a non-nil error is returned, no subcommands are run
|
||||||
|
Before BeforeFunc
|
||||||
|
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||||
|
// It is run even if Action() panics
|
||||||
|
After AfterFunc
|
||||||
|
|
||||||
|
// The action to execute when no subcommands are specified
|
||||||
|
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
|
||||||
|
// *Note*: support for the deprecated `Action` signature will be removed in a future version
|
||||||
|
Action interface{}
|
||||||
|
|
||||||
|
// Execute this function if the proper command cannot be found
|
||||||
|
CommandNotFound CommandNotFoundFunc
|
||||||
|
// Execute this function if an usage error occurs
|
||||||
|
OnUsageError OnUsageErrorFunc
|
||||||
|
// Compilation date
|
||||||
|
Compiled time.Time
|
||||||
|
// List of all authors who contributed
|
||||||
|
Authors []Author
|
||||||
|
// Copyright of the binary if any
|
||||||
|
Copyright string
|
||||||
|
// Name of Author (Note: Use App.Authors, this is deprecated)
|
||||||
|
Author string
|
||||||
|
// Email of Author (Note: Use App.Authors, this is deprecated)
|
||||||
|
Email string
|
||||||
|
// Writer writer to write output to
|
||||||
|
Writer io.Writer
|
||||||
|
// ErrWriter writes error output
|
||||||
|
ErrWriter io.Writer
|
||||||
|
// Other custom info
|
||||||
|
Metadata map[string]interface{}
|
||||||
|
// Carries a function which returns app specific info.
|
||||||
|
ExtraInfo func() map[string]string
|
||||||
|
// CustomAppHelpTemplate the text template for app help topic.
|
||||||
|
// cli.go uses text/template to render templates. You can
|
||||||
|
// render custom help text by setting this variable.
|
||||||
|
CustomAppHelpTemplate string
|
||||||
|
|
||||||
|
didSetup bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tries to find out when this binary was compiled.
|
||||||
|
// Returns the current time if it fails to find it.
|
||||||
|
func compileTime() time.Time {
|
||||||
|
info, err := os.Stat(os.Args[0])
|
||||||
|
if err != nil {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
return info.ModTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewApp creates a new cli Application with some reasonable defaults for Name,
|
||||||
|
// Usage, Version and Action.
|
||||||
|
func NewApp() *App {
|
||||||
|
return &App{
|
||||||
|
Name: filepath.Base(os.Args[0]),
|
||||||
|
HelpName: filepath.Base(os.Args[0]),
|
||||||
|
Usage: "A new cli application",
|
||||||
|
UsageText: "",
|
||||||
|
Version: "0.0.0",
|
||||||
|
BashComplete: DefaultAppComplete,
|
||||||
|
Action: helpCommand.Action,
|
||||||
|
Compiled: compileTime(),
|
||||||
|
Writer: os.Stdout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup runs initialization code to ensure all data structures are ready for
|
||||||
|
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but
|
||||||
|
// will return early if setup has already happened.
|
||||||
|
func (a *App) Setup() {
|
||||||
|
if a.didSetup {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a.didSetup = true
|
||||||
|
|
||||||
|
if a.Author != "" || a.Email != "" {
|
||||||
|
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
|
||||||
|
}
|
||||||
|
|
||||||
|
newCmds := []Command{}
|
||||||
|
for _, c := range a.Commands {
|
||||||
|
if c.HelpName == "" {
|
||||||
|
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
||||||
|
}
|
||||||
|
newCmds = append(newCmds, c)
|
||||||
|
}
|
||||||
|
a.Commands = newCmds
|
||||||
|
|
||||||
|
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||||
|
a.Commands = append(a.Commands, helpCommand)
|
||||||
|
if (HelpFlag != BoolFlag{}) {
|
||||||
|
a.appendFlag(HelpFlag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.HideVersion {
|
||||||
|
a.appendFlag(VersionFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.categories = CommandCategories{}
|
||||||
|
for _, command := range a.Commands {
|
||||||
|
a.categories = a.categories.AddCommand(command.Category, command)
|
||||||
|
}
|
||||||
|
sort.Sort(a.categories)
|
||||||
|
|
||||||
|
if a.Metadata == nil {
|
||||||
|
a.Metadata = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Writer == nil {
|
||||||
|
a.Writer = os.Stdout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run is the entry point to the cli app. Parses the arguments slice and routes
|
||||||
|
// to the proper flag/args combination
|
||||||
|
func (a *App) Run(arguments []string) (err error) {
|
||||||
|
a.Setup()
|
||||||
|
|
||||||
|
// handle the completion flag separately from the flagset since
|
||||||
|
// completion could be attempted after a flag, but before its value was put
|
||||||
|
// on the command line. this causes the flagset to interpret the completion
|
||||||
|
// flag name as the value of the flag before it which is undesirable
|
||||||
|
// note that we can only do this because the shell autocomplete function
|
||||||
|
// always appends the completion flag at the end of the command
|
||||||
|
shellComplete, arguments := checkShellCompleteFlag(a, arguments)
|
||||||
|
|
||||||
|
// parse flags
|
||||||
|
set, err := flagSet(a.Name, a.Flags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
set.SetOutput(ioutil.Discard)
|
||||||
|
err = set.Parse(arguments[1:])
|
||||||
|
nerr := normalizeFlags(a.Flags, set)
|
||||||
|
context := NewContext(a, set, nil)
|
||||||
|
if nerr != nil {
|
||||||
|
fmt.Fprintln(a.Writer, nerr)
|
||||||
|
ShowAppHelp(context)
|
||||||
|
return nerr
|
||||||
|
}
|
||||||
|
context.shellComplete = shellComplete
|
||||||
|
|
||||||
|
if checkCompletions(context) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if a.OnUsageError != nil {
|
||||||
|
err := a.OnUsageError(context, err, false)
|
||||||
|
HandleExitCoder(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
||||||
|
ShowAppHelp(context)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.HideHelp && checkHelp(context) {
|
||||||
|
ShowAppHelp(context)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.HideVersion && checkVersion(context) {
|
||||||
|
ShowVersion(context)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.After != nil {
|
||||||
|
defer func() {
|
||||||
|
if afterErr := a.After(context); afterErr != nil {
|
||||||
|
if err != nil {
|
||||||
|
err = NewMultiError(err, afterErr)
|
||||||
|
} else {
|
||||||
|
err = afterErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Before != nil {
|
||||||
|
beforeErr := a.Before(context)
|
||||||
|
if beforeErr != nil {
|
||||||
|
ShowAppHelp(context)
|
||||||
|
HandleExitCoder(beforeErr)
|
||||||
|
err = beforeErr
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args := context.Args()
|
||||||
|
if args.Present() {
|
||||||
|
name := args.First()
|
||||||
|
c := a.Command(name)
|
||||||
|
if c != nil {
|
||||||
|
return c.Run(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Action == nil {
|
||||||
|
a.Action = helpCommand.Action
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run default Action
|
||||||
|
err = HandleAction(a.Action, context)
|
||||||
|
|
||||||
|
HandleExitCoder(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
|
||||||
|
//
|
||||||
|
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
|
||||||
|
// to cli.App.Run. This will cause the application to exit with the given eror
|
||||||
|
// code in the cli.ExitCoder
|
||||||
|
func (a *App) RunAndExitOnError() {
|
||||||
|
if err := a.Run(os.Args); err != nil {
|
||||||
|
fmt.Fprintln(a.errWriter(), err)
|
||||||
|
OsExiter(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
|
||||||
|
// generate command-specific flags
|
||||||
|
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||||
|
// append help to commands
|
||||||
|
if len(a.Commands) > 0 {
|
||||||
|
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||||
|
a.Commands = append(a.Commands, helpCommand)
|
||||||
|
if (HelpFlag != BoolFlag{}) {
|
||||||
|
a.appendFlag(HelpFlag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newCmds := []Command{}
|
||||||
|
for _, c := range a.Commands {
|
||||||
|
if c.HelpName == "" {
|
||||||
|
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
||||||
|
}
|
||||||
|
newCmds = append(newCmds, c)
|
||||||
|
}
|
||||||
|
a.Commands = newCmds
|
||||||
|
|
||||||
|
// parse flags
|
||||||
|
set, err := flagSet(a.Name, a.Flags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
set.SetOutput(ioutil.Discard)
|
||||||
|
err = set.Parse(ctx.Args().Tail())
|
||||||
|
nerr := normalizeFlags(a.Flags, set)
|
||||||
|
context := NewContext(a, set, ctx)
|
||||||
|
|
||||||
|
if nerr != nil {
|
||||||
|
fmt.Fprintln(a.Writer, nerr)
|
||||||
|
fmt.Fprintln(a.Writer)
|
||||||
|
if len(a.Commands) > 0 {
|
||||||
|
ShowSubcommandHelp(context)
|
||||||
|
} else {
|
||||||
|
ShowCommandHelp(ctx, context.Args().First())
|
||||||
|
}
|
||||||
|
return nerr
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkCompletions(context) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if a.OnUsageError != nil {
|
||||||
|
err = a.OnUsageError(context, err, true)
|
||||||
|
HandleExitCoder(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
||||||
|
ShowSubcommandHelp(context)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a.Commands) > 0 {
|
||||||
|
if checkSubcommandHelp(context) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if checkCommandHelp(ctx, context.Args().First()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.After != nil {
|
||||||
|
defer func() {
|
||||||
|
afterErr := a.After(context)
|
||||||
|
if afterErr != nil {
|
||||||
|
HandleExitCoder(err)
|
||||||
|
if err != nil {
|
||||||
|
err = NewMultiError(err, afterErr)
|
||||||
|
} else {
|
||||||
|
err = afterErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Before != nil {
|
||||||
|
beforeErr := a.Before(context)
|
||||||
|
if beforeErr != nil {
|
||||||
|
HandleExitCoder(beforeErr)
|
||||||
|
err = beforeErr
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args := context.Args()
|
||||||
|
if args.Present() {
|
||||||
|
name := args.First()
|
||||||
|
c := a.Command(name)
|
||||||
|
if c != nil {
|
||||||
|
return c.Run(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run default Action
|
||||||
|
err = HandleAction(a.Action, context)
|
||||||
|
|
||||||
|
HandleExitCoder(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the named command on App. Returns nil if the command does not exist
|
||||||
|
func (a *App) Command(name string) *Command {
|
||||||
|
for _, c := range a.Commands {
|
||||||
|
if c.HasName(name) {
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Categories returns a slice containing all the categories with the commands they contain
|
||||||
|
func (a *App) Categories() CommandCategories {
|
||||||
|
return a.categories
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleCategories returns a slice of categories and commands that are
|
||||||
|
// Hidden=false
|
||||||
|
func (a *App) VisibleCategories() []*CommandCategory {
|
||||||
|
ret := []*CommandCategory{}
|
||||||
|
for _, category := range a.categories {
|
||||||
|
if visible := func() *CommandCategory {
|
||||||
|
for _, command := range category.Commands {
|
||||||
|
if !command.Hidden {
|
||||||
|
return category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); visible != nil {
|
||||||
|
ret = append(ret, visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleCommands returns a slice of the Commands with Hidden=false
|
||||||
|
func (a *App) VisibleCommands() []Command {
|
||||||
|
ret := []Command{}
|
||||||
|
for _, command := range a.Commands {
|
||||||
|
if !command.Hidden {
|
||||||
|
ret = append(ret, command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleFlags returns a slice of the Flags with Hidden=false
|
||||||
|
func (a *App) VisibleFlags() []Flag {
|
||||||
|
return visibleFlags(a.Flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) hasFlag(flag Flag) bool {
|
||||||
|
for _, f := range a.Flags {
|
||||||
|
if flag == f {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) errWriter() io.Writer {
|
||||||
|
|
||||||
|
// When the app ErrWriter is nil use the package level one.
|
||||||
|
if a.ErrWriter == nil {
|
||||||
|
return ErrWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.ErrWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) appendFlag(flag Flag) {
|
||||||
|
if !a.hasFlag(flag) {
|
||||||
|
a.Flags = append(a.Flags, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Author represents someone who has contributed to a cli project.
|
||||||
|
type Author struct {
|
||||||
|
Name string // The Authors name
|
||||||
|
Email string // The Authors email
|
||||||
|
}
|
||||||
|
|
||||||
|
// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
|
||||||
|
func (a Author) String() string {
|
||||||
|
e := ""
|
||||||
|
if a.Email != "" {
|
||||||
|
e = " <" + a.Email + ">"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%v%v", a.Name, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleAction attempts to figure out which Action signature was used. If
|
||||||
|
// it's an ActionFunc or a func with the legacy signature for Action, the func
|
||||||
|
// is run!
|
||||||
|
func HandleAction(action interface{}, context *Context) (err error) {
|
||||||
|
if a, ok := action.(ActionFunc); ok {
|
||||||
|
return a(context)
|
||||||
|
} else if a, ok := action.(func(*Context) error); ok {
|
||||||
|
return a(context)
|
||||||
|
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
||||||
|
a(context)
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errInvalidActionType
|
||||||
|
}
|
||||||
|
}
|
||||||
26
vendor/github.com/urfave/cli/appveyor.yml
generated
vendored
Normal file
26
vendor/github.com/urfave/cli/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
os: Windows Server 2016
|
||||||
|
|
||||||
|
image: Visual Studio 2017
|
||||||
|
|
||||||
|
clone_folder: c:\gopath\src\github.com\urfave\cli
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: C:\gopath
|
||||||
|
GOVERSION: 1.8.x
|
||||||
|
PYTHON: C:\Python36-x64
|
||||||
|
PYTHON_VERSION: 3.6.x
|
||||||
|
PYTHON_ARCH: 64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
- go get github.com/urfave/gfmrun/...
|
||||||
|
- go get -v -t ./...
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- python runtests vet
|
||||||
|
- python runtests test
|
||||||
|
- python runtests gfmrun
|
||||||
44
vendor/github.com/urfave/cli/category.go
generated
vendored
Normal file
44
vendor/github.com/urfave/cli/category.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
// CommandCategories is a slice of *CommandCategory.
|
||||||
|
type CommandCategories []*CommandCategory
|
||||||
|
|
||||||
|
// CommandCategory is a category containing commands.
|
||||||
|
type CommandCategory struct {
|
||||||
|
Name string
|
||||||
|
Commands Commands
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommandCategories) Less(i, j int) bool {
|
||||||
|
return c[i].Name < c[j].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommandCategories) Len() int {
|
||||||
|
return len(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommandCategories) Swap(i, j int) {
|
||||||
|
c[i], c[j] = c[j], c[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCommand adds a command to a category.
|
||||||
|
func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
|
||||||
|
for _, commandCategory := range c {
|
||||||
|
if commandCategory.Name == category {
|
||||||
|
commandCategory.Commands = append(commandCategory.Commands, command)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleCommands returns a slice of the Commands with Hidden=false
|
||||||
|
func (c *CommandCategory) VisibleCommands() []Command {
|
||||||
|
ret := []Command{}
|
||||||
|
for _, command := range c.Commands {
|
||||||
|
if !command.Hidden {
|
||||||
|
ret = append(ret, command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
22
vendor/github.com/urfave/cli/cli.go
generated
vendored
Normal file
22
vendor/github.com/urfave/cli/cli.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Package cli provides a minimal framework for creating and organizing command line
|
||||||
|
// Go applications. cli is designed to be easy to understand and write, the most simple
|
||||||
|
// cli application can be written as follows:
|
||||||
|
// func main() {
|
||||||
|
// cli.NewApp().Run(os.Args)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Of course this application does not do much, so let's make this an actual application:
|
||||||
|
// func main() {
|
||||||
|
// app := cli.NewApp()
|
||||||
|
// app.Name = "greet"
|
||||||
|
// app.Usage = "say a greeting"
|
||||||
|
// app.Action = func(c *cli.Context) error {
|
||||||
|
// println("Greetings")
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// app.Run(os.Args)
|
||||||
|
// }
|
||||||
|
package cli
|
||||||
|
|
||||||
|
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
|
||||||
304
vendor/github.com/urfave/cli/command.go
generated
vendored
Normal file
304
vendor/github.com/urfave/cli/command.go
generated
vendored
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Command is a subcommand for a cli.App.
|
||||||
|
type Command struct {
|
||||||
|
// The name of the command
|
||||||
|
Name string
|
||||||
|
// short name of the command. Typically one character (deprecated, use `Aliases`)
|
||||||
|
ShortName string
|
||||||
|
// A list of aliases for the command
|
||||||
|
Aliases []string
|
||||||
|
// A short description of the usage of this command
|
||||||
|
Usage string
|
||||||
|
// Custom text to show on USAGE section of help
|
||||||
|
UsageText string
|
||||||
|
// A longer explanation of how the command works
|
||||||
|
Description string
|
||||||
|
// A short description of the arguments of this command
|
||||||
|
ArgsUsage string
|
||||||
|
// The category the command is part of
|
||||||
|
Category string
|
||||||
|
// The function to call when checking for bash command completions
|
||||||
|
BashComplete BashCompleteFunc
|
||||||
|
// An action to execute before any sub-subcommands are run, but after the context is ready
|
||||||
|
// If a non-nil error is returned, no sub-subcommands are run
|
||||||
|
Before BeforeFunc
|
||||||
|
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||||
|
// It is run even if Action() panics
|
||||||
|
After AfterFunc
|
||||||
|
// The function to call when this command is invoked
|
||||||
|
Action interface{}
|
||||||
|
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
|
||||||
|
// of deprecation period has passed, maybe?
|
||||||
|
|
||||||
|
// Execute this function if a usage error occurs.
|
||||||
|
OnUsageError OnUsageErrorFunc
|
||||||
|
// List of child commands
|
||||||
|
Subcommands Commands
|
||||||
|
// List of flags to parse
|
||||||
|
Flags []Flag
|
||||||
|
// Treat all flags as normal arguments if true
|
||||||
|
SkipFlagParsing bool
|
||||||
|
// Skip argument reordering which attempts to move flags before arguments,
|
||||||
|
// but only works if all flags appear after all arguments. This behavior was
|
||||||
|
// removed n version 2 since it only works under specific conditions so we
|
||||||
|
// backport here by exposing it as an option for compatibility.
|
||||||
|
SkipArgReorder bool
|
||||||
|
// Boolean to hide built-in help command
|
||||||
|
HideHelp bool
|
||||||
|
// Boolean to hide this command from help or completion
|
||||||
|
Hidden bool
|
||||||
|
|
||||||
|
// Full name of command for help, defaults to full command name, including parent commands.
|
||||||
|
HelpName string
|
||||||
|
commandNamePath []string
|
||||||
|
|
||||||
|
// CustomHelpTemplate the text template for the command help topic.
|
||||||
|
// cli.go uses text/template to render templates. You can
|
||||||
|
// render custom help text by setting this variable.
|
||||||
|
CustomHelpTemplate string
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommandsByName []Command
|
||||||
|
|
||||||
|
func (c CommandsByName) Len() int {
|
||||||
|
return len(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommandsByName) Less(i, j int) bool {
|
||||||
|
return c[i].Name < c[j].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommandsByName) Swap(i, j int) {
|
||||||
|
c[i], c[j] = c[j], c[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// FullName returns the full name of the command.
|
||||||
|
// For subcommands this ensures that parent commands are part of the command path
|
||||||
|
func (c Command) FullName() string {
|
||||||
|
if c.commandNamePath == nil {
|
||||||
|
return c.Name
|
||||||
|
}
|
||||||
|
return strings.Join(c.commandNamePath, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commands is a slice of Command
|
||||||
|
type Commands []Command
|
||||||
|
|
||||||
|
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
||||||
|
func (c Command) Run(ctx *Context) (err error) {
|
||||||
|
if len(c.Subcommands) > 0 {
|
||||||
|
return c.startApp(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
|
||||||
|
// append help to flags
|
||||||
|
c.Flags = append(
|
||||||
|
c.Flags,
|
||||||
|
HelpFlag,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
set, err := flagSet(c.Name, c.Flags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
set.SetOutput(ioutil.Discard)
|
||||||
|
|
||||||
|
if c.SkipFlagParsing {
|
||||||
|
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
|
||||||
|
} else if !c.SkipArgReorder {
|
||||||
|
firstFlagIndex := -1
|
||||||
|
terminatorIndex := -1
|
||||||
|
for index, arg := range ctx.Args() {
|
||||||
|
if arg == "--" {
|
||||||
|
terminatorIndex = index
|
||||||
|
break
|
||||||
|
} else if arg == "-" {
|
||||||
|
// Do nothing. A dash alone is not really a flag.
|
||||||
|
continue
|
||||||
|
} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
|
||||||
|
firstFlagIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if firstFlagIndex > -1 {
|
||||||
|
args := ctx.Args()
|
||||||
|
regularArgs := make([]string, len(args[1:firstFlagIndex]))
|
||||||
|
copy(regularArgs, args[1:firstFlagIndex])
|
||||||
|
|
||||||
|
var flagArgs []string
|
||||||
|
if terminatorIndex > -1 {
|
||||||
|
flagArgs = args[firstFlagIndex:terminatorIndex]
|
||||||
|
regularArgs = append(regularArgs, args[terminatorIndex:]...)
|
||||||
|
} else {
|
||||||
|
flagArgs = args[firstFlagIndex:]
|
||||||
|
}
|
||||||
|
|
||||||
|
err = set.Parse(append(flagArgs, regularArgs...))
|
||||||
|
} else {
|
||||||
|
err = set.Parse(ctx.Args().Tail())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = set.Parse(ctx.Args().Tail())
|
||||||
|
}
|
||||||
|
|
||||||
|
nerr := normalizeFlags(c.Flags, set)
|
||||||
|
if nerr != nil {
|
||||||
|
fmt.Fprintln(ctx.App.Writer, nerr)
|
||||||
|
fmt.Fprintln(ctx.App.Writer)
|
||||||
|
ShowCommandHelp(ctx, c.Name)
|
||||||
|
return nerr
|
||||||
|
}
|
||||||
|
|
||||||
|
context := NewContext(ctx.App, set, ctx)
|
||||||
|
context.Command = c
|
||||||
|
if checkCommandCompletions(context, c.Name) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if c.OnUsageError != nil {
|
||||||
|
err := c.OnUsageError(context, err, false)
|
||||||
|
HandleExitCoder(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error())
|
||||||
|
fmt.Fprintln(context.App.Writer)
|
||||||
|
ShowCommandHelp(context, c.Name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkCommandHelp(context, c.Name) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.After != nil {
|
||||||
|
defer func() {
|
||||||
|
afterErr := c.After(context)
|
||||||
|
if afterErr != nil {
|
||||||
|
HandleExitCoder(err)
|
||||||
|
if err != nil {
|
||||||
|
err = NewMultiError(err, afterErr)
|
||||||
|
} else {
|
||||||
|
err = afterErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Before != nil {
|
||||||
|
err = c.Before(context)
|
||||||
|
if err != nil {
|
||||||
|
ShowCommandHelp(context, c.Name)
|
||||||
|
HandleExitCoder(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Action == nil {
|
||||||
|
c.Action = helpSubcommand.Action
|
||||||
|
}
|
||||||
|
|
||||||
|
err = HandleAction(c.Action, context)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
HandleExitCoder(err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Names returns the names including short names and aliases.
|
||||||
|
func (c Command) Names() []string {
|
||||||
|
names := []string{c.Name}
|
||||||
|
|
||||||
|
if c.ShortName != "" {
|
||||||
|
names = append(names, c.ShortName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(names, c.Aliases...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasName returns true if Command.Name or Command.ShortName matches given name
|
||||||
|
func (c Command) HasName(name string) bool {
|
||||||
|
for _, n := range c.Names() {
|
||||||
|
if n == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Command) startApp(ctx *Context) error {
|
||||||
|
app := NewApp()
|
||||||
|
app.Metadata = ctx.App.Metadata
|
||||||
|
// set the name and usage
|
||||||
|
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
|
||||||
|
if c.HelpName == "" {
|
||||||
|
app.HelpName = c.HelpName
|
||||||
|
} else {
|
||||||
|
app.HelpName = app.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Usage = c.Usage
|
||||||
|
app.Description = c.Description
|
||||||
|
app.ArgsUsage = c.ArgsUsage
|
||||||
|
|
||||||
|
// set CommandNotFound
|
||||||
|
app.CommandNotFound = ctx.App.CommandNotFound
|
||||||
|
app.CustomAppHelpTemplate = c.CustomHelpTemplate
|
||||||
|
|
||||||
|
// set the flags and commands
|
||||||
|
app.Commands = c.Subcommands
|
||||||
|
app.Flags = c.Flags
|
||||||
|
app.HideHelp = c.HideHelp
|
||||||
|
|
||||||
|
app.Version = ctx.App.Version
|
||||||
|
app.HideVersion = ctx.App.HideVersion
|
||||||
|
app.Compiled = ctx.App.Compiled
|
||||||
|
app.Author = ctx.App.Author
|
||||||
|
app.Email = ctx.App.Email
|
||||||
|
app.Writer = ctx.App.Writer
|
||||||
|
app.ErrWriter = ctx.App.ErrWriter
|
||||||
|
|
||||||
|
app.categories = CommandCategories{}
|
||||||
|
for _, command := range c.Subcommands {
|
||||||
|
app.categories = app.categories.AddCommand(command.Category, command)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(app.categories)
|
||||||
|
|
||||||
|
// bash completion
|
||||||
|
app.EnableBashCompletion = ctx.App.EnableBashCompletion
|
||||||
|
if c.BashComplete != nil {
|
||||||
|
app.BashComplete = c.BashComplete
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the actions
|
||||||
|
app.Before = c.Before
|
||||||
|
app.After = c.After
|
||||||
|
if c.Action != nil {
|
||||||
|
app.Action = c.Action
|
||||||
|
} else {
|
||||||
|
app.Action = helpSubcommand.Action
|
||||||
|
}
|
||||||
|
app.OnUsageError = c.OnUsageError
|
||||||
|
|
||||||
|
for index, cc := range app.Commands {
|
||||||
|
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.RunAsSubcommand(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleFlags returns a slice of the Flags with Hidden=false
|
||||||
|
func (c Command) VisibleFlags() []Flag {
|
||||||
|
return visibleFlags(c.Flags)
|
||||||
|
}
|
||||||
278
vendor/github.com/urfave/cli/context.go
generated
vendored
Normal file
278
vendor/github.com/urfave/cli/context.go
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Context is a type that is passed through to
|
||||||
|
// each Handler action in a cli application. Context
|
||||||
|
// can be used to retrieve context-specific Args and
|
||||||
|
// parsed command-line options.
|
||||||
|
type Context struct {
|
||||||
|
App *App
|
||||||
|
Command Command
|
||||||
|
shellComplete bool
|
||||||
|
flagSet *flag.FlagSet
|
||||||
|
setFlags map[string]bool
|
||||||
|
parentContext *Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext creates a new context. For use in when invoking an App or Command action.
|
||||||
|
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
|
||||||
|
c := &Context{App: app, flagSet: set, parentContext: parentCtx}
|
||||||
|
|
||||||
|
if parentCtx != nil {
|
||||||
|
c.shellComplete = parentCtx.shellComplete
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumFlags returns the number of flags set
|
||||||
|
func (c *Context) NumFlags() int {
|
||||||
|
return c.flagSet.NFlag()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets a context flag to a value.
|
||||||
|
func (c *Context) Set(name, value string) error {
|
||||||
|
c.setFlags = nil
|
||||||
|
return c.flagSet.Set(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalSet sets a context flag to a value on the global flagset
|
||||||
|
func (c *Context) GlobalSet(name, value string) error {
|
||||||
|
globalContext(c).setFlags = nil
|
||||||
|
return globalContext(c).flagSet.Set(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet determines if the flag was actually set
|
||||||
|
func (c *Context) IsSet(name string) bool {
|
||||||
|
if c.setFlags == nil {
|
||||||
|
c.setFlags = make(map[string]bool)
|
||||||
|
|
||||||
|
c.flagSet.Visit(func(f *flag.Flag) {
|
||||||
|
c.setFlags[f.Name] = true
|
||||||
|
})
|
||||||
|
|
||||||
|
c.flagSet.VisitAll(func(f *flag.Flag) {
|
||||||
|
if _, ok := c.setFlags[f.Name]; ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.setFlags[f.Name] = false
|
||||||
|
})
|
||||||
|
|
||||||
|
// XXX hack to support IsSet for flags with EnvVar
|
||||||
|
//
|
||||||
|
// There isn't an easy way to do this with the current implementation since
|
||||||
|
// whether a flag was set via an environment variable is very difficult to
|
||||||
|
// determine here. Instead, we intend to introduce a backwards incompatible
|
||||||
|
// change in version 2 to add `IsSet` to the Flag interface to push the
|
||||||
|
// responsibility closer to where the information required to determine
|
||||||
|
// whether a flag is set by non-standard means such as environment
|
||||||
|
// variables is avaliable.
|
||||||
|
//
|
||||||
|
// See https://github.com/urfave/cli/issues/294 for additional discussion
|
||||||
|
flags := c.Command.Flags
|
||||||
|
if c.Command.Name == "" { // cannot == Command{} since it contains slice types
|
||||||
|
if c.App != nil {
|
||||||
|
flags = c.App.Flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, f := range flags {
|
||||||
|
eachName(f.GetName(), func(name string) {
|
||||||
|
if isSet, ok := c.setFlags[name]; isSet || !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val := reflect.ValueOf(f)
|
||||||
|
if val.Kind() == reflect.Ptr {
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
envVarValue := val.FieldByName("EnvVar")
|
||||||
|
if !envVarValue.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(envVarValue.String(), func(envVar string) {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if _, ok := syscall.Getenv(envVar); ok {
|
||||||
|
c.setFlags[name] = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.setFlags[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalIsSet determines if the global flag was actually set
|
||||||
|
func (c *Context) GlobalIsSet(name string) bool {
|
||||||
|
ctx := c
|
||||||
|
if ctx.parentContext != nil {
|
||||||
|
ctx = ctx.parentContext
|
||||||
|
}
|
||||||
|
|
||||||
|
for ; ctx != nil; ctx = ctx.parentContext {
|
||||||
|
if ctx.IsSet(name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagNames returns a slice of flag names used in this context.
|
||||||
|
func (c *Context) FlagNames() (names []string) {
|
||||||
|
for _, flag := range c.Command.Flags {
|
||||||
|
name := strings.Split(flag.GetName(), ",")[0]
|
||||||
|
if name == "help" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalFlagNames returns a slice of global flag names used by the app.
|
||||||
|
func (c *Context) GlobalFlagNames() (names []string) {
|
||||||
|
for _, flag := range c.App.Flags {
|
||||||
|
name := strings.Split(flag.GetName(), ",")[0]
|
||||||
|
if name == "help" || name == "version" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent returns the parent context, if any
|
||||||
|
func (c *Context) Parent() *Context {
|
||||||
|
return c.parentContext
|
||||||
|
}
|
||||||
|
|
||||||
|
// value returns the value of the flag coressponding to `name`
|
||||||
|
func (c *Context) value(name string) interface{} {
|
||||||
|
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Args contains apps console arguments
|
||||||
|
type Args []string
|
||||||
|
|
||||||
|
// Args returns the command line arguments associated with the context.
|
||||||
|
func (c *Context) Args() Args {
|
||||||
|
args := Args(c.flagSet.Args())
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
// NArg returns the number of the command line arguments.
|
||||||
|
func (c *Context) NArg() int {
|
||||||
|
return len(c.Args())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the nth argument, or else a blank string
|
||||||
|
func (a Args) Get(n int) string {
|
||||||
|
if len(a) > n {
|
||||||
|
return a[n]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// First returns the first argument, or else a blank string
|
||||||
|
func (a Args) First() string {
|
||||||
|
return a.Get(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tail returns the rest of the arguments (not the first one)
|
||||||
|
// or else an empty string slice
|
||||||
|
func (a Args) Tail() []string {
|
||||||
|
if len(a) >= 2 {
|
||||||
|
return []string(a)[1:]
|
||||||
|
}
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Present checks if there are any arguments present
|
||||||
|
func (a Args) Present() bool {
|
||||||
|
return len(a) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps arguments at the given indexes
|
||||||
|
func (a Args) Swap(from, to int) error {
|
||||||
|
if from >= len(a) || to >= len(a) {
|
||||||
|
return errors.New("index out of range")
|
||||||
|
}
|
||||||
|
a[from], a[to] = a[to], a[from]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func globalContext(ctx *Context) *Context {
|
||||||
|
if ctx == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if ctx.parentContext == nil {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
ctx = ctx.parentContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
|
||||||
|
if ctx.parentContext != nil {
|
||||||
|
ctx = ctx.parentContext
|
||||||
|
}
|
||||||
|
for ; ctx != nil; ctx = ctx.parentContext {
|
||||||
|
if f := ctx.flagSet.Lookup(name); f != nil {
|
||||||
|
return ctx.flagSet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
|
||||||
|
switch ff.Value.(type) {
|
||||||
|
case *StringSlice:
|
||||||
|
default:
|
||||||
|
set.Set(name, ff.Value.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
||||||
|
visited := make(map[string]bool)
|
||||||
|
set.Visit(func(f *flag.Flag) {
|
||||||
|
visited[f.Name] = true
|
||||||
|
})
|
||||||
|
for _, f := range flags {
|
||||||
|
parts := strings.Split(f.GetName(), ",")
|
||||||
|
if len(parts) == 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var ff *flag.Flag
|
||||||
|
for _, name := range parts {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
if visited[name] {
|
||||||
|
if ff != nil {
|
||||||
|
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
|
||||||
|
}
|
||||||
|
ff = set.Lookup(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ff == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, name := range parts {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
if !visited[name] {
|
||||||
|
copyFlag(name, ff, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
115
vendor/github.com/urfave/cli/errors.go
generated
vendored
Normal file
115
vendor/github.com/urfave/cli/errors.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
|
||||||
|
var OsExiter = os.Exit
|
||||||
|
|
||||||
|
// ErrWriter is used to write errors to the user. This can be anything
|
||||||
|
// implementing the io.Writer interface and defaults to os.Stderr.
|
||||||
|
var ErrWriter io.Writer = os.Stderr
|
||||||
|
|
||||||
|
// MultiError is an error that wraps multiple errors.
|
||||||
|
type MultiError struct {
|
||||||
|
Errors []error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMultiError creates a new MultiError. Pass in one or more errors.
|
||||||
|
func NewMultiError(err ...error) MultiError {
|
||||||
|
return MultiError{Errors: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (m MultiError) Error() string {
|
||||||
|
errs := make([]string, len(m.Errors))
|
||||||
|
for i, err := range m.Errors {
|
||||||
|
errs[i] = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(errs, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorFormatter interface {
|
||||||
|
Format(s fmt.State, verb rune)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
|
||||||
|
// code
|
||||||
|
type ExitCoder interface {
|
||||||
|
error
|
||||||
|
ExitCode() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
|
||||||
|
type ExitError struct {
|
||||||
|
exitCode int
|
||||||
|
message interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewExitError makes a new *ExitError
|
||||||
|
func NewExitError(message interface{}, exitCode int) *ExitError {
|
||||||
|
return &ExitError{
|
||||||
|
exitCode: exitCode,
|
||||||
|
message: message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the string message, fulfilling the interface required by
|
||||||
|
// `error`
|
||||||
|
func (ee *ExitError) Error() string {
|
||||||
|
return fmt.Sprintf("%v", ee.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExitCode returns the exit code, fulfilling the interface required by
|
||||||
|
// `ExitCoder`
|
||||||
|
func (ee *ExitError) ExitCode() int {
|
||||||
|
return ee.exitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
|
||||||
|
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
|
||||||
|
// given exit code. If the given error is a MultiError, then this func is
|
||||||
|
// called on all members of the Errors slice and calls OsExiter with the last exit code.
|
||||||
|
func HandleExitCoder(err error) {
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if exitErr, ok := err.(ExitCoder); ok {
|
||||||
|
if err.Error() != "" {
|
||||||
|
if _, ok := exitErr.(ErrorFormatter); ok {
|
||||||
|
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(ErrWriter, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OsExiter(exitErr.ExitCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if multiErr, ok := err.(MultiError); ok {
|
||||||
|
code := handleMultiError(multiErr)
|
||||||
|
OsExiter(code)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMultiError(multiErr MultiError) int {
|
||||||
|
code := 1
|
||||||
|
for _, merr := range multiErr.Errors {
|
||||||
|
if multiErr2, ok := merr.(MultiError); ok {
|
||||||
|
code = handleMultiError(multiErr2)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(ErrWriter, merr)
|
||||||
|
if exitErr, ok := merr.(ExitCoder); ok {
|
||||||
|
code = exitErr.ExitCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code
|
||||||
|
}
|
||||||
93
vendor/github.com/urfave/cli/flag-types.json
generated
vendored
Normal file
93
vendor/github.com/urfave/cli/flag-types.json
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Bool",
|
||||||
|
"type": "bool",
|
||||||
|
"value": false,
|
||||||
|
"context_default": "false",
|
||||||
|
"parser": "strconv.ParseBool(f.Value.String())"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "BoolT",
|
||||||
|
"type": "bool",
|
||||||
|
"value": false,
|
||||||
|
"doctail": " that is true by default",
|
||||||
|
"context_default": "false",
|
||||||
|
"parser": "strconv.ParseBool(f.Value.String())"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Duration",
|
||||||
|
"type": "time.Duration",
|
||||||
|
"doctail": " (see https://golang.org/pkg/time/#ParseDuration)",
|
||||||
|
"context_default": "0",
|
||||||
|
"parser": "time.ParseDuration(f.Value.String())"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Float64",
|
||||||
|
"type": "float64",
|
||||||
|
"context_default": "0",
|
||||||
|
"parser": "strconv.ParseFloat(f.Value.String(), 64)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Generic",
|
||||||
|
"type": "Generic",
|
||||||
|
"dest": false,
|
||||||
|
"context_default": "nil",
|
||||||
|
"context_type": "interface{}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Int64",
|
||||||
|
"type": "int64",
|
||||||
|
"context_default": "0",
|
||||||
|
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Int",
|
||||||
|
"type": "int",
|
||||||
|
"context_default": "0",
|
||||||
|
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
|
||||||
|
"parser_cast": "int(parsed)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "IntSlice",
|
||||||
|
"type": "*IntSlice",
|
||||||
|
"dest": false,
|
||||||
|
"context_default": "nil",
|
||||||
|
"context_type": "[]int",
|
||||||
|
"parser": "(f.Value.(*IntSlice)).Value(), error(nil)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Int64Slice",
|
||||||
|
"type": "*Int64Slice",
|
||||||
|
"dest": false,
|
||||||
|
"context_default": "nil",
|
||||||
|
"context_type": "[]int64",
|
||||||
|
"parser": "(f.Value.(*Int64Slice)).Value(), error(nil)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "String",
|
||||||
|
"type": "string",
|
||||||
|
"context_default": "\"\"",
|
||||||
|
"parser": "f.Value.String(), error(nil)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "StringSlice",
|
||||||
|
"type": "*StringSlice",
|
||||||
|
"dest": false,
|
||||||
|
"context_default": "nil",
|
||||||
|
"context_type": "[]string",
|
||||||
|
"parser": "(f.Value.(*StringSlice)).Value(), error(nil)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Uint64",
|
||||||
|
"type": "uint64",
|
||||||
|
"context_default": "0",
|
||||||
|
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Uint",
|
||||||
|
"type": "uint",
|
||||||
|
"context_default": "0",
|
||||||
|
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
|
||||||
|
"parser_cast": "uint(parsed)"
|
||||||
|
}
|
||||||
|
]
|
||||||
799
vendor/github.com/urfave/cli/flag.go
generated
vendored
Normal file
799
vendor/github.com/urfave/cli/flag.go
generated
vendored
Normal file
@@ -0,0 +1,799 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultPlaceholder = "value"
|
||||||
|
|
||||||
|
// BashCompletionFlag enables bash-completion for all commands and subcommands
|
||||||
|
var BashCompletionFlag Flag = BoolFlag{
|
||||||
|
Name: "generate-bash-completion",
|
||||||
|
Hidden: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// VersionFlag prints the version for the application
|
||||||
|
var VersionFlag Flag = BoolFlag{
|
||||||
|
Name: "version, v",
|
||||||
|
Usage: "print the version",
|
||||||
|
}
|
||||||
|
|
||||||
|
// HelpFlag prints the help for all commands and subcommands
|
||||||
|
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
||||||
|
// unless HideHelp is set to true)
|
||||||
|
var HelpFlag Flag = BoolFlag{
|
||||||
|
Name: "help, h",
|
||||||
|
Usage: "show help",
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagStringer converts a flag definition to a string. This is used by help
|
||||||
|
// to display a flag.
|
||||||
|
var FlagStringer FlagStringFunc = stringifyFlag
|
||||||
|
|
||||||
|
// FlagsByName is a slice of Flag.
|
||||||
|
type FlagsByName []Flag
|
||||||
|
|
||||||
|
func (f FlagsByName) Len() int {
|
||||||
|
return len(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FlagsByName) Less(i, j int) bool {
|
||||||
|
return f[i].GetName() < f[j].GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FlagsByName) Swap(i, j int) {
|
||||||
|
f[i], f[j] = f[j], f[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flag is a common interface related to parsing flags in cli.
|
||||||
|
// For more advanced flag parsing techniques, it is recommended that
|
||||||
|
// this interface be implemented.
|
||||||
|
type Flag interface {
|
||||||
|
fmt.Stringer
|
||||||
|
// Apply Flag settings to the given flag set
|
||||||
|
Apply(*flag.FlagSet)
|
||||||
|
GetName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// errorableFlag is an interface that allows us to return errors during apply
|
||||||
|
// it allows flags defined in this library to return errors in a fashion backwards compatible
|
||||||
|
// TODO remove in v2 and modify the existing Flag interface to return errors
|
||||||
|
type errorableFlag interface {
|
||||||
|
Flag
|
||||||
|
|
||||||
|
ApplyWithError(*flag.FlagSet) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
|
||||||
|
set := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||||
|
|
||||||
|
for _, f := range flags {
|
||||||
|
//TODO remove in v2 when errorableFlag is removed
|
||||||
|
if ef, ok := f.(errorableFlag); ok {
|
||||||
|
if err := ef.ApplyWithError(set); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f.Apply(set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func eachName(longName string, fn func(string)) {
|
||||||
|
parts := strings.Split(longName, ",")
|
||||||
|
for _, name := range parts {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
fn(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic is a generic parseable type identified by a specific flag
|
||||||
|
type Generic interface {
|
||||||
|
Set(value string) error
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply takes the flagset and calls Set on the generic flag with the value
|
||||||
|
// provided by the user for parsing by the flag
|
||||||
|
// Ignores parsing errors
|
||||||
|
func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError takes the flagset and calls Set on the generic flag with the value
|
||||||
|
// provided by the user for parsing by the flag
|
||||||
|
func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
val := f.Value
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
if err := val.Set(envVal); err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
set.Var(f.Value, name, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter
|
||||||
|
type StringSlice []string
|
||||||
|
|
||||||
|
// Set appends the string value to the list of values
|
||||||
|
func (f *StringSlice) Set(value string) error {
|
||||||
|
*f = append(*f, value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value (for usage defaults)
|
||||||
|
func (f *StringSlice) String() string {
|
||||||
|
return fmt.Sprintf("%s", *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the slice of strings set by this flag
|
||||||
|
func (f *StringSlice) Value() []string {
|
||||||
|
return *f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the slice of strings set by this flag
|
||||||
|
func (f *StringSlice) Get() interface{} {
|
||||||
|
return *f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
newVal := &StringSlice{}
|
||||||
|
for _, s := range strings.Split(envVal, ",") {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
if err := newVal.Set(s); err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Value = newVal
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Value == nil {
|
||||||
|
f.Value = &StringSlice{}
|
||||||
|
}
|
||||||
|
set.Var(f.Value, name, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
||||||
|
type IntSlice []int
|
||||||
|
|
||||||
|
// Set parses the value into an integer and appends it to the list of values
|
||||||
|
func (f *IntSlice) Set(value string) error {
|
||||||
|
tmp, err := strconv.Atoi(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*f = append(*f, tmp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value (for usage defaults)
|
||||||
|
func (f *IntSlice) String() string {
|
||||||
|
return fmt.Sprintf("%#v", *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the slice of ints set by this flag
|
||||||
|
func (f *IntSlice) Value() []int {
|
||||||
|
return *f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the slice of ints set by this flag
|
||||||
|
func (f *IntSlice) Get() interface{} {
|
||||||
|
return *f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
newVal := &IntSlice{}
|
||||||
|
for _, s := range strings.Split(envVal, ",") {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
if err := newVal.Set(s); err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Value = newVal
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Value == nil {
|
||||||
|
f.Value = &IntSlice{}
|
||||||
|
}
|
||||||
|
set.Var(f.Value, name, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
||||||
|
type Int64Slice []int64
|
||||||
|
|
||||||
|
// Set parses the value into an integer and appends it to the list of values
|
||||||
|
func (f *Int64Slice) Set(value string) error {
|
||||||
|
tmp, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*f = append(*f, tmp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value (for usage defaults)
|
||||||
|
func (f *Int64Slice) String() string {
|
||||||
|
return fmt.Sprintf("%#v", *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the slice of ints set by this flag
|
||||||
|
func (f *Int64Slice) Value() []int64 {
|
||||||
|
return *f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the slice of ints set by this flag
|
||||||
|
func (f *Int64Slice) Get() interface{} {
|
||||||
|
return *f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
newVal := &Int64Slice{}
|
||||||
|
for _, s := range strings.Split(envVal, ",") {
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
if err := newVal.Set(s); err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Value = newVal
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Value == nil {
|
||||||
|
f.Value = &Int64Slice{}
|
||||||
|
}
|
||||||
|
set.Var(f.Value, name, f.Usage)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
val := false
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
if envVal == "" {
|
||||||
|
val = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
envValBool, err := strconv.ParseBool(envVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val = envValBool
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.BoolVar(f.Destination, name, val, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Bool(name, val, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
val := true
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
if envVal == "" {
|
||||||
|
val = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
envValBool, err := strconv.ParseBool(envVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val = envValBool
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.BoolVar(f.Destination, name, val, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Bool(name, val, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
f.Value = envVal
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.StringVar(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.String(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
f.Value = int(envValInt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.IntVar(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Int(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f Int64Flag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Value = envValInt
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.Int64Var(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Int64(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f UintFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f UintFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Value = uint(envValInt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.UintVar(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Uint(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Value = uint64(envValInt)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Uint64(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
envValDuration, err := time.ParseDuration(envVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Value = envValDuration
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.DurationVar(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Duration(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
|
func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
|
if f.EnvVar != "" {
|
||||||
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
|
envVar = strings.TrimSpace(envVar)
|
||||||
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
|
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Value = float64(envValFloat)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eachName(f.Name, func(name string) {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.Float64Var(f.Destination, name, f.Value, f.Usage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
set.Float64(name, f.Value, f.Usage)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func visibleFlags(fl []Flag) []Flag {
|
||||||
|
visible := []Flag{}
|
||||||
|
for _, flag := range fl {
|
||||||
|
field := flagValue(flag).FieldByName("Hidden")
|
||||||
|
if !field.IsValid() || !field.Bool() {
|
||||||
|
visible = append(visible, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return visible
|
||||||
|
}
|
||||||
|
|
||||||
|
func prefixFor(name string) (prefix string) {
|
||||||
|
if len(name) == 1 {
|
||||||
|
prefix = "-"
|
||||||
|
} else {
|
||||||
|
prefix = "--"
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the placeholder, if any, and the unquoted usage string.
|
||||||
|
func unquoteUsage(usage string) (string, string) {
|
||||||
|
for i := 0; i < len(usage); i++ {
|
||||||
|
if usage[i] == '`' {
|
||||||
|
for j := i + 1; j < len(usage); j++ {
|
||||||
|
if usage[j] == '`' {
|
||||||
|
name := usage[i+1 : j]
|
||||||
|
usage = usage[:i] + name + usage[j+1:]
|
||||||
|
return name, usage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", usage
|
||||||
|
}
|
||||||
|
|
||||||
|
func prefixedNames(fullName, placeholder string) string {
|
||||||
|
var prefixed string
|
||||||
|
parts := strings.Split(fullName, ",")
|
||||||
|
for i, name := range parts {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
prefixed += prefixFor(name) + name
|
||||||
|
if placeholder != "" {
|
||||||
|
prefixed += " " + placeholder
|
||||||
|
}
|
||||||
|
if i < len(parts)-1 {
|
||||||
|
prefixed += ", "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prefixed
|
||||||
|
}
|
||||||
|
|
||||||
|
func withEnvHint(envVar, str string) string {
|
||||||
|
envText := ""
|
||||||
|
if envVar != "" {
|
||||||
|
prefix := "$"
|
||||||
|
suffix := ""
|
||||||
|
sep := ", $"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
prefix = "%"
|
||||||
|
suffix = "%"
|
||||||
|
sep = "%, %"
|
||||||
|
}
|
||||||
|
envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(strings.Split(envVar, ","), sep), suffix)
|
||||||
|
}
|
||||||
|
return str + envText
|
||||||
|
}
|
||||||
|
|
||||||
|
func flagValue(f Flag) reflect.Value {
|
||||||
|
fv := reflect.ValueOf(f)
|
||||||
|
for fv.Kind() == reflect.Ptr {
|
||||||
|
fv = reflect.Indirect(fv)
|
||||||
|
}
|
||||||
|
return fv
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringifyFlag(f Flag) string {
|
||||||
|
fv := flagValue(f)
|
||||||
|
|
||||||
|
switch f.(type) {
|
||||||
|
case IntSliceFlag:
|
||||||
|
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||||
|
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||||
|
case Int64SliceFlag:
|
||||||
|
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||||
|
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
||||||
|
case StringSliceFlag:
|
||||||
|
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||||
|
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||||
|
}
|
||||||
|
|
||||||
|
placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
|
||||||
|
|
||||||
|
needsPlaceholder := false
|
||||||
|
defaultValueString := ""
|
||||||
|
|
||||||
|
if val := fv.FieldByName("Value"); val.IsValid() {
|
||||||
|
needsPlaceholder = true
|
||||||
|
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
||||||
|
|
||||||
|
if val.Kind() == reflect.String && val.String() != "" {
|
||||||
|
defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if defaultValueString == " (default: )" {
|
||||||
|
defaultValueString = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if needsPlaceholder && placeholder == "" {
|
||||||
|
placeholder = defaultPlaceholder
|
||||||
|
}
|
||||||
|
|
||||||
|
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
|
||||||
|
|
||||||
|
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||||
|
fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringifyIntSliceFlag(f IntSliceFlag) string {
|
||||||
|
defaultVals := []string{}
|
||||||
|
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||||
|
for _, i := range f.Value.Value() {
|
||||||
|
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
|
||||||
|
defaultVals := []string{}
|
||||||
|
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||||
|
for _, i := range f.Value.Value() {
|
||||||
|
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringifyStringSliceFlag(f StringSliceFlag) string {
|
||||||
|
defaultVals := []string{}
|
||||||
|
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||||
|
for _, s := range f.Value.Value() {
|
||||||
|
if len(s) > 0 {
|
||||||
|
defaultVals = append(defaultVals, fmt.Sprintf("%q", s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringifySliceFlag(usage, name string, defaultVals []string) string {
|
||||||
|
placeholder, usage := unquoteUsage(usage)
|
||||||
|
if placeholder == "" {
|
||||||
|
placeholder = defaultPlaceholder
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultVal := ""
|
||||||
|
if len(defaultVals) > 0 {
|
||||||
|
defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
|
||||||
|
return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault)
|
||||||
|
}
|
||||||
627
vendor/github.com/urfave/cli/flag_generated.go
generated
vendored
Normal file
627
vendor/github.com/urfave/cli/flag_generated.go
generated
vendored
Normal file
@@ -0,0 +1,627 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WARNING: This file is generated!
|
||||||
|
|
||||||
|
// BoolFlag is a flag with type bool
|
||||||
|
type BoolFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Destination *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f BoolFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f BoolFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool looks up the value of a local BoolFlag, returns
|
||||||
|
// false if not found
|
||||||
|
func (c *Context) Bool(name string) bool {
|
||||||
|
return lookupBool(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalBool looks up the value of a global BoolFlag, returns
|
||||||
|
// false if not found
|
||||||
|
func (c *Context) GlobalBool(name string) bool {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupBool(name, fs)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupBool(name string, set *flag.FlagSet) bool {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseBool(f.Value.String())
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolTFlag is a flag with type bool that is true by default
|
||||||
|
type BoolTFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Destination *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f BoolTFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f BoolTFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolT looks up the value of a local BoolTFlag, returns
|
||||||
|
// false if not found
|
||||||
|
func (c *Context) BoolT(name string) bool {
|
||||||
|
return lookupBoolT(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalBoolT looks up the value of a global BoolTFlag, returns
|
||||||
|
// false if not found
|
||||||
|
func (c *Context) GlobalBoolT(name string) bool {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupBoolT(name, fs)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupBoolT(name string, set *flag.FlagSet) bool {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseBool(f.Value.String())
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
|
||||||
|
type DurationFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value time.Duration
|
||||||
|
Destination *time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f DurationFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f DurationFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration looks up the value of a local DurationFlag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) Duration(name string) time.Duration {
|
||||||
|
return lookupDuration(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalDuration looks up the value of a global DurationFlag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) GlobalDuration(name string) time.Duration {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupDuration(name, fs)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := time.ParseDuration(f.Value.String())
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Flag is a flag with type float64
|
||||||
|
type Float64Flag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value float64
|
||||||
|
Destination *float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f Float64Flag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f Float64Flag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 looks up the value of a local Float64Flag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) Float64(name string) float64 {
|
||||||
|
return lookupFloat64(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalFloat64 looks up the value of a global Float64Flag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) GlobalFloat64(name string) float64 {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupFloat64(name, fs)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupFloat64(name string, set *flag.FlagSet) float64 {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseFloat(f.Value.String(), 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericFlag is a flag with type Generic
|
||||||
|
type GenericFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value Generic
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f GenericFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f GenericFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic looks up the value of a local GenericFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) Generic(name string) interface{} {
|
||||||
|
return lookupGeneric(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalGeneric looks up the value of a global GenericFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) GlobalGeneric(name string) interface{} {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupGeneric(name, fs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := f.Value, error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Flag is a flag with type int64
|
||||||
|
type Int64Flag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value int64
|
||||||
|
Destination *int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f Int64Flag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f Int64Flag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 looks up the value of a local Int64Flag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) Int64(name string) int64 {
|
||||||
|
return lookupInt64(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalInt64 looks up the value of a global Int64Flag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) GlobalInt64(name string) int64 {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupInt64(name, fs)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupInt64(name string, set *flag.FlagSet) int64 {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntFlag is a flag with type int
|
||||||
|
type IntFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value int
|
||||||
|
Destination *int
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f IntFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f IntFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int looks up the value of a local IntFlag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) Int(name string) int {
|
||||||
|
return lookupInt(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalInt looks up the value of a global IntFlag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) GlobalInt(name string) int {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupInt(name, fs)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupInt(name string, set *flag.FlagSet) int {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return int(parsed)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSliceFlag is a flag with type *IntSlice
|
||||||
|
type IntSliceFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value *IntSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f IntSliceFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f IntSliceFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntSlice looks up the value of a local IntSliceFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) IntSlice(name string) []int {
|
||||||
|
return lookupIntSlice(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalIntSlice looks up the value of a global IntSliceFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) GlobalIntSlice(name string) []int {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupIntSlice(name, fs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupIntSlice(name string, set *flag.FlagSet) []int {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := (f.Value.(*IntSlice)).Value(), error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceFlag is a flag with type *Int64Slice
|
||||||
|
type Int64SliceFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value *Int64Slice
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f Int64SliceFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f Int64SliceFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) Int64Slice(name string) []int64 {
|
||||||
|
return lookupInt64Slice(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) GlobalInt64Slice(name string) []int64 {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupInt64Slice(name, fs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringFlag is a flag with type string
|
||||||
|
type StringFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value string
|
||||||
|
Destination *string
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f StringFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f StringFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// String looks up the value of a local StringFlag, returns
|
||||||
|
// "" if not found
|
||||||
|
func (c *Context) String(name string) string {
|
||||||
|
return lookupString(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalString looks up the value of a global StringFlag, returns
|
||||||
|
// "" if not found
|
||||||
|
func (c *Context) GlobalString(name string) string {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupString(name, fs)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupString(name string, set *flag.FlagSet) string {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := f.Value.String(), error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSliceFlag is a flag with type *StringSlice
|
||||||
|
type StringSliceFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value *StringSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f StringSliceFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f StringSliceFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice looks up the value of a local StringSliceFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) StringSlice(name string) []string {
|
||||||
|
return lookupStringSlice(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalStringSlice looks up the value of a global StringSliceFlag, returns
|
||||||
|
// nil if not found
|
||||||
|
func (c *Context) GlobalStringSlice(name string) []string {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupStringSlice(name, fs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupStringSlice(name string, set *flag.FlagSet) []string {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := (f.Value.(*StringSlice)).Value(), error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64Flag is a flag with type uint64
|
||||||
|
type Uint64Flag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value uint64
|
||||||
|
Destination *uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f Uint64Flag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f Uint64Flag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 looks up the value of a local Uint64Flag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) Uint64(name string) uint64 {
|
||||||
|
return lookupUint64(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalUint64 looks up the value of a global Uint64Flag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) GlobalUint64(name string) uint64 {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupUint64(name, fs)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupUint64(name string, set *flag.FlagSet) uint64 {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintFlag is a flag with type uint
|
||||||
|
type UintFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
Value uint
|
||||||
|
Destination *uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f UintFlag) String() string {
|
||||||
|
return FlagStringer(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f UintFlag) GetName() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint looks up the value of a local UintFlag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) Uint(name string) uint {
|
||||||
|
return lookupUint(name, c.flagSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalUint looks up the value of a global UintFlag, returns
|
||||||
|
// 0 if not found
|
||||||
|
func (c *Context) GlobalUint(name string) uint {
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||||
|
return lookupUint(name, fs)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupUint(name string, set *flag.FlagSet) uint {
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {
|
||||||
|
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return uint(parsed)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
28
vendor/github.com/urfave/cli/funcs.go
generated
vendored
Normal file
28
vendor/github.com/urfave/cli/funcs.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
// BashCompleteFunc is an action to execute when the bash-completion flag is set
|
||||||
|
type BashCompleteFunc func(*Context)
|
||||||
|
|
||||||
|
// BeforeFunc is an action to execute before any subcommands are run, but after
|
||||||
|
// the context is ready if a non-nil error is returned, no subcommands are run
|
||||||
|
type BeforeFunc func(*Context) error
|
||||||
|
|
||||||
|
// AfterFunc is an action to execute after any subcommands are run, but after the
|
||||||
|
// subcommand has finished it is run even if Action() panics
|
||||||
|
type AfterFunc func(*Context) error
|
||||||
|
|
||||||
|
// ActionFunc is the action to execute when no subcommands are specified
|
||||||
|
type ActionFunc func(*Context) error
|
||||||
|
|
||||||
|
// CommandNotFoundFunc is executed if the proper command cannot be found
|
||||||
|
type CommandNotFoundFunc func(*Context, string)
|
||||||
|
|
||||||
|
// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
|
||||||
|
// customized usage error messages. This function is able to replace the
|
||||||
|
// original error messages. If this function is not set, the "Incorrect usage"
|
||||||
|
// is displayed and the execution is interrupted.
|
||||||
|
type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
|
||||||
|
|
||||||
|
// FlagStringFunc is used by the help generation to display a flag, which is
|
||||||
|
// expected to be a single line.
|
||||||
|
type FlagStringFunc func(Flag) string
|
||||||
255
vendor/github.com/urfave/cli/generate-flag-types
generated
vendored
Normal file
255
vendor/github.com/urfave/cli/generate-flag-types
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
The flag types that ship with the cli library have many things in common, and
|
||||||
|
so we can take advantage of the `go generate` command to create much of the
|
||||||
|
source code from a list of definitions. These definitions attempt to cover
|
||||||
|
the parts that vary between flag types, and should evolve as needed.
|
||||||
|
|
||||||
|
An example of the minimum definition needed is:
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "SomeType",
|
||||||
|
"type": "sometype",
|
||||||
|
"context_default": "nil"
|
||||||
|
}
|
||||||
|
|
||||||
|
In this example, the code generated for the `cli` package will include a type
|
||||||
|
named `SomeTypeFlag` that is expected to wrap a value of type `sometype`.
|
||||||
|
Fetching values by name via `*cli.Context` will default to a value of `nil`.
|
||||||
|
|
||||||
|
A more complete, albeit somewhat redundant, example showing all available
|
||||||
|
definition keys is:
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "VeryMuchType",
|
||||||
|
"type": "*VeryMuchType",
|
||||||
|
"value": true,
|
||||||
|
"dest": false,
|
||||||
|
"doctail": " which really only wraps a []float64, oh well!",
|
||||||
|
"context_type": "[]float64",
|
||||||
|
"context_default": "nil",
|
||||||
|
"parser": "parseVeryMuchType(f.Value.String())",
|
||||||
|
"parser_cast": "[]float64(parsed)"
|
||||||
|
}
|
||||||
|
|
||||||
|
The meaning of each field is as follows:
|
||||||
|
|
||||||
|
name (string) - The type "name", which will be suffixed with
|
||||||
|
`Flag` when generating the type definition
|
||||||
|
for `cli` and the wrapper type for `altsrc`
|
||||||
|
type (string) - The type that the generated `Flag` type for `cli`
|
||||||
|
is expected to "contain" as its `.Value` member
|
||||||
|
value (bool) - Should the generated `cli` type have a `Value`
|
||||||
|
member?
|
||||||
|
dest (bool) - Should the generated `cli` type support a
|
||||||
|
destination pointer?
|
||||||
|
doctail (string) - Additional docs for the `cli` flag type comment
|
||||||
|
context_type (string) - The literal type used in the `*cli.Context`
|
||||||
|
reader func signature
|
||||||
|
context_default (string) - The literal value used as the default by the
|
||||||
|
`*cli.Context` reader funcs when no value is
|
||||||
|
present
|
||||||
|
parser (string) - Literal code used to parse the flag `f`,
|
||||||
|
expected to have a return signature of
|
||||||
|
(value, error)
|
||||||
|
parser_cast (string) - Literal code used to cast the `parsed` value
|
||||||
|
returned from the `parser` code
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
|
class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter,
|
||||||
|
argparse.RawDescriptionHelpFormatter):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def main(sysargs=sys.argv[:]):
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Generate flag type code!',
|
||||||
|
formatter_class=_FancyFormatter)
|
||||||
|
parser.add_argument(
|
||||||
|
'package',
|
||||||
|
type=str, default='cli', choices=_WRITEFUNCS.keys(),
|
||||||
|
help='Package for which flag types will be generated'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-i', '--in-json',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
default=sys.stdin,
|
||||||
|
help='Input JSON file which defines each type to be generated'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-o', '--out-go',
|
||||||
|
type=argparse.FileType('w'),
|
||||||
|
default=sys.stdout,
|
||||||
|
help='Output file/stream to which generated source will be written'
|
||||||
|
)
|
||||||
|
parser.epilog = __doc__
|
||||||
|
|
||||||
|
args = parser.parse_args(sysargs[1:])
|
||||||
|
_generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_flag_types(writefunc, output_go, input_json):
|
||||||
|
types = json.load(input_json)
|
||||||
|
|
||||||
|
tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False)
|
||||||
|
writefunc(tmp, types)
|
||||||
|
tmp.close()
|
||||||
|
|
||||||
|
new_content = subprocess.check_output(
|
||||||
|
['goimports', tmp.name]
|
||||||
|
).decode('utf-8')
|
||||||
|
|
||||||
|
print(new_content, file=output_go, end='')
|
||||||
|
output_go.flush()
|
||||||
|
os.remove(tmp.name)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_typedef_defaults(typedef):
|
||||||
|
typedef.setdefault('doctail', '')
|
||||||
|
typedef.setdefault('context_type', typedef['type'])
|
||||||
|
typedef.setdefault('dest', True)
|
||||||
|
typedef.setdefault('value', True)
|
||||||
|
typedef.setdefault('parser', 'f.Value, error(nil)')
|
||||||
|
typedef.setdefault('parser_cast', 'parsed')
|
||||||
|
|
||||||
|
|
||||||
|
def _write_cli_flag_types(outfile, types):
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
package cli
|
||||||
|
|
||||||
|
// WARNING: This file is generated!
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
for typedef in types:
|
||||||
|
_set_typedef_defaults(typedef)
|
||||||
|
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
// {name}Flag is a flag with type {type}{doctail}
|
||||||
|
type {name}Flag struct {{
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
EnvVar string
|
||||||
|
Hidden bool
|
||||||
|
""".format(**typedef))
|
||||||
|
|
||||||
|
if typedef['value']:
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
Value {type}
|
||||||
|
""".format(**typedef))
|
||||||
|
|
||||||
|
if typedef['dest']:
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
Destination *{type}
|
||||||
|
""".format(**typedef))
|
||||||
|
|
||||||
|
_fwrite(outfile, "\n}\n\n")
|
||||||
|
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
// String returns a readable representation of this value
|
||||||
|
// (for usage defaults)
|
||||||
|
func (f {name}Flag) String() string {{
|
||||||
|
return FlagStringer(f)
|
||||||
|
}}
|
||||||
|
|
||||||
|
// GetName returns the name of the flag
|
||||||
|
func (f {name}Flag) GetName() string {{
|
||||||
|
return f.Name
|
||||||
|
}}
|
||||||
|
|
||||||
|
// {name} looks up the value of a local {name}Flag, returns
|
||||||
|
// {context_default} if not found
|
||||||
|
func (c *Context) {name}(name string) {context_type} {{
|
||||||
|
return lookup{name}(name, c.flagSet)
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Global{name} looks up the value of a global {name}Flag, returns
|
||||||
|
// {context_default} if not found
|
||||||
|
func (c *Context) Global{name}(name string) {context_type} {{
|
||||||
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {{
|
||||||
|
return lookup{name}(name, fs)
|
||||||
|
}}
|
||||||
|
return {context_default}
|
||||||
|
}}
|
||||||
|
|
||||||
|
func lookup{name}(name string, set *flag.FlagSet) {context_type} {{
|
||||||
|
f := set.Lookup(name)
|
||||||
|
if f != nil {{
|
||||||
|
parsed, err := {parser}
|
||||||
|
if err != nil {{
|
||||||
|
return {context_default}
|
||||||
|
}}
|
||||||
|
return {parser_cast}
|
||||||
|
}}
|
||||||
|
return {context_default}
|
||||||
|
}}
|
||||||
|
""".format(**typedef))
|
||||||
|
|
||||||
|
|
||||||
|
def _write_altsrc_flag_types(outfile, types):
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
package altsrc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/urfave/cli.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WARNING: This file is generated!
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
for typedef in types:
|
||||||
|
_set_typedef_defaults(typedef)
|
||||||
|
|
||||||
|
_fwrite(outfile, """\
|
||||||
|
// {name}Flag is the flag type that wraps cli.{name}Flag to allow
|
||||||
|
// for other values to be specified
|
||||||
|
type {name}Flag struct {{
|
||||||
|
cli.{name}Flag
|
||||||
|
set *flag.FlagSet
|
||||||
|
}}
|
||||||
|
|
||||||
|
// New{name}Flag creates a new {name}Flag
|
||||||
|
func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{
|
||||||
|
return &{name}Flag{{{name}Flag: fl, set: nil}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Apply saves the flagSet for later usage calls, then calls the
|
||||||
|
// wrapped {name}Flag.Apply
|
||||||
|
func (f *{name}Flag) Apply(set *flag.FlagSet) {{
|
||||||
|
f.set = set
|
||||||
|
f.{name}Flag.Apply(set)
|
||||||
|
}}
|
||||||
|
|
||||||
|
// ApplyWithError saves the flagSet for later usage calls, then calls the
|
||||||
|
// wrapped {name}Flag.ApplyWithError
|
||||||
|
func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{
|
||||||
|
f.set = set
|
||||||
|
return f.{name}Flag.ApplyWithError(set)
|
||||||
|
}}
|
||||||
|
""".format(**typedef))
|
||||||
|
|
||||||
|
|
||||||
|
def _fwrite(outfile, text):
|
||||||
|
print(textwrap.dedent(text), end='', file=outfile)
|
||||||
|
|
||||||
|
|
||||||
|
_WRITEFUNCS = {
|
||||||
|
'cli': _write_cli_flag_types,
|
||||||
|
'altsrc': _write_altsrc_flag_types
|
||||||
|
}
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
338
vendor/github.com/urfave/cli/help.go
generated
vendored
Normal file
338
vendor/github.com/urfave/cli/help.go
generated
vendored
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/tabwriter"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AppHelpTemplate is the text template for the Default help topic.
|
||||||
|
// cli.go uses text/template to render templates. You can
|
||||||
|
// render custom help text by setting this variable.
|
||||||
|
var AppHelpTemplate = `NAME:
|
||||||
|
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
||||||
|
|
||||||
|
VERSION:
|
||||||
|
{{.Version}}{{end}}{{end}}{{if .Description}}
|
||||||
|
|
||||||
|
DESCRIPTION:
|
||||||
|
{{.Description}}{{end}}{{if len .Authors}}
|
||||||
|
|
||||||
|
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||||
|
{{range $index, $author := .Authors}}{{if $index}}
|
||||||
|
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
||||||
|
|
||||||
|
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||||
|
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||||
|
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||||
|
|
||||||
|
GLOBAL OPTIONS:
|
||||||
|
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
||||||
|
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
|
||||||
|
|
||||||
|
COPYRIGHT:
|
||||||
|
{{.Copyright}}{{end}}
|
||||||
|
`
|
||||||
|
|
||||||
|
// CommandHelpTemplate is the text template for the command help topic.
|
||||||
|
// cli.go uses text/template to render templates. You can
|
||||||
|
// render custom help text by setting this variable.
|
||||||
|
var CommandHelpTemplate = `NAME:
|
||||||
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
|
||||||
|
|
||||||
|
CATEGORY:
|
||||||
|
{{.Category}}{{end}}{{if .Description}}
|
||||||
|
|
||||||
|
DESCRIPTION:
|
||||||
|
{{.Description}}{{end}}{{if .VisibleFlags}}
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
{{range .VisibleFlags}}{{.}}
|
||||||
|
{{end}}{{end}}
|
||||||
|
`
|
||||||
|
|
||||||
|
// SubcommandHelpTemplate is the text template for the subcommand help topic.
|
||||||
|
// cli.go uses text/template to render templates. You can
|
||||||
|
// render custom help text by setting this variable.
|
||||||
|
var SubcommandHelpTemplate = `NAME:
|
||||||
|
{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
|
||||||
|
|
||||||
|
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||||
|
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||||
|
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
|
||||||
|
{{end}}{{if .VisibleFlags}}
|
||||||
|
OPTIONS:
|
||||||
|
{{range .VisibleFlags}}{{.}}
|
||||||
|
{{end}}{{end}}
|
||||||
|
`
|
||||||
|
|
||||||
|
var helpCommand = Command{
|
||||||
|
Name: "help",
|
||||||
|
Aliases: []string{"h"},
|
||||||
|
Usage: "Shows a list of commands or help for one command",
|
||||||
|
ArgsUsage: "[command]",
|
||||||
|
Action: func(c *Context) error {
|
||||||
|
args := c.Args()
|
||||||
|
if args.Present() {
|
||||||
|
return ShowCommandHelp(c, args.First())
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowAppHelp(c)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var helpSubcommand = Command{
|
||||||
|
Name: "help",
|
||||||
|
Aliases: []string{"h"},
|
||||||
|
Usage: "Shows a list of commands or help for one command",
|
||||||
|
ArgsUsage: "[command]",
|
||||||
|
Action: func(c *Context) error {
|
||||||
|
args := c.Args()
|
||||||
|
if args.Present() {
|
||||||
|
return ShowCommandHelp(c, args.First())
|
||||||
|
}
|
||||||
|
|
||||||
|
return ShowSubcommandHelp(c)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints help for the App or Command
|
||||||
|
type helpPrinter func(w io.Writer, templ string, data interface{})
|
||||||
|
|
||||||
|
// Prints help for the App or Command with custom template function.
|
||||||
|
type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{})
|
||||||
|
|
||||||
|
// HelpPrinter is a function that writes the help output. If not set a default
|
||||||
|
// is used. The function signature is:
|
||||||
|
// func(w io.Writer, templ string, data interface{})
|
||||||
|
var HelpPrinter helpPrinter = printHelp
|
||||||
|
|
||||||
|
// HelpPrinterCustom is same as HelpPrinter but
|
||||||
|
// takes a custom function for template function map.
|
||||||
|
var HelpPrinterCustom helpPrinterCustom = printHelpCustom
|
||||||
|
|
||||||
|
// VersionPrinter prints the version for the App
|
||||||
|
var VersionPrinter = printVersion
|
||||||
|
|
||||||
|
// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code.
|
||||||
|
func ShowAppHelpAndExit(c *Context, exitCode int) {
|
||||||
|
ShowAppHelp(c)
|
||||||
|
os.Exit(exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowAppHelp is an action that displays the help.
|
||||||
|
func ShowAppHelp(c *Context) (err error) {
|
||||||
|
if c.App.CustomAppHelpTemplate == "" {
|
||||||
|
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
customAppData := func() map[string]interface{} {
|
||||||
|
if c.App.ExtraInfo == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return map[string]interface{}{
|
||||||
|
"ExtraInfo": c.App.ExtraInfo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HelpPrinterCustom(c.App.Writer, c.App.CustomAppHelpTemplate, c.App, customAppData())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||||
|
func DefaultAppComplete(c *Context) {
|
||||||
|
for _, command := range c.App.Commands {
|
||||||
|
if command.Hidden {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, name := range command.Names() {
|
||||||
|
fmt.Fprintln(c.App.Writer, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowCommandHelpAndExit - exits with code after showing help
|
||||||
|
func ShowCommandHelpAndExit(c *Context, command string, code int) {
|
||||||
|
ShowCommandHelp(c, command)
|
||||||
|
os.Exit(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowCommandHelp prints help for the given command
|
||||||
|
func ShowCommandHelp(ctx *Context, command string) error {
|
||||||
|
// show the subcommand help for a command with subcommands
|
||||||
|
if command == "" {
|
||||||
|
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range ctx.App.Commands {
|
||||||
|
if c.HasName(command) {
|
||||||
|
if c.CustomHelpTemplate != "" {
|
||||||
|
HelpPrinterCustom(ctx.App.Writer, c.CustomHelpTemplate, c, nil)
|
||||||
|
} else {
|
||||||
|
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.App.CommandNotFound == nil {
|
||||||
|
return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.App.CommandNotFound(ctx, command)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowSubcommandHelp prints help for the given subcommand
|
||||||
|
func ShowSubcommandHelp(c *Context) error {
|
||||||
|
return ShowCommandHelp(c, c.Command.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowVersion prints the version number of the App
|
||||||
|
func ShowVersion(c *Context) {
|
||||||
|
VersionPrinter(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printVersion(c *Context) {
|
||||||
|
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowCompletions prints the lists of commands within a given context
|
||||||
|
func ShowCompletions(c *Context) {
|
||||||
|
a := c.App
|
||||||
|
if a != nil && a.BashComplete != nil {
|
||||||
|
a.BashComplete(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowCommandCompletions prints the custom completions for a given command
|
||||||
|
func ShowCommandCompletions(ctx *Context, command string) {
|
||||||
|
c := ctx.App.Command(command)
|
||||||
|
if c != nil && c.BashComplete != nil {
|
||||||
|
c.BashComplete(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
||||||
|
funcMap := template.FuncMap{
|
||||||
|
"join": strings.Join,
|
||||||
|
}
|
||||||
|
if customFunc != nil {
|
||||||
|
for key, value := range customFunc {
|
||||||
|
funcMap[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
||||||
|
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||||
|
err := t.Execute(w, data)
|
||||||
|
if err != nil {
|
||||||
|
// If the writer is closed, t.Execute will fail, and there's nothing
|
||||||
|
// we can do to recover.
|
||||||
|
if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" {
|
||||||
|
fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printHelp(out io.Writer, templ string, data interface{}) {
|
||||||
|
printHelpCustom(out, templ, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkVersion(c *Context) bool {
|
||||||
|
found := false
|
||||||
|
if VersionFlag.GetName() != "" {
|
||||||
|
eachName(VersionFlag.GetName(), func(name string) {
|
||||||
|
if c.GlobalBool(name) || c.Bool(name) {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkHelp(c *Context) bool {
|
||||||
|
found := false
|
||||||
|
if HelpFlag.GetName() != "" {
|
||||||
|
eachName(HelpFlag.GetName(), func(name string) {
|
||||||
|
if c.GlobalBool(name) || c.Bool(name) {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkCommandHelp(c *Context, name string) bool {
|
||||||
|
if c.Bool("h") || c.Bool("help") {
|
||||||
|
ShowCommandHelp(c, name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSubcommandHelp(c *Context) bool {
|
||||||
|
if c.Bool("h") || c.Bool("help") {
|
||||||
|
ShowSubcommandHelp(c)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
|
||||||
|
if !a.EnableBashCompletion {
|
||||||
|
return false, arguments
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := len(arguments) - 1
|
||||||
|
lastArg := arguments[pos]
|
||||||
|
|
||||||
|
if lastArg != "--"+BashCompletionFlag.GetName() {
|
||||||
|
return false, arguments
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, arguments[:pos]
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkCompletions(c *Context) bool {
|
||||||
|
if !c.shellComplete {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if args := c.Args(); args.Present() {
|
||||||
|
name := args.First()
|
||||||
|
if cmd := c.App.Command(name); cmd != nil {
|
||||||
|
// let the command handle the completion
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowCompletions(c)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkCommandCompletions(c *Context, name string) bool {
|
||||||
|
if !c.shellComplete {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowCommandCompletions(c, name)
|
||||||
|
return true
|
||||||
|
}
|
||||||
122
vendor/github.com/urfave/cli/runtests
generated
vendored
Normal file
122
vendor/github.com/urfave/cli/runtests
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from subprocess import check_call, check_output
|
||||||
|
|
||||||
|
|
||||||
|
PACKAGE_NAME = os.environ.get(
|
||||||
|
'CLI_PACKAGE_NAME', 'github.com/urfave/cli'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main(sysargs=sys.argv[:]):
|
||||||
|
targets = {
|
||||||
|
'vet': _vet,
|
||||||
|
'test': _test,
|
||||||
|
'gfmrun': _gfmrun,
|
||||||
|
'toc': _toc,
|
||||||
|
'gen': _gen,
|
||||||
|
}
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'target', nargs='?', choices=tuple(targets.keys()), default='test'
|
||||||
|
)
|
||||||
|
args = parser.parse_args(sysargs[1:])
|
||||||
|
|
||||||
|
targets[args.target]()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _test():
|
||||||
|
if check_output('go version'.split()).split()[2] < 'go1.2':
|
||||||
|
_run('go test -v .')
|
||||||
|
return
|
||||||
|
|
||||||
|
coverprofiles = []
|
||||||
|
for subpackage in ['', 'altsrc']:
|
||||||
|
coverprofile = 'cli.coverprofile'
|
||||||
|
if subpackage != '':
|
||||||
|
coverprofile = '{}.coverprofile'.format(subpackage)
|
||||||
|
|
||||||
|
coverprofiles.append(coverprofile)
|
||||||
|
|
||||||
|
_run('go test -v'.split() + [
|
||||||
|
'-coverprofile={}'.format(coverprofile),
|
||||||
|
('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/')
|
||||||
|
])
|
||||||
|
|
||||||
|
combined_name = _combine_coverprofiles(coverprofiles)
|
||||||
|
_run('go tool cover -func={}'.format(combined_name))
|
||||||
|
os.remove(combined_name)
|
||||||
|
|
||||||
|
|
||||||
|
def _gfmrun():
|
||||||
|
go_version = check_output('go version'.split()).split()[2]
|
||||||
|
if go_version < 'go1.3':
|
||||||
|
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
|
||||||
|
return
|
||||||
|
_run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md'])
|
||||||
|
|
||||||
|
|
||||||
|
def _vet():
|
||||||
|
_run('go vet ./...')
|
||||||
|
|
||||||
|
|
||||||
|
def _toc():
|
||||||
|
_run('node_modules/.bin/markdown-toc -i README.md')
|
||||||
|
_run('git diff --exit-code')
|
||||||
|
|
||||||
|
|
||||||
|
def _gen():
|
||||||
|
go_version = check_output('go version'.split()).split()[2]
|
||||||
|
if go_version < 'go1.5':
|
||||||
|
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
|
||||||
|
return
|
||||||
|
|
||||||
|
_run('go generate ./...')
|
||||||
|
_run('git diff --exit-code')
|
||||||
|
|
||||||
|
|
||||||
|
def _run(command):
|
||||||
|
if hasattr(command, 'split'):
|
||||||
|
command = command.split()
|
||||||
|
print('runtests: {}'.format(' '.join(command)), file=sys.stderr)
|
||||||
|
check_call(command)
|
||||||
|
|
||||||
|
|
||||||
|
def _gfmrun_count():
|
||||||
|
with open('README.md') as infile:
|
||||||
|
lines = infile.read().splitlines()
|
||||||
|
return len(filter(_is_go_runnable, lines))
|
||||||
|
|
||||||
|
|
||||||
|
def _is_go_runnable(line):
|
||||||
|
return line.startswith('package main')
|
||||||
|
|
||||||
|
|
||||||
|
def _combine_coverprofiles(coverprofiles):
|
||||||
|
combined = tempfile.NamedTemporaryFile(
|
||||||
|
suffix='.coverprofile', delete=False
|
||||||
|
)
|
||||||
|
combined.write('mode: set\n')
|
||||||
|
|
||||||
|
for coverprofile in coverprofiles:
|
||||||
|
with open(coverprofile, 'r') as infile:
|
||||||
|
for line in infile.readlines():
|
||||||
|
if not line.startswith('mode: '):
|
||||||
|
combined.write(line)
|
||||||
|
|
||||||
|
combined.flush()
|
||||||
|
name = combined.name
|
||||||
|
combined.close()
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
2
vendor/github.com/vektah/dataloaden/.gitignore
generated
vendored
Normal file
2
vendor/github.com/vektah/dataloaden/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/vendor
|
||||||
|
/.idea
|
||||||
97
vendor/github.com/vektah/dataloaden/README.md
generated
vendored
Normal file
97
vendor/github.com/vektah/dataloaden/README.md
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
### The DATALOADer gENerator [](https://circleci.com/gh/vektah/dataloaden) [](https://goreportcard.com/report/github.com/vektah/dataloaden) [](https://codecov.io/gh/vektah/dataloaden)
|
||||||
|
|
||||||
|
Requires golang 1.11+ for modules support.
|
||||||
|
|
||||||
|
This is a tool for generating type safe data loaders for go, inspired by https://github.com/facebook/dataloader.
|
||||||
|
|
||||||
|
The intended use is in graphql servers, to reduce the number of queries being sent to the database. These dataloader
|
||||||
|
objects should be request scoped and short lived. They should be cheap to create in every request even if they dont
|
||||||
|
get used.
|
||||||
|
|
||||||
|
#### Getting started
|
||||||
|
|
||||||
|
From inside the package you want to have the dataloader in:
|
||||||
|
```bash
|
||||||
|
go run github.com/vektah/dataloaden UserLoader string *github.com/dataloaden/example.User
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate a dataloader called `UserLoader` that looks up `*github.com/dataloaden/example.User`'s objects
|
||||||
|
based on a `string` key.
|
||||||
|
|
||||||
|
In another file in the same package, create the constructor method:
|
||||||
|
```go
|
||||||
|
func NewUserLoader() *UserLoader {
|
||||||
|
return &UserLoader{
|
||||||
|
wait: 2 * time.Millisecond,
|
||||||
|
maxBatch: 100,
|
||||||
|
fetch: func(keys []string) ([]*User, []error) {
|
||||||
|
users := make([]*User, len(keys))
|
||||||
|
errors := make([]error, len(keys))
|
||||||
|
|
||||||
|
for i, key := range keys {
|
||||||
|
users[i] = &User{ID: key, Name: "user " + key}
|
||||||
|
}
|
||||||
|
return users, errors
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then wherever you want to call the dataloader
|
||||||
|
```go
|
||||||
|
loader := NewUserLoader()
|
||||||
|
|
||||||
|
user, err := loader.Load("123")
|
||||||
|
```
|
||||||
|
|
||||||
|
This method will block for a short amount of time, waiting for any other similar requests to come in, call your fetch
|
||||||
|
function once. It also caches values and wont request duplicates in a batch.
|
||||||
|
|
||||||
|
#### Returning Slices
|
||||||
|
|
||||||
|
You may want to generate a dataloader that returns slices instead of single values. Both key and value types can be a
|
||||||
|
simple go type expression:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run github.com/vektah/dataloaden UserSliceLoader string []*github.com/dataloaden/example.User
|
||||||
|
```
|
||||||
|
|
||||||
|
Now each key is expected to return a slice of values and the `fetch` function has the return type `[][]*User`.
|
||||||
|
|
||||||
|
#### Using with go modules
|
||||||
|
|
||||||
|
Create a tools.go that looks like this:
|
||||||
|
```go
|
||||||
|
// +build tools
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "github.com/vektah/dataloaden"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will allow go modules to see the dependency.
|
||||||
|
|
||||||
|
You can invoke it from anywhere within your module now using `go run github.com/vektah/dataloaden` and
|
||||||
|
always get the pinned version.
|
||||||
|
|
||||||
|
#### Wait, how do I use context with this?
|
||||||
|
|
||||||
|
I don't think context makes sense to be passed through a data loader. Consider a few scenarios:
|
||||||
|
1. a dataloader shared between requests: request A and B both get batched together, which context should be passed to the DB? context.Background is probably more suitable.
|
||||||
|
2. a dataloader per request for graphql: two different nodes in the graph get batched together, they have different context for tracing purposes, which should be passed to the db? neither, you should just use the root request context.
|
||||||
|
|
||||||
|
|
||||||
|
So be explicit about your context:
|
||||||
|
```go
|
||||||
|
func NewLoader(ctx context.Context) *UserLoader {
|
||||||
|
return &UserLoader{
|
||||||
|
wait: 2 * time.Millisecond,
|
||||||
|
maxBatch: 100,
|
||||||
|
fetch: func(keys []string) ([]*User, []error) {
|
||||||
|
// you now have a ctx to work with
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you feel like I'm wrong please raise an issue.
|
||||||
32
vendor/github.com/vektah/dataloaden/appveyor.yml
generated
vendored
Normal file
32
vendor/github.com/vektah/dataloaden/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
# Source Config
|
||||||
|
|
||||||
|
skip_branch_with_pr: true
|
||||||
|
clone_folder: c:\projects\dataloaden
|
||||||
|
|
||||||
|
# Build host
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: c:\gopath
|
||||||
|
GOVERSION: 1.11.5
|
||||||
|
PATH: '%PATH%;c:\gopath\bin'
|
||||||
|
|
||||||
|
init:
|
||||||
|
- git config --global core.autocrlf input
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Install the specific Go version.
|
||||||
|
- rmdir c:\go /s /q
|
||||||
|
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
|
||||||
|
- msiexec /i go%GOVERSION%.windows-amd64.msi /q
|
||||||
|
- go version
|
||||||
|
|
||||||
|
build: false
|
||||||
|
deploy: false
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- go generate ./...
|
||||||
|
- go test -parallel 8 ./...
|
||||||
28
vendor/github.com/vektah/dataloaden/dataloaden.go
generated
vendored
Normal file
28
vendor/github.com/vektah/dataloaden/dataloaden.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/vektah/dataloaden/pkg/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) != 4 {
|
||||||
|
fmt.Println("usage: name keyType valueType")
|
||||||
|
fmt.Println(" example:")
|
||||||
|
fmt.Println(" dataloaden 'UserLoader int []*github.com/my/package.User'")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := generator.Generate(os.Args[1], os.Args[2], os.Args[3], wd); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
9
vendor/github.com/vektah/dataloaden/go.mod
generated
vendored
Normal file
9
vendor/github.com/vektah/dataloaden/go.mod
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module github.com/vektah/dataloaden
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.2.1
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd
|
||||||
|
)
|
||||||
15
vendor/github.com/vektah/dataloaden/go.sum
generated
vendored
Normal file
15
vendor/github.com/vektah/dataloaden/go.sum
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
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/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
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/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
|
||||||
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
|
||||||
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
7
vendor/github.com/vektah/dataloaden/licence.md
generated
vendored
Normal file
7
vendor/github.com/vektah/dataloaden/licence.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Copyright (c) 2017 Adam Scarr
|
||||||
|
|
||||||
|
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.
|
||||||
163
vendor/github.com/vektah/dataloaden/pkg/generator/generator.go
generated
vendored
Normal file
163
vendor/github.com/vektah/dataloaden/pkg/generator/generator.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
|
"golang.org/x/tools/imports"
|
||||||
|
)
|
||||||
|
|
||||||
|
type templateData struct {
|
||||||
|
Package string
|
||||||
|
Name string
|
||||||
|
KeyType *goType
|
||||||
|
ValType *goType
|
||||||
|
}
|
||||||
|
|
||||||
|
type goType struct {
|
||||||
|
Modifiers string
|
||||||
|
ImportPath string
|
||||||
|
ImportName string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *goType) String() string {
|
||||||
|
if t.ImportName != "" {
|
||||||
|
return t.Modifiers + t.ImportName + "." + t.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.Modifiers + t.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *goType) IsPtr() bool {
|
||||||
|
return strings.HasPrefix(t.Modifiers, "*")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *goType) IsSlice() bool {
|
||||||
|
return strings.HasPrefix(t.Modifiers, "[]")
|
||||||
|
}
|
||||||
|
|
||||||
|
var partsRe = regexp.MustCompile(`^([\[\]\*]*)(.*?)(\.\w*)?$`)
|
||||||
|
|
||||||
|
func parseType(str string) (*goType, error) {
|
||||||
|
parts := partsRe.FindStringSubmatch(str)
|
||||||
|
if len(parts) != 4 {
|
||||||
|
return nil, fmt.Errorf("type must be in the form []*github.com/import/path.Name")
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &goType{
|
||||||
|
Modifiers: parts[1],
|
||||||
|
ImportPath: parts[2],
|
||||||
|
Name: strings.TrimPrefix(parts[3], "."),
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Name == "" {
|
||||||
|
t.Name = t.ImportPath
|
||||||
|
t.ImportPath = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.ImportPath != "" {
|
||||||
|
p, err := packages.Load(&packages.Config{Mode: packages.NeedName}, t.ImportPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(p) != 1 {
|
||||||
|
return nil, fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.ImportName = p[0].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Generate(name string, keyType string, valueType string, wd string) error {
|
||||||
|
data, err := getData(name, keyType, valueType, wd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := strings.ToLower(data.Name) + "_gen.go"
|
||||||
|
|
||||||
|
if err := writeTemplate(filepath.Join(wd, filename), data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getData(name string, keyType string, valueType string, wd string) (templateData, error) {
|
||||||
|
var data templateData
|
||||||
|
|
||||||
|
genPkg := getPackage(wd)
|
||||||
|
if genPkg == nil {
|
||||||
|
return templateData{}, fmt.Errorf("unable to find package info for " + wd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
data.Name = name
|
||||||
|
data.Package = genPkg.Name
|
||||||
|
data.KeyType, err = parseType(keyType)
|
||||||
|
if err != nil {
|
||||||
|
return templateData{}, fmt.Errorf("key type: %s", err.Error())
|
||||||
|
}
|
||||||
|
data.ValType, err = parseType(valueType)
|
||||||
|
if err != nil {
|
||||||
|
return templateData{}, fmt.Errorf("key type: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we are inside the same package as the type we don't need an import and can refer directly to the type
|
||||||
|
if genPkg.PkgPath == data.ValType.ImportPath {
|
||||||
|
data.ValType.ImportName = ""
|
||||||
|
data.ValType.ImportPath = ""
|
||||||
|
}
|
||||||
|
if genPkg.PkgPath == data.KeyType.ImportPath {
|
||||||
|
data.KeyType.ImportName = ""
|
||||||
|
data.KeyType.ImportPath = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPackage(dir string) *packages.Package {
|
||||||
|
p, _ := packages.Load(&packages.Config{
|
||||||
|
Dir: dir,
|
||||||
|
}, ".")
|
||||||
|
|
||||||
|
if len(p) != 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return p[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTemplate(filepath string, data templateData) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := tpl.Execute(&buf, data); err != nil {
|
||||||
|
return errors.Wrap(err, "generating code")
|
||||||
|
}
|
||||||
|
|
||||||
|
src, err := imports.Process(filepath, buf.Bytes(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "unable to gofmt")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ioutil.WriteFile(filepath, src, 0644); err != nil {
|
||||||
|
return errors.Wrap(err, "writing output")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func lcFirst(s string) string {
|
||||||
|
r := []rune(s)
|
||||||
|
r[0] = unicode.ToLower(r[0])
|
||||||
|
return string(r)
|
||||||
|
}
|
||||||
245
vendor/github.com/vektah/dataloaden/pkg/generator/template.go
generated
vendored
Normal file
245
vendor/github.com/vektah/dataloaden/pkg/generator/template.go
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import "text/template"
|
||||||
|
|
||||||
|
var tpl = template.Must(template.New("generated").
|
||||||
|
Funcs(template.FuncMap{
|
||||||
|
"lcFirst": lcFirst,
|
||||||
|
}).
|
||||||
|
Parse(`
|
||||||
|
// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.
|
||||||
|
|
||||||
|
package {{.Package}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
{{if .KeyType.ImportPath}}"{{.KeyType.ImportPath}}"{{end}}
|
||||||
|
{{if .ValType.ImportPath}}"{{.ValType.ImportPath}}"{{end}}
|
||||||
|
)
|
||||||
|
|
||||||
|
// {{.Name}}Config captures the config to create a new {{.Name}}
|
||||||
|
type {{.Name}}Config struct {
|
||||||
|
// Fetch is a method that provides the data for the loader
|
||||||
|
Fetch func(keys []{{.KeyType.String}}) ([]{{.ValType.String}}, []error)
|
||||||
|
|
||||||
|
// Wait is how long wait before sending a batch
|
||||||
|
Wait time.Duration
|
||||||
|
|
||||||
|
// MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit
|
||||||
|
MaxBatch int
|
||||||
|
}
|
||||||
|
|
||||||
|
// New{{.Name}} creates a new {{.Name}} given a fetch, wait, and maxBatch
|
||||||
|
func New{{.Name}}(config {{.Name}}Config) *{{.Name}} {
|
||||||
|
return &{{.Name}}{
|
||||||
|
fetch: config.Fetch,
|
||||||
|
wait: config.Wait,
|
||||||
|
maxBatch: config.MaxBatch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Name}} batches and caches requests
|
||||||
|
type {{.Name}} struct {
|
||||||
|
// this method provides the data for the loader
|
||||||
|
fetch func(keys []{{.KeyType.String}}) ([]{{.ValType.String}}, []error)
|
||||||
|
|
||||||
|
// how long to done before sending a batch
|
||||||
|
wait time.Duration
|
||||||
|
|
||||||
|
// this will limit the maximum number of keys to send in one batch, 0 = no limit
|
||||||
|
maxBatch int
|
||||||
|
|
||||||
|
// INTERNAL
|
||||||
|
|
||||||
|
// lazily created cache
|
||||||
|
cache map[{{.KeyType.String}}]{{.ValType.String}}
|
||||||
|
|
||||||
|
// the current batch. keys will continue to be collected until timeout is hit,
|
||||||
|
// then everything will be sent to the fetch method and out to the listeners
|
||||||
|
batch *{{.Name|lcFirst}}Batch
|
||||||
|
|
||||||
|
// mutex to prevent races
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type {{.Name|lcFirst}}Batch struct {
|
||||||
|
keys []{{.KeyType}}
|
||||||
|
data []{{.ValType.String}}
|
||||||
|
error []error
|
||||||
|
closing bool
|
||||||
|
done chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load a {{.ValType.Name}} by key, batching and caching will be applied automatically
|
||||||
|
func (l *{{.Name}}) Load(key {{.KeyType.String}}) ({{.ValType.String}}, error) {
|
||||||
|
return l.LoadThunk(key)()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadThunk returns a function that when called will block waiting for a {{.ValType.Name}}.
|
||||||
|
// This method should be used if you want one goroutine to make requests to many
|
||||||
|
// different data loaders without blocking until the thunk is called.
|
||||||
|
func (l *{{.Name}}) LoadThunk(key {{.KeyType.String}}) func() ({{.ValType.String}}, error) {
|
||||||
|
l.mu.Lock()
|
||||||
|
if it, ok := l.cache[key]; ok {
|
||||||
|
l.mu.Unlock()
|
||||||
|
return func() ({{.ValType.String}}, error) {
|
||||||
|
return it, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if l.batch == nil {
|
||||||
|
l.batch = &{{.Name|lcFirst}}Batch{done: make(chan struct{})}
|
||||||
|
}
|
||||||
|
batch := l.batch
|
||||||
|
pos := batch.keyIndex(l, key)
|
||||||
|
l.mu.Unlock()
|
||||||
|
|
||||||
|
return func() ({{.ValType.String}}, error) {
|
||||||
|
<-batch.done
|
||||||
|
|
||||||
|
var data {{.ValType.String}}
|
||||||
|
if pos < len(batch.data) {
|
||||||
|
data = batch.data[pos]
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
// its convenient to be able to return a single error for everything
|
||||||
|
if len(batch.error) == 1 {
|
||||||
|
err = batch.error[0]
|
||||||
|
} else if batch.error != nil {
|
||||||
|
err = batch.error[pos]
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
l.mu.Lock()
|
||||||
|
l.unsafeSet(key, data)
|
||||||
|
l.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAll fetches many keys at once. It will be broken into appropriate sized
|
||||||
|
// sub batches depending on how the loader is configured
|
||||||
|
func (l *{{.Name}}) LoadAll(keys []{{.KeyType}}) ([]{{.ValType.String}}, []error) {
|
||||||
|
results := make([]func() ({{.ValType.String}}, error), len(keys))
|
||||||
|
|
||||||
|
for i, key := range keys {
|
||||||
|
results[i] = l.LoadThunk(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
{{.ValType.Name|lcFirst}}s := make([]{{.ValType.String}}, len(keys))
|
||||||
|
errors := make([]error, len(keys))
|
||||||
|
for i, thunk := range results {
|
||||||
|
{{.ValType.Name|lcFirst}}s[i], errors[i] = thunk()
|
||||||
|
}
|
||||||
|
return {{.ValType.Name|lcFirst}}s, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAllThunk returns a function that when called will block waiting for a {{.ValType.Name}}s.
|
||||||
|
// This method should be used if you want one goroutine to make requests to many
|
||||||
|
// different data loaders without blocking until the thunk is called.
|
||||||
|
func (l *{{.Name}}) LoadAllThunk(keys []{{.KeyType}}) (func() ([]{{.ValType.String}}, []error)) {
|
||||||
|
results := make([]func() ({{.ValType.String}}, error), len(keys))
|
||||||
|
for i, key := range keys {
|
||||||
|
results[i] = l.LoadThunk(key)
|
||||||
|
}
|
||||||
|
return func() ([]{{.ValType.String}}, []error) {
|
||||||
|
{{.ValType.Name|lcFirst}}s := make([]{{.ValType.String}}, len(keys))
|
||||||
|
errors := make([]error, len(keys))
|
||||||
|
for i, thunk := range results {
|
||||||
|
{{.ValType.Name|lcFirst}}s[i], errors[i] = thunk()
|
||||||
|
}
|
||||||
|
return {{.ValType.Name|lcFirst}}s, errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prime the cache with the provided key and value. If the key already exists, no change is made
|
||||||
|
// and false is returned.
|
||||||
|
// (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).)
|
||||||
|
func (l *{{.Name}}) Prime(key {{.KeyType}}, value {{.ValType.String}}) bool {
|
||||||
|
l.mu.Lock()
|
||||||
|
var found bool
|
||||||
|
if _, found = l.cache[key]; !found {
|
||||||
|
{{- if .ValType.IsPtr }}
|
||||||
|
// make a copy when writing to the cache, its easy to pass a pointer in from a loop var
|
||||||
|
// and end up with the whole cache pointing to the same value.
|
||||||
|
cpy := *value
|
||||||
|
l.unsafeSet(key, &cpy)
|
||||||
|
{{- else if .ValType.IsSlice }}
|
||||||
|
// make a copy when writing to the cache, its easy to pass a pointer in from a loop var
|
||||||
|
// and end up with the whole cache pointing to the same value.
|
||||||
|
cpy := make({{.ValType.String}}, len(value))
|
||||||
|
copy(cpy, value)
|
||||||
|
l.unsafeSet(key, cpy)
|
||||||
|
{{- else }}
|
||||||
|
l.unsafeSet(key, value)
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
l.mu.Unlock()
|
||||||
|
return !found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the value at key from the cache, if it exists
|
||||||
|
func (l *{{.Name}}) Clear(key {{.KeyType}}) {
|
||||||
|
l.mu.Lock()
|
||||||
|
delete(l.cache, key)
|
||||||
|
l.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *{{.Name}}) unsafeSet(key {{.KeyType}}, value {{.ValType.String}}) {
|
||||||
|
if l.cache == nil {
|
||||||
|
l.cache = map[{{.KeyType}}]{{.ValType.String}}{}
|
||||||
|
}
|
||||||
|
l.cache[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyIndex will return the location of the key in the batch, if its not found
|
||||||
|
// it will add the key to the batch
|
||||||
|
func (b *{{.Name|lcFirst}}Batch) keyIndex(l *{{.Name}}, key {{.KeyType}}) int {
|
||||||
|
for i, existingKey := range b.keys {
|
||||||
|
if key == existingKey {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := len(b.keys)
|
||||||
|
b.keys = append(b.keys, key)
|
||||||
|
if pos == 0 {
|
||||||
|
go b.startTimer(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.maxBatch != 0 && pos >= l.maxBatch-1 {
|
||||||
|
if !b.closing {
|
||||||
|
b.closing = true
|
||||||
|
l.batch = nil
|
||||||
|
go b.end(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *{{.Name|lcFirst}}Batch) startTimer(l *{{.Name}}) {
|
||||||
|
time.Sleep(l.wait)
|
||||||
|
l.mu.Lock()
|
||||||
|
|
||||||
|
// we must have hit a batch limit and are already finalizing this batch
|
||||||
|
if b.closing {
|
||||||
|
l.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.batch = nil
|
||||||
|
l.mu.Unlock()
|
||||||
|
|
||||||
|
b.end(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *{{.Name|lcFirst}}Batch) end(l *{{.Name}}) {
|
||||||
|
b.data, b.error = l.fetch(b.keys)
|
||||||
|
close(b.done)
|
||||||
|
}
|
||||||
|
`))
|
||||||
31
vendor/modules.txt
vendored
31
vendor/modules.txt
vendored
@@ -1,8 +1,20 @@
|
|||||||
# github.com/99designs/gqlgen v0.9.0
|
# github.com/99designs/gqlgen v0.9.0
|
||||||
github.com/99designs/gqlgen/handler
|
github.com/99designs/gqlgen
|
||||||
github.com/99designs/gqlgen/graphql
|
github.com/99designs/gqlgen/graphql
|
||||||
|
github.com/99designs/gqlgen/handler
|
||||||
github.com/99designs/gqlgen/graphql/introspection
|
github.com/99designs/gqlgen/graphql/introspection
|
||||||
|
github.com/99designs/gqlgen/cmd
|
||||||
github.com/99designs/gqlgen/complexity
|
github.com/99designs/gqlgen/complexity
|
||||||
|
github.com/99designs/gqlgen/api
|
||||||
|
github.com/99designs/gqlgen/codegen/config
|
||||||
|
github.com/99designs/gqlgen/plugin/servergen
|
||||||
|
github.com/99designs/gqlgen/codegen
|
||||||
|
github.com/99designs/gqlgen/plugin
|
||||||
|
github.com/99designs/gqlgen/plugin/modelgen
|
||||||
|
github.com/99designs/gqlgen/plugin/resolvergen
|
||||||
|
github.com/99designs/gqlgen/codegen/templates
|
||||||
|
github.com/99designs/gqlgen/internal/code
|
||||||
|
github.com/99designs/gqlgen/internal/imports
|
||||||
# github.com/BurntSushi/toml v0.3.1
|
# github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/BurntSushi/toml
|
github.com/BurntSushi/toml
|
||||||
# github.com/PuerkitoBio/goquery v1.5.0
|
# github.com/PuerkitoBio/goquery v1.5.0
|
||||||
@@ -46,8 +58,8 @@ github.com/gobuffalo/meta
|
|||||||
github.com/gobuffalo/packd
|
github.com/gobuffalo/packd
|
||||||
# github.com/gobuffalo/packr/v2 v2.0.2
|
# github.com/gobuffalo/packr/v2 v2.0.2
|
||||||
github.com/gobuffalo/packr/v2
|
github.com/gobuffalo/packr/v2
|
||||||
github.com/gobuffalo/packr/v2/file/resolver
|
|
||||||
github.com/gobuffalo/packr/v2/file
|
github.com/gobuffalo/packr/v2/file
|
||||||
|
github.com/gobuffalo/packr/v2/file/resolver
|
||||||
github.com/gobuffalo/packr/v2/jam/parser
|
github.com/gobuffalo/packr/v2/jam/parser
|
||||||
github.com/gobuffalo/packr/v2/plog
|
github.com/gobuffalo/packr/v2/plog
|
||||||
github.com/gobuffalo/packr/v2/file/resolver/encoding/hex
|
github.com/gobuffalo/packr/v2/file/resolver/encoding/hex
|
||||||
@@ -130,6 +142,11 @@ github.com/spf13/jwalterweatherman
|
|||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
# github.com/spf13/viper v1.4.0
|
# github.com/spf13/viper v1.4.0
|
||||||
github.com/spf13/viper
|
github.com/spf13/viper
|
||||||
|
# github.com/urfave/cli v1.20.0
|
||||||
|
github.com/urfave/cli
|
||||||
|
# github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e
|
||||||
|
github.com/vektah/dataloaden
|
||||||
|
github.com/vektah/dataloaden/pkg/generator
|
||||||
# github.com/vektah/gqlparser v1.1.2
|
# github.com/vektah/gqlparser v1.1.2
|
||||||
github.com/vektah/gqlparser
|
github.com/vektah/gqlparser
|
||||||
github.com/vektah/gqlparser/ast
|
github.com/vektah/gqlparser/ast
|
||||||
@@ -156,15 +173,15 @@ golang.org/x/sys/windows
|
|||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd
|
# golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd
|
||||||
golang.org/x/tools/go/ast/astutil
|
|
||||||
golang.org/x/tools/imports
|
|
||||||
golang.org/x/tools/go/packages
|
golang.org/x/tools/go/packages
|
||||||
golang.org/x/tools/internal/gopathwalk
|
golang.org/x/tools/imports
|
||||||
golang.org/x/tools/internal/module
|
golang.org/x/tools/go/ast/astutil
|
||||||
golang.org/x/tools/go/gcexportdata
|
golang.org/x/tools/go/gcexportdata
|
||||||
golang.org/x/tools/go/internal/packagesdriver
|
golang.org/x/tools/go/internal/packagesdriver
|
||||||
|
golang.org/x/tools/internal/gopathwalk
|
||||||
golang.org/x/tools/internal/semver
|
golang.org/x/tools/internal/semver
|
||||||
golang.org/x/tools/internal/fastwalk
|
golang.org/x/tools/internal/module
|
||||||
golang.org/x/tools/go/internal/gcimporter
|
golang.org/x/tools/go/internal/gcimporter
|
||||||
|
golang.org/x/tools/internal/fastwalk
|
||||||
# gopkg.in/yaml.v2 v2.2.2
|
# gopkg.in/yaml.v2 v2.2.2
|
||||||
gopkg.in/yaml.v2
|
gopkg.in/yaml.v2
|
||||||
|
|||||||
Reference in New Issue
Block a user