From 7a45943e8e3339d5bb582833dc1d9d371d45a2cc Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Thu, 17 Sep 2020 19:57:18 +1000 Subject: [PATCH] Stash box client interface (#751) * Add gql client generation files * Update dependencies * Add stash-box client generation to the makefile * Move scraped scene object matchers to models * Add stash-box to scrape with dropdown * Add scrape scene from fingerprint in UI --- .gqlgenc.yml | 13 + Makefile | 5 + go.mod | 14 +- go.sum | 91 +- .../queries/scrapers/scrapers.graphql | 6 + graphql/schema/schema.graphql | 3 + graphql/schema/types/scraper.graphql | 10 +- graphql/stash-box/query.graphql | 139 + pkg/api/resolver_query_scraper.go | 23 + pkg/api/server.go | 6 +- pkg/models/scraped.go | 87 + pkg/scraper/scrapers.go | 84 +- .../stashbox/graphql/generated_client.go | 559 + .../stashbox/graphql/generated_models.go | 1427 ++ pkg/scraper/stashbox/stash_box.go | 315 + tools.go | 1 + .../Scenes/SceneDetails/SceneEditPanel.tsx | 97 +- ui/v2.5/src/core/StashService.ts | 11 + vendor/github.com/99designs/gqlgen/.gitignore | 2 + .../github.com/99designs/gqlgen/.golangci.yml | 36 + vendor/github.com/99designs/gqlgen/LICENSE | 2 +- vendor/github.com/99designs/gqlgen/README.md | 108 +- .../99designs/gqlgen/api/generate.go | 65 +- .../github.com/99designs/gqlgen/appveyor.yml | 32 - .../99designs/gqlgen/cmd/ambient.go | 4 +- vendor/github.com/99designs/gqlgen/cmd/gen.go | 27 +- .../github.com/99designs/gqlgen/cmd/init.go | 183 +- .../github.com/99designs/gqlgen/cmd/root.go | 5 +- .../99designs/gqlgen/cmd/version.go | 7 +- .../99designs/gqlgen/codegen/args.go | 18 +- .../99designs/gqlgen/codegen/args.gotpl | 25 +- .../99designs/gqlgen/codegen/config/binder.go | 110 +- .../99designs/gqlgen/codegen/config/config.go | 448 +- .../gqlgen/codegen/config/package.go | 62 + .../gqlgen/codegen/config/resolver.go | 100 + .../99designs/gqlgen/codegen/data.go | 51 +- .../99designs/gqlgen/codegen/directive.go | 67 +- .../99designs/gqlgen/codegen/directives.gotpl | 149 + .../99designs/gqlgen/codegen/field.go | 299 +- .../99designs/gqlgen/codegen/field.gotpl | 180 +- .../99designs/gqlgen/codegen/generate.go | 1 + .../99designs/gqlgen/codegen/generated!.gotpl | 194 +- .../99designs/gqlgen/codegen/input.gotpl | 28 +- .../99designs/gqlgen/codegen/interface.go | 71 +- .../99designs/gqlgen/codegen/interface.gotpl | 17 +- .../99designs/gqlgen/codegen/object.go | 9 +- .../99designs/gqlgen/codegen/object.gotpl | 8 +- .../gqlgen/codegen/templates/import.go | 12 +- .../gqlgen/codegen/templates/templates.go | 68 +- .../99designs/gqlgen/codegen/type.go | 26 +- .../99designs/gqlgen/codegen/type.gotpl | 85 +- .../99designs/gqlgen/complexity/complexity.go | 2 +- vendor/github.com/99designs/gqlgen/go.mod | 23 +- vendor/github.com/99designs/gqlgen/go.sum | 67 +- .../99designs/gqlgen/graphql/cache.go | 29 + .../99designs/gqlgen/graphql/context.go | 274 - .../99designs/gqlgen/graphql/context_field.go | 92 + .../gqlgen/graphql/context_field_input.go | 85 + .../gqlgen/graphql/context_operation.go | 107 + .../gqlgen/graphql/context_response.go | 157 + .../99designs/gqlgen/graphql/errcode/codes.go | 49 + .../99designs/gqlgen/graphql/error.go | 8 +- .../graphql/{exec.go => executable_schema.go} | 22 +- .../gqlgen/graphql/executable_schema_mock.go | 175 + .../gqlgen/graphql/executor/executor.go | 191 + .../gqlgen/graphql/executor/extensions.go | 159 + .../99designs/gqlgen/graphql/handler.go | 123 + .../gqlgen/graphql/handler/extension/apq.go | 112 + .../graphql/handler/extension/complexity.go | 88 + .../handler/extension/introspection.go | 29 + .../gqlgen/graphql/handler/lru/lru.go | 32 + .../gqlgen/graphql/handler/server.go | 180 + .../gqlgen/graphql/handler/transport/error.go | 26 + .../graphql/handler/transport/http_form.go | 208 + .../graphql/handler/transport/http_get.go | 87 + .../graphql/handler/transport/http_post.go | 54 + .../graphql/handler/transport/options.go | 26 + .../graphql/handler/transport/reader.go | 25 + .../gqlgen/graphql/handler/transport/util.go | 30 + .../handler/transport}/websocket.go | 222 +- .../handler/transport/websocket_init.go} | 14 +- .../github.com/99designs/gqlgen/graphql/id.go | 2 + .../graphql/introspection/introspection.go | 2 +- .../gqlgen/graphql/introspection/schema.go | 20 +- .../gqlgen/graphql/introspection/type.go | 6 +- .../99designs/gqlgen/graphql/oneshot.go | 6 +- .../playground}/playground.go | 7 +- .../99designs/gqlgen/graphql/response.go | 2 +- .../99designs/gqlgen/graphql/stats.go | 60 + .../99designs/gqlgen/graphql/tracer.go | 58 - .../99designs/gqlgen/graphql/upload.go | 7 +- .../99designs/gqlgen/graphql/version.go | 2 +- .../99designs/gqlgen/handler/graphql.go | 709 - .../99designs/gqlgen/handler/handler.go | 247 + .../99designs/gqlgen/handler/mock.go | 57 - .../99designs/gqlgen/handler/stub.go | 51 - .../99designs/gqlgen/internal/code/imports.go | 63 +- .../gqlgen/internal/code/packages.go | 173 + .../99designs/gqlgen/internal/code/util.go | 5 + .../gqlgen/internal/imports/prune.go | 13 +- .../gqlgen/internal/rewrite/rewriter.go | 195 + .../gqlgen/plugin/federation/federation.go | 311 + .../gqlgen/plugin/federation/federation.gotpl | 69 + .../gqlgen/plugin/modelgen/models.go | 55 +- .../gqlgen/plugin/modelgen/models.gotpl | 6 +- .../99designs/gqlgen/plugin/plugin.go | 11 + .../gqlgen/plugin/resolvergen/resolver.go | 176 +- .../gqlgen/plugin/resolvergen/resolver.gotpl | 51 +- .../gqlgen/plugin/servergen/server.go | 1 + .../gqlgen/plugin/servergen/server.gotpl | 9 +- vendor/github.com/99designs/gqlgen/tools.go | 5 +- vendor/github.com/Yamashou/gqlgenc/.gitignore | 7 + .../github.com/Yamashou/gqlgenc/.golangci.yml | 65 + vendor/github.com/Yamashou/gqlgenc/LICENSE | 21 + vendor/github.com/Yamashou/gqlgenc/Makefile | 10 + vendor/github.com/Yamashou/gqlgenc/README.md | 118 + .../Yamashou/gqlgenc/client/client.go | 88 + .../Yamashou/gqlgenc/clientgen/client.go | 76 + .../Yamashou/gqlgenc/clientgen/query.go | 93 + .../gqlgenc/clientgen/query_source.go | 106 + .../Yamashou/gqlgenc/clientgen/source.go | 193 + .../gqlgenc/clientgen/source_generator.go | 204 + .../Yamashou/gqlgenc/clientgen/template.go | 27 + .../Yamashou/gqlgenc/clientgen/template.gotpl | 54 + .../Yamashou/gqlgenc/config/config.go | 123 + .../Yamashou/gqlgenc/generator/generater.go | 40 + vendor/github.com/Yamashou/gqlgenc/go.mod | 14 + vendor/github.com/Yamashou/gqlgenc/go.sum | 122 + .../Yamashou/gqlgenc/graphqljson/graphql.go | 416 + .../Yamashou/gqlgenc/introspection/parse.go | 289 + .../Yamashou/gqlgenc/introspection/query.go | 93 + .../Yamashou/gqlgenc/introspection/type.go | 80 + vendor/github.com/Yamashou/gqlgenc/main.go | 27 + .../agnivade/levenshtein/.travis.yml | 20 +- .../github.com/agnivade/levenshtein/Makefile | 10 +- .../github.com/agnivade/levenshtein/README.md | 31 +- vendor/github.com/agnivade/levenshtein/go.mod | 7 + vendor/github.com/agnivade/levenshtein/go.sum | 4 + .../agnivade/levenshtein/levenshtein.go | 32 +- .../cpuguy83/go-md2man/v2/LICENSE.md | 21 + .../cpuguy83/go-md2man/v2/md2man/md2man.go | 14 + .../cpuguy83/go-md2man/v2/md2man/roff.go | 345 + vendor/github.com/matryer/moq/.gitignore | 25 + vendor/github.com/matryer/moq/.travis.yml | 23 + vendor/github.com/matryer/moq/LICENSE | 21 + vendor/github.com/matryer/moq/README.md | 110 + vendor/github.com/matryer/moq/main.go | 77 + .../github.com/matryer/moq/moq-logo-small.png | Bin 0 -> 32570 bytes vendor/github.com/matryer/moq/moq-logo.png | Bin 0 -> 29562 bytes vendor/github.com/matryer/moq/pkg/moq/moq.go | 372 + .../matryer/moq/pkg/moq/template.go | 107 + vendor/github.com/matryer/moq/preview.png | Bin 0 -> 743543 bytes vendor/github.com/pkg/errors/.travis.yml | 11 +- vendor/github.com/pkg/errors/Makefile | 44 + vendor/github.com/pkg/errors/README.md | 11 +- vendor/github.com/pkg/errors/errors.go | 8 +- vendor/github.com/pkg/errors/go113.go | 38 + vendor/github.com/pkg/errors/stack.go | 58 +- .../russross/blackfriday/v2/.gitignore | 8 + .../russross/blackfriday/v2/.travis.yml | 17 + .../russross/blackfriday/v2/LICENSE.txt | 29 + .../russross/blackfriday/v2/README.md | 291 + .../russross/blackfriday/v2/block.go | 1590 ++ .../github.com/russross/blackfriday/v2/doc.go | 18 + .../github.com/russross/blackfriday/v2/esc.go | 34 + .../github.com/russross/blackfriday/v2/go.mod | 1 + .../russross/blackfriday/v2/html.go | 949 + .../russross/blackfriday/v2/inline.go | 1228 + .../russross/blackfriday/v2/markdown.go | 950 + .../russross/blackfriday/v2/node.go | 354 + .../russross/blackfriday/v2/smartypants.go | 457 + .../sanitized_anchor_name/.travis.yml | 16 + .../shurcooL/sanitized_anchor_name/LICENSE | 21 + .../shurcooL/sanitized_anchor_name/README.md | 36 + .../shurcooL/sanitized_anchor_name/go.mod | 1 + .../shurcooL/sanitized_anchor_name/main.go | 29 + vendor/github.com/urfave/cli/.travis.yml | 27 - vendor/github.com/urfave/cli/CHANGELOG.md | 435 - vendor/github.com/urfave/cli/README.md | 1381 -- vendor/github.com/urfave/cli/appveyor.yml | 26 - vendor/github.com/urfave/cli/category.go | 44 - vendor/github.com/urfave/cli/context.go | 278 - vendor/github.com/urfave/cli/flag-types.json | 93 - vendor/github.com/urfave/cli/flag.go | 799 - .../github.com/urfave/cli/flag_generated.go | 627 - .../github.com/urfave/cli/generate-flag-types | 255 - vendor/github.com/urfave/cli/runtests | 122 - vendor/github.com/urfave/cli/{ => v2}/.flake8 | 0 .../github.com/urfave/cli/{ => v2}/.gitignore | 3 + .../urfave/cli/v2/CODE_OF_CONDUCT.md | 74 + vendor/github.com/urfave/cli/{ => v2}/LICENSE | 0 vendor/github.com/urfave/cli/v2/README.md | 68 + vendor/github.com/urfave/cli/{ => v2}/app.go | 251 +- vendor/github.com/urfave/cli/v2/appveyor.yml | 28 + vendor/github.com/urfave/cli/v2/args.go | 54 + vendor/github.com/urfave/cli/v2/category.go | 79 + vendor/github.com/urfave/cli/{ => v2}/cli.go | 19 +- .../github.com/urfave/cli/{ => v2}/command.go | 207 +- vendor/github.com/urfave/cli/v2/context.go | 274 + vendor/github.com/urfave/cli/v2/docs.go | 148 + .../github.com/urfave/cli/{ => v2}/errors.go | 62 +- vendor/github.com/urfave/cli/v2/fish.go | 192 + vendor/github.com/urfave/cli/v2/flag.go | 398 + vendor/github.com/urfave/cli/v2/flag_bool.go | 106 + .../github.com/urfave/cli/v2/flag_duration.go | 105 + .../github.com/urfave/cli/v2/flag_float64.go | 106 + .../urfave/cli/v2/flag_float64_slice.go | 165 + .../github.com/urfave/cli/v2/flag_generic.go | 108 + vendor/github.com/urfave/cli/v2/flag_int.go | 106 + vendor/github.com/urfave/cli/v2/flag_int64.go | 105 + .../urfave/cli/v2/flag_int64_slice.go | 161 + .../urfave/cli/v2/flag_int_slice.go | 175 + vendor/github.com/urfave/cli/v2/flag_path.go | 95 + .../github.com/urfave/cli/v2/flag_string.go | 95 + .../urfave/cli/v2/flag_string_slice.go | 159 + .../urfave/cli/v2/flag_timestamp.go | 152 + vendor/github.com/urfave/cli/v2/flag_uint.go | 105 + .../github.com/urfave/cli/v2/flag_uint64.go | 105 + .../github.com/urfave/cli/{ => v2}/funcs.go | 18 +- vendor/github.com/urfave/cli/v2/go.mod | 9 + vendor/github.com/urfave/cli/v2/go.sum | 14 + vendor/github.com/urfave/cli/{ => v2}/help.go | 274 +- vendor/github.com/urfave/cli/v2/parse.go | 94 + vendor/github.com/urfave/cli/v2/sort.go | 29 + vendor/github.com/urfave/cli/v2/template.go | 119 + .../vektah/gqlparser/{ => v2}/.gitignore | 0 .../vektah/gqlparser/{ => v2}/LICENSE | 0 .../vektah/gqlparser/{ => v2}/ast/argmap.go | 0 .../gqlparser/{ => v2}/ast/collections.go | 10 + .../gqlparser/{ => v2}/ast/definition.go | 0 .../gqlparser/{ => v2}/ast/directive.go | 0 .../vektah/gqlparser/{ => v2}/ast/document.go | 0 .../vektah/gqlparser/{ => v2}/ast/dumper.go | 0 .../vektah/gqlparser/{ => v2}/ast/fragment.go | 0 .../gqlparser/{ => v2}/ast/operation.go | 0 .../vektah/gqlparser/v2/ast/path.go | 67 + .../gqlparser/{ => v2}/ast/selection.go | 0 .../vektah/gqlparser/{ => v2}/ast/source.go | 6 +- .../vektah/gqlparser/{ => v2}/ast/type.go | 0 .../vektah/gqlparser/{ => v2}/ast/value.go | 0 .../gqlparser/v2/formatter/formatter.go | 605 + .../vektah/gqlparser/{ => v2}/go.mod | 10 +- .../vektah/gqlparser/{ => v2}/go.sum | 19 +- .../gqlparser/{ => v2}/gqlerror/error.go | 23 +- .../vektah/gqlparser/{ => v2}/gqlparser.go | 10 +- .../gqlparser/{ => v2}/lexer/blockstring.go | 0 .../vektah/gqlparser/{ => v2}/lexer/lexer.go | 4 +- .../gqlparser/{ => v2}/lexer/lexer_test.yml | 0 .../vektah/gqlparser/{ => v2}/lexer/token.go | 2 +- .../gqlparser/{ => v2}/parser/parser.go | 6 +- .../vektah/gqlparser/{ => v2}/parser/query.go | 6 +- .../gqlparser/{ => v2}/parser/query_test.yml | 0 .../gqlparser/{ => v2}/parser/schema.go | 6 +- .../gqlparser/{ => v2}/parser/schema_test.yml | 0 .../vektah/gqlparser/{ => v2}/readme.md | 2 +- .../gqlparser/{ => v2}/validator/error.go | 4 +- .../gqlparser/{ => v2}/validator/messaging.go | 0 .../gqlparser/{ => v2}/validator/prelude.go | 2 +- .../{ => v2}/validator/prelude.graphql | 0 .../validator/rules/fields_on_correct_type.go | 4 +- .../rules/fragments_on_composite_types.go | 4 +- .../validator/rules/known_argument_names.go | 4 +- .../validator/rules/known_directives.go | 4 +- .../validator/rules/known_fragment_names.go | 4 +- .../validator/rules/known_type_names.go | 4 +- .../rules/lone_anonymous_operation.go | 4 +- .../validator/rules/no_fragment_cycles.go | 4 +- .../validator/rules/no_undefined_variables.go | 4 +- .../validator/rules/no_unused_fragments.go | 4 +- .../validator/rules/no_unused_variables.go | 4 +- .../rules/overlapping_fields_can_be_merged.go | 4 +- .../rules/possible_fragment_spreads.go | 4 +- .../rules/provided_required_arguments.go | 4 +- .../{ => v2}/validator/rules/scalar_leafs.go | 4 +- .../rules/single_field_subscriptions.go | 4 +- .../validator/rules/unique_argument_names.go | 4 +- .../rules/unique_directives_per_location.go | 4 +- .../validator/rules/unique_fragment_names.go | 4 +- .../rules/unique_input_field_names.go | 4 +- .../validator/rules/unique_operation_names.go | 4 +- .../validator/rules/unique_variable_names.go | 4 +- .../validator/rules/values_of_correct_type.go | 4 +- .../rules/variables_are_input_types.go | 4 +- .../rules/variables_in_allowed_position.go | 4 +- .../gqlparser/{ => v2}/validator/schema.go | 22 +- .../{ => v2}/validator/schema_test.yml | 36 +- .../{ => v2}/validator/suggestionList.go | 0 .../gqlparser/{ => v2}/validator/validator.go | 4 +- .../gqlparser/{ => v2}/validator/vars.go | 37 +- .../gqlparser/{ => v2}/validator/walk.go | 2 +- .../x/crypto/ssh/terminal/terminal.go | 25 +- .../x/crypto/ssh/terminal/util_windows.go | 4 +- vendor/golang.org/x/net/publicsuffix/table.go | 19919 ++++++++-------- .../tools/go/internal/packagesdriver/sizes.go | 11 +- .../golang.org/x/tools/go/packages/golist.go | 160 +- .../x/tools/go/packages/golist_overlay.go | 252 +- .../x/tools/go/packages/loadmode_string.go | 2 +- .../x/tools/go/packages/packages.go | 80 +- vendor/golang.org/x/tools/imports/forward.go | 35 +- .../x/tools/internal/event/core/event.go | 85 + .../x/tools/internal/event/core/export.go | 70 + .../x/tools/internal/event/core/fast.go | 77 + .../golang.org/x/tools/internal/event/doc.go | 7 + .../x/tools/internal/event/event.go | 127 + .../x/tools/internal/event/keys/keys.go | 564 + .../x/tools/internal/event/keys/standard.go | 22 + .../x/tools/internal/event/label/label.go | 213 + .../x/tools/internal/gocommand/invoke.go | 142 +- .../x/tools/internal/gocommand/vendor.go | 102 + .../x/tools/internal/gopathwalk/walk.go | 11 - .../x/tools/internal/imports/fix.go | 272 +- .../x/tools/internal/imports/imports.go | 88 +- .../x/tools/internal/imports/mod.go | 121 +- .../x/tools/internal/imports/sortimports.go | 20 +- .../x/tools/internal/imports/zstdlib.go | 139 + .../internal/packagesinternal/packages.go | 29 +- .../x/tools/internal/typesinternal/types.go | 28 + vendor/gopkg.in/yaml.v2/.travis.yml | 18 +- vendor/gopkg.in/yaml.v2/apic.go | 1 + vendor/gopkg.in/yaml.v2/decode.go | 14 +- vendor/gopkg.in/yaml.v2/scannerc.go | 109 +- vendor/gopkg.in/yaml.v2/yaml.go | 2 +- vendor/gopkg.in/yaml.v2/yamlh.go | 1 + vendor/modules.txt | 70 +- 324 files changed, 34978 insertions(+), 17323 deletions(-) create mode 100644 .gqlgenc.yml create mode 100644 graphql/stash-box/query.graphql create mode 100644 pkg/models/scraped.go create mode 100644 pkg/scraper/stashbox/graphql/generated_client.go create mode 100644 pkg/scraper/stashbox/graphql/generated_models.go create mode 100644 pkg/scraper/stashbox/stash_box.go delete mode 100644 vendor/github.com/99designs/gqlgen/appveyor.yml create mode 100644 vendor/github.com/99designs/gqlgen/codegen/config/package.go create mode 100644 vendor/github.com/99designs/gqlgen/codegen/config/resolver.go create mode 100644 vendor/github.com/99designs/gqlgen/codegen/directives.gotpl create mode 100644 vendor/github.com/99designs/gqlgen/graphql/cache.go delete mode 100644 vendor/github.com/99designs/gqlgen/graphql/context.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/context_field.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/context_field_input.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/context_operation.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/context_response.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/errcode/codes.go rename vendor/github.com/99designs/gqlgen/graphql/{exec.go => executable_schema.go} (77%) create mode 100644 vendor/github.com/99designs/gqlgen/graphql/executable_schema_mock.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/executor/executor.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/executor/extensions.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/extension/apq.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/extension/complexity.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/extension/introspection.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/lru/lru.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/server.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/error.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_form.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_get.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/options.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/reader.go create mode 100644 vendor/github.com/99designs/gqlgen/graphql/handler/transport/util.go rename vendor/github.com/99designs/gqlgen/{handler => graphql/handler/transport}/websocket.go (56%) rename vendor/github.com/99designs/gqlgen/{handler/context.go => graphql/handler/transport/websocket_init.go} (78%) rename vendor/github.com/99designs/gqlgen/{handler => graphql/playground}/playground.go (92%) create mode 100644 vendor/github.com/99designs/gqlgen/graphql/stats.go delete mode 100644 vendor/github.com/99designs/gqlgen/graphql/tracer.go delete mode 100644 vendor/github.com/99designs/gqlgen/handler/graphql.go create mode 100644 vendor/github.com/99designs/gqlgen/handler/handler.go delete mode 100644 vendor/github.com/99designs/gqlgen/handler/mock.go delete mode 100644 vendor/github.com/99designs/gqlgen/handler/stub.go create mode 100644 vendor/github.com/99designs/gqlgen/internal/code/packages.go create mode 100644 vendor/github.com/99designs/gqlgen/internal/rewrite/rewriter.go create mode 100644 vendor/github.com/99designs/gqlgen/plugin/federation/federation.go create mode 100644 vendor/github.com/99designs/gqlgen/plugin/federation/federation.gotpl create mode 100644 vendor/github.com/Yamashou/gqlgenc/.gitignore create mode 100644 vendor/github.com/Yamashou/gqlgenc/.golangci.yml create mode 100644 vendor/github.com/Yamashou/gqlgenc/LICENSE create mode 100644 vendor/github.com/Yamashou/gqlgenc/Makefile create mode 100644 vendor/github.com/Yamashou/gqlgenc/README.md create mode 100644 vendor/github.com/Yamashou/gqlgenc/client/client.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/client.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/query.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/source.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/source_generator.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/template.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl create mode 100644 vendor/github.com/Yamashou/gqlgenc/config/config.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/generator/generater.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/go.mod create mode 100644 vendor/github.com/Yamashou/gqlgenc/go.sum create mode 100644 vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/introspection/parse.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/introspection/query.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/introspection/type.go create mode 100644 vendor/github.com/Yamashou/gqlgenc/main.go create mode 100644 vendor/github.com/agnivade/levenshtein/go.sum create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go create mode 100644 vendor/github.com/matryer/moq/.gitignore create mode 100644 vendor/github.com/matryer/moq/.travis.yml create mode 100644 vendor/github.com/matryer/moq/LICENSE create mode 100644 vendor/github.com/matryer/moq/README.md create mode 100644 vendor/github.com/matryer/moq/main.go create mode 100644 vendor/github.com/matryer/moq/moq-logo-small.png create mode 100644 vendor/github.com/matryer/moq/moq-logo.png create mode 100644 vendor/github.com/matryer/moq/pkg/moq/moq.go create mode 100644 vendor/github.com/matryer/moq/pkg/moq/template.go create mode 100644 vendor/github.com/matryer/moq/preview.png create mode 100644 vendor/github.com/pkg/errors/Makefile create mode 100644 vendor/github.com/pkg/errors/go113.go create mode 100644 vendor/github.com/russross/blackfriday/v2/.gitignore create mode 100644 vendor/github.com/russross/blackfriday/v2/.travis.yml create mode 100644 vendor/github.com/russross/blackfriday/v2/LICENSE.txt create mode 100644 vendor/github.com/russross/blackfriday/v2/README.md create mode 100644 vendor/github.com/russross/blackfriday/v2/block.go create mode 100644 vendor/github.com/russross/blackfriday/v2/doc.go create mode 100644 vendor/github.com/russross/blackfriday/v2/esc.go create mode 100644 vendor/github.com/russross/blackfriday/v2/go.mod create mode 100644 vendor/github.com/russross/blackfriday/v2/html.go create mode 100644 vendor/github.com/russross/blackfriday/v2/inline.go create mode 100644 vendor/github.com/russross/blackfriday/v2/markdown.go create mode 100644 vendor/github.com/russross/blackfriday/v2/node.go create mode 100644 vendor/github.com/russross/blackfriday/v2/smartypants.go create mode 100644 vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml create mode 100644 vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE create mode 100644 vendor/github.com/shurcooL/sanitized_anchor_name/README.md create mode 100644 vendor/github.com/shurcooL/sanitized_anchor_name/go.mod create mode 100644 vendor/github.com/shurcooL/sanitized_anchor_name/main.go delete mode 100644 vendor/github.com/urfave/cli/.travis.yml delete mode 100644 vendor/github.com/urfave/cli/CHANGELOG.md delete mode 100644 vendor/github.com/urfave/cli/README.md delete mode 100644 vendor/github.com/urfave/cli/appveyor.yml delete mode 100644 vendor/github.com/urfave/cli/category.go delete mode 100644 vendor/github.com/urfave/cli/context.go delete mode 100644 vendor/github.com/urfave/cli/flag-types.json delete mode 100644 vendor/github.com/urfave/cli/flag.go delete mode 100644 vendor/github.com/urfave/cli/flag_generated.go delete mode 100644 vendor/github.com/urfave/cli/generate-flag-types delete mode 100644 vendor/github.com/urfave/cli/runtests rename vendor/github.com/urfave/cli/{ => v2}/.flake8 (100%) rename vendor/github.com/urfave/cli/{ => v2}/.gitignore (59%) create mode 100644 vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md rename vendor/github.com/urfave/cli/{ => v2}/LICENSE (100%) create mode 100644 vendor/github.com/urfave/cli/v2/README.md rename vendor/github.com/urfave/cli/{ => v2}/app.go (65%) create mode 100644 vendor/github.com/urfave/cli/v2/appveyor.yml create mode 100644 vendor/github.com/urfave/cli/v2/args.go create mode 100644 vendor/github.com/urfave/cli/v2/category.go rename vendor/github.com/urfave/cli/{ => v2}/cli.go (56%) rename vendor/github.com/urfave/cli/{ => v2}/command.go (57%) create mode 100644 vendor/github.com/urfave/cli/v2/context.go create mode 100644 vendor/github.com/urfave/cli/v2/docs.go rename vendor/github.com/urfave/cli/{ => v2}/errors.go (62%) create mode 100644 vendor/github.com/urfave/cli/v2/fish.go create mode 100644 vendor/github.com/urfave/cli/v2/flag.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_bool.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_duration.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_float64.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_float64_slice.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_generic.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_int.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_int64.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_int64_slice.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_int_slice.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_path.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_string.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_string_slice.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_timestamp.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_uint.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_uint64.go rename vendor/github.com/urfave/cli/{ => v2}/funcs.go (59%) create mode 100644 vendor/github.com/urfave/cli/v2/go.mod create mode 100644 vendor/github.com/urfave/cli/v2/go.sum rename vendor/github.com/urfave/cli/{ => v2}/help.go (50%) create mode 100644 vendor/github.com/urfave/cli/v2/parse.go create mode 100644 vendor/github.com/urfave/cli/v2/sort.go create mode 100644 vendor/github.com/urfave/cli/v2/template.go rename vendor/github.com/vektah/gqlparser/{ => v2}/.gitignore (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/LICENSE (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/argmap.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/collections.go (93%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/definition.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/directive.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/document.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/dumper.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/fragment.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/operation.go (100%) create mode 100644 vendor/github.com/vektah/gqlparser/v2/ast/path.go rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/selection.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/source.go (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/type.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/ast/value.go (100%) create mode 100644 vendor/github.com/vektah/gqlparser/v2/formatter/formatter.go rename vendor/github.com/vektah/gqlparser/{ => v2}/go.mod (52%) rename vendor/github.com/vektah/gqlparser/{ => v2}/go.sum (52%) rename vendor/github.com/vektah/gqlparser/{ => v2}/gqlerror/error.go (81%) rename vendor/github.com/vektah/gqlparser/{ => v2}/gqlparser.go (79%) rename vendor/github.com/vektah/gqlparser/{ => v2}/lexer/blockstring.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/lexer/lexer.go (99%) rename vendor/github.com/vektah/gqlparser/{ => v2}/lexer/lexer_test.yml (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/lexer/token.go (98%) rename vendor/github.com/vektah/gqlparser/{ => v2}/parser/parser.go (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/parser/query.go (98%) rename vendor/github.com/vektah/gqlparser/{ => v2}/parser/query_test.yml (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/parser/schema.go (99%) rename vendor/github.com/vektah/gqlparser/{ => v2}/parser/schema_test.yml (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/readme.md (85%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/error.go (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/messaging.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/prelude.go (98%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/prelude.graphql (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/fields_on_correct_type.go (97%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/fragments_on_composite_types.go (92%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/known_argument_names.go (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/known_directives.go (87%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/known_fragment_names.go (82%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/known_type_names.go (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/lone_anonymous_operation.go (83%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/no_fragment_cycles.go (96%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/no_undefined_variables.go (88%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/no_unused_fragments.go (88%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/no_unused_variables.go (88%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/overlapping_fields_can_be_merged.go (99%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/possible_fragment_spreads.go (95%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/provided_required_arguments.go (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/scalar_leafs.go (91%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/single_field_subscriptions.go (87%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/unique_argument_names.go (89%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/unique_directives_per_location.go (85%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/unique_fragment_names.go (84%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/unique_input_field_names.go (85%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/unique_operation_names.go (83%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/unique_variable_names.go (85%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/values_of_correct_type.go (97%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/variables_are_input_types.go (86%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/rules/variables_in_allowed_position.go (91%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/schema.go (95%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/schema_test.yml (94%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/suggestionList.go (100%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/validator.go (90%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/vars.go (81%) rename vendor/github.com/vektah/gqlparser/{ => v2}/validator/walk.go (99%) create mode 100644 vendor/golang.org/x/tools/internal/event/core/event.go create mode 100644 vendor/golang.org/x/tools/internal/event/core/export.go create mode 100644 vendor/golang.org/x/tools/internal/event/core/fast.go create mode 100644 vendor/golang.org/x/tools/internal/event/doc.go create mode 100644 vendor/golang.org/x/tools/internal/event/event.go create mode 100644 vendor/golang.org/x/tools/internal/event/keys/keys.go create mode 100644 vendor/golang.org/x/tools/internal/event/keys/standard.go create mode 100644 vendor/golang.org/x/tools/internal/event/label/label.go create mode 100644 vendor/golang.org/x/tools/internal/gocommand/vendor.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/types.go diff --git a/.gqlgenc.yml b/.gqlgenc.yml new file mode 100644 index 000000000..9d10817b5 --- /dev/null +++ b/.gqlgenc.yml @@ -0,0 +1,13 @@ +model: + filename: ./pkg/scraper/stashbox/graphql/generated_models.go +client: + filename: ./pkg/scraper/stashbox/graphql/generated_client.go +models: + Date: + model: github.com/99designs/gqlgen/graphql.String +endpoint: + # This points to stashdb.org currently, but can be directed at any stash-box + # instance. It is used for generation only. + url: https://stashdb.org/graphql +query: + - "./graphql/stash-box/*.graphql" diff --git a/Makefile b/Makefile index 44a3904b9..03d86daeb 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,11 @@ generate: go generate -mod=vendor cd ui/v2.5 && yarn run gqlgen +# Regenerates stash-box client files +.PHONY: generate-stash-box-client +generate-stash-box-client: + go run -mod=vendor github.com/Yamashou/gqlgenc + # Runs gofmt -w on the project's source code, modifying any files that do not match its style. .PHONY: fmt fmt: diff --git a/go.mod b/go.mod index 61580fe4e..08c335f7e 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,8 @@ module github.com/stashapp/stash require ( - github.com/99designs/gqlgen v0.9.0 + github.com/99designs/gqlgen v0.12.2 + github.com/Yamashou/gqlgenc v0.0.0-20200902035953-4dbef3551953 github.com/antchfx/htmlquery v1.2.3 github.com/bmatcuk/doublestar/v2 v2.0.1 github.com/chromedp/cdproto v0.0.0-20200608134039-8a80cdaf865c @@ -14,7 +15,6 @@ require ( github.com/gorilla/sessions v1.2.0 github.com/gorilla/websocket v1.4.2 github.com/h2non/filetype v1.0.8 - github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a github.com/jmoiron/sqlx v1.2.0 github.com/json-iterator/go v1.1.9 @@ -27,13 +27,13 @@ require ( github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.5.1 github.com/tidwall/gjson v1.6.0 - github.com/vektah/gqlparser v1.1.2 - github.com/vektra/mockery v1.1.2 // indirect + github.com/vektah/gqlparser/v2 v2.0.1 github.com/vektra/mockery/v2 v2.2.1 - golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/image v0.0.0-20190802002840-cff245a6509b - golang.org/x/net v0.0.0-20200602114024-627f9648deb9 - gopkg.in/yaml.v2 v2.2.4 + golang.org/x/net v0.0.0-20200822124328-c89045814202 + golang.org/x/tools v0.0.0-20200915031644-64986481280e // indirect + gopkg.in/yaml.v2 v2.3.0 ) replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999 diff --git a/go.sum b/go.sum index 1829c755d..7a51679a7 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -github.com/99designs/gqlgen v0.9.0 h1:g1arBPML74Vqv0L3Q+TqIhGXLspV+2MYtRLkBxuZrlE= -github.com/99designs/gqlgen v0.9.0/go.mod h1:HrrG7ic9EgLPsULxsZh/Ti+p0HNWgR3XRuvnD0pb5KY= +github.com/99designs/gqlgen v0.12.2 h1:aOdpsiCycFtCnAv8CAI1exnKrIDHMqtMzQoXeTziY4o= +github.com/99designs/gqlgen v0.12.2/go.mod h1:7zdGo6ry9u1YBp/qlb2uxSU5Mt2jQKLcBETQiKk+Bxo= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -30,8 +30,14 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/Yamashou/gqlgenc v0.0.0-20200902035953-4dbef3551953 h1:+iPJDL28FxZhEdtJ9qykrMt/oDiOvlzTa0zV06nUcFM= +github.com/Yamashou/gqlgenc v0.0.0-20200902035953-4dbef3551953/go.mod h1:kaTsk10p2hJWwrB2t7vMsk1lXj9KAHaDYRtJQiB+Ick= github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= +github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= +github.com/agnivade/levenshtein v1.1.0 h1:n6qGwyHG61v3ABce1rPVZklEYRT8NFpCMrpZdBUbYGM= +github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -44,6 +50,8 @@ github.com/antchfx/xpath v1.1.6 h1:6sVh6hB5T6phw1pFpHRQ+C4bd8sNI+O58flqtg7h0R0= github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -77,6 +85,8 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= @@ -93,6 +103,9 @@ 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= github.com/disintegration/imaging v1.6.0 h1:nVPXRUUQ36Z7MNf0O77UzgnOb1mkMMor7lmJMJXc/mA= github.com/disintegration/imaging v1.6.0/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ= @@ -372,6 +385,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -383,6 +398,7 @@ github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -396,8 +412,6 @@ github.com/gorilla/sessions v1.1.2/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= -github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -455,6 +469,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= @@ -482,6 +497,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -510,9 +526,14 @@ github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/markbates/sigtx v1.0.0/go.mod h1:QF1Hv6Ic6Ca6W+T+DL0Y/ypborFKyvUY9HmuCD4VeTc= github.com/markbates/willie v1.0.9/go.mod h1:fsrFVWl91+gXpx/6dv715j7i11fYPfZ9ZGfH0DQzY7w= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= @@ -571,6 +592,8 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -604,7 +627,11 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8= github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -612,6 +639,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= 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/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -637,6 +666,7 @@ github.com/shurcooL/octicon v0.0.0-20180602230221-c42b0e3b24d9/go.mod h1:eWdoE5J github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= @@ -650,7 +680,9 @@ github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= @@ -684,6 +716,7 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.2.2/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/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= @@ -701,14 +734,14 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= -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/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= 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= -github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4= -github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU= +github.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU= +github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74= +github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o= +github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= github.com/vektra/mockery/v2 v2.2.1 h1:EYgPvxyYkm/0JKs62qlVc9pO+ljb8biPbDWabk5/PmI= github.com/vektra/mockery/v2 v2.2.1/go.mod h1:rBZUbbhMbiSX1WlCGsOgAi6xjuJGxB7KKbnoL0XNYW8= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= @@ -717,6 +750,8 @@ github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -752,18 +787,16 @@ golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/Le golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 h1:FNSSV4jv1PrPsiM2iKGpqLPPgYACqh9Muav7Pollk1k= -golang.org/x/image v0.0.0-20190118043309-183bebdce1b2/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -779,8 +812,11 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -812,11 +848,13 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgP golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -833,6 +871,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -859,6 +899,7 @@ golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190116161447-11f53e031339 h1:g/Jesu8+QLnA0CPzF3E1pURg0Byr7i6jLoX5sqjcAh0= golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -933,12 +974,24 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e h1:ssd5ulOvVWlh4kDSUF2SqzmMeWfjmwDXM+uGw/aQjRE= golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3 h1:OjYQxZBKJFs+sJbHkvSGIKNMkZXDJQ9JsMpebGhkafI= +golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200915031644-64986481280e h1:tfSNPIxC48Azhz4nLSPskz/yE9R6ftFRK8pfgfqWUAc= +golang.org/x/tools v0.0.0-20200915031644-64986481280e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -956,6 +1009,7 @@ google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO50 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -984,6 +1038,8 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod 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/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= @@ -1000,6 +1056,9 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/graphql/documents/queries/scrapers/scrapers.graphql b/graphql/documents/queries/scrapers/scrapers.graphql index 9904f31f5..0aaceba84 100644 --- a/graphql/documents/queries/scrapers/scrapers.graphql +++ b/graphql/documents/queries/scrapers/scrapers.graphql @@ -66,3 +66,9 @@ query ScrapeMovieURL($url: String!) { ...ScrapedMovieData } } + +query QueryStashBoxScene($input: StashBoxQueryInput!) { + queryStashBoxScene(input: $input) { + ...ScrapedSceneData + } +} \ No newline at end of file diff --git a/graphql/schema/schema.graphql b/graphql/schema/schema.graphql index 656b24f95..ac1e2d696 100644 --- a/graphql/schema/schema.graphql +++ b/graphql/schema/schema.graphql @@ -79,6 +79,9 @@ type Query { """Scrape a list of performers from a query""" scrapeFreeonesPerformerList(query: String!): [String!]! + """Query StashBox for scenes""" + queryStashBoxScene(input: StashBoxQueryInput!): [ScrapedScene!]! + # Plugins """List loaded plugins""" plugins: [Plugin!] diff --git a/graphql/schema/types/scraper.graphql b/graphql/schema/types/scraper.graphql index 6a7dcaa0b..d5c0ad397 100644 --- a/graphql/schema/types/scraper.graphql +++ b/graphql/schema/types/scraper.graphql @@ -24,7 +24,6 @@ type Scraper { movie: ScraperSpec } - type ScrapedScenePerformer { """Set if performer matched""" stored_id: ID @@ -88,3 +87,12 @@ type ScrapedScene { performers: [ScrapedScenePerformer!] movies: [ScrapedSceneMovie!] } + +input StashBoxQueryInput { + """Index of the configured stash-box instance to use""" + stash_box_index: Int! + """Instructs query by scene fingerprints""" + scene_ids: [ID!] + """Query by query string""" + q: String +} diff --git a/graphql/stash-box/query.graphql b/graphql/stash-box/query.graphql new file mode 100644 index 000000000..4424ce8db --- /dev/null +++ b/graphql/stash-box/query.graphql @@ -0,0 +1,139 @@ +fragment URLFragment on URL { + url + type +} + +fragment ImageFragment on Image { + id + url + width + height +} + +fragment StudioFragment on Studio { + name + id + urls { + ...URLFragment + } + images { + ...ImageFragment + } +} + +fragment TagFragment on Tag { + name + id +} + +fragment FuzzyDateFragment on FuzzyDate { + date + accuracy +} + +fragment MeasurementsFragment on Measurements { + band_size + cup_size + waist + hip +} + +fragment BodyModificationFragment on BodyModification { + location + description +} + +fragment PerformerFragment on Performer { + id + name + disambiguation + aliases + gender + urls { + ...URLFragment + } + images { + ...ImageFragment + } + birthdate { + ...FuzzyDateFragment + } + ethnicity + country + eye_color + hair_color + height + measurements { + ...MeasurementsFragment + } + breast_type + career_start_year + career_end_year + tattoos { + ...BodyModificationFragment + } + piercings { + ...BodyModificationFragment + } +} + +fragment PerformerAppearanceFragment on PerformerAppearance { + as + performer { + ...PerformerFragment + } +} + +fragment FingerprintFragment on Fingerprint { + algorithm + hash + duration +} + +fragment SceneFragment on Scene { + id + title + details + duration + date + urls { + ...URLFragment + } + images { + ...ImageFragment + } + studio { + ...StudioFragment + } + tags { + ...TagFragment + } + performers { + ...PerformerAppearanceFragment + } + fingerprints { + ...FingerprintFragment + } +} + +query FindSceneByFingerprint($fingerprint: FingerprintQueryInput!) { + findSceneByFingerprint(fingerprint: $fingerprint) { + ...SceneFragment + } +} + +query FindScenesByFingerprints($fingerprints: [String!]!) { + findScenesByFingerprints(fingerprints: $fingerprints) { + ...SceneFragment + } +} + +query SearchScene($term: String!) { + searchScene(term: $term) { + ...SceneFragment + } +} + +mutation SubmitFingerprint($input: FingerprintSubmission!) { + submitFingerprint(input: $input) +} diff --git a/pkg/api/resolver_query_scraper.go b/pkg/api/resolver_query_scraper.go index c66f2ebc6..ecbf0371a 100644 --- a/pkg/api/resolver_query_scraper.go +++ b/pkg/api/resolver_query_scraper.go @@ -2,10 +2,13 @@ package api import ( "context" + "fmt" "github.com/stashapp/stash/pkg/manager" + "github.com/stashapp/stash/pkg/manager/config" "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/scraper" + "github.com/stashapp/stash/pkg/scraper/stashbox" ) // deprecated @@ -72,3 +75,23 @@ func (r *queryResolver) ScrapeSceneURL(ctx context.Context, url string) (*models func (r *queryResolver) ScrapeMovieURL(ctx context.Context, url string) (*models.ScrapedMovie, error) { return manager.GetInstance().ScraperCache.ScrapeMovieURL(url) } + +func (r *queryResolver) QueryStashBoxScene(ctx context.Context, input models.StashBoxQueryInput) ([]*models.ScrapedScene, error) { + boxes := config.GetStashBoxes() + + if input.StashBoxIndex < 0 || input.StashBoxIndex >= len(boxes) { + return nil, fmt.Errorf("invalid stash_box_index %d", input.StashBoxIndex) + } + + client := stashbox.NewClient(*boxes[input.StashBoxIndex]) + + if len(input.SceneIds) > 0 { + return client.FindStashBoxScenesByFingerprints(input.SceneIds) + } + + if input.Q != nil { + return client.QueryStashBoxScene(*input.Q) + } + + return nil, nil +} diff --git a/pkg/api/server.go b/pkg/api/server.go index df713c516..02b44c07d 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -129,16 +129,12 @@ func Start() { message := fmt.Sprintf("Internal system error. Error <%v>", err) return errors.New(message) }) - requestMiddleware := handler.RequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte { - //api.GetRequestContext(ctx).Variables[] - return next(ctx) - }) websocketUpgrader := handler.WebsocketUpgrader(websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, }) - gqlHandler := handler.GraphQL(models.NewExecutableSchema(models.Config{Resolvers: &Resolver{}}), recoverFunc, requestMiddleware, websocketUpgrader) + gqlHandler := handler.GraphQL(models.NewExecutableSchema(models.Config{Resolvers: &Resolver{}}), recoverFunc, websocketUpgrader) r.Handle("/graphql", gqlHandler) r.Handle("/playground", handler.Playground("GraphQL playground", "/graphql")) diff --git a/pkg/models/scraped.go b/pkg/models/scraped.go new file mode 100644 index 000000000..c2167e902 --- /dev/null +++ b/pkg/models/scraped.go @@ -0,0 +1,87 @@ +package models + +import "strconv" + +// MatchScrapedScenePerformer matches the provided performer with the +// performers in the database and sets the ID field if one is found. +func MatchScrapedScenePerformer(p *ScrapedScenePerformer) error { + qb := NewPerformerQueryBuilder() + + performers, err := qb.FindByNames([]string{p.Name}, nil, true) + + if err != nil { + return err + } + + if len(performers) != 1 { + // ignore - cannot match + return nil + } + + id := strconv.Itoa(performers[0].ID) + p.ID = &id + return nil +} + +// MatchScrapedSceneStudio matches the provided studio with the studios +// in the database and sets the ID field if one is found. +func MatchScrapedSceneStudio(s *ScrapedSceneStudio) error { + qb := NewStudioQueryBuilder() + + studio, err := qb.FindByName(s.Name, nil, true) + + if err != nil { + return err + } + + if studio == nil { + // ignore - cannot match + return nil + } + + id := strconv.Itoa(studio.ID) + s.ID = &id + return nil +} + +// MatchScrapedSceneMovie matches the provided movie with the movies +// in the database and sets the ID field if one is found. +func MatchScrapedSceneMovie(m *ScrapedSceneMovie) error { + qb := NewMovieQueryBuilder() + + movies, err := qb.FindByNames([]string{m.Name}, nil, true) + + if err != nil { + return err + } + + if len(movies) != 1 { + // ignore - cannot match + return nil + } + + id := strconv.Itoa(movies[0].ID) + m.ID = &id + return nil +} + +// MatchScrapedSceneTag matches the provided tag with the tags +// in the database and sets the ID field if one is found. +func MatchScrapedSceneTag(s *ScrapedSceneTag) error { + qb := NewTagQueryBuilder() + + tag, err := qb.FindByName(s.Name, nil, true) + + if err != nil { + return err + } + + if tag == nil { + // ignore - cannot match + return nil + } + + id := strconv.Itoa(tag.ID) + s.ID = &id + return nil +} diff --git a/pkg/scraper/scrapers.go b/pkg/scraper/scrapers.go index 64788bccc..e6cc65640 100644 --- a/pkg/scraper/scrapers.go +++ b/pkg/scraper/scrapers.go @@ -214,106 +214,30 @@ func (c Cache) ScrapePerformerURL(url string) (*models.ScrapedPerformer, error) return nil, nil } -func matchPerformer(p *models.ScrapedScenePerformer) error { - qb := models.NewPerformerQueryBuilder() - - performers, err := qb.FindByNames([]string{p.Name}, nil, true) - - if err != nil { - return err - } - - if len(performers) != 1 { - // ignore - cannot match - return nil - } - - id := strconv.Itoa(performers[0].ID) - p.ID = &id - return nil -} - -func matchStudio(s *models.ScrapedSceneStudio) error { - qb := models.NewStudioQueryBuilder() - - studio, err := qb.FindByName(s.Name, nil, true) - - if err != nil { - return err - } - - if studio == nil { - // ignore - cannot match - return nil - } - - id := strconv.Itoa(studio.ID) - s.ID = &id - return nil -} - -func matchMovie(m *models.ScrapedSceneMovie) error { - qb := models.NewMovieQueryBuilder() - - movies, err := qb.FindByNames([]string{m.Name}, nil, true) - - if err != nil { - return err - } - - if len(movies) != 1 { - // ignore - cannot match - return nil - } - - id := strconv.Itoa(movies[0].ID) - m.ID = &id - return nil -} - -func matchTag(s *models.ScrapedSceneTag) error { - qb := models.NewTagQueryBuilder() - - tag, err := qb.FindByName(s.Name, nil, true) - - if err != nil { - return err - } - - if tag == nil { - // ignore - cannot match - return nil - } - - id := strconv.Itoa(tag.ID) - s.ID = &id - return nil -} - func (c Cache) postScrapeScene(ret *models.ScrapedScene) error { for _, p := range ret.Performers { - err := matchPerformer(p) + err := models.MatchScrapedScenePerformer(p) if err != nil { return err } } for _, p := range ret.Movies { - err := matchMovie(p) + err := models.MatchScrapedSceneMovie(p) if err != nil { return err } } for _, t := range ret.Tags { - err := matchTag(t) + err := models.MatchScrapedSceneTag(t) if err != nil { return err } } if ret.Studio != nil { - err := matchStudio(ret.Studio) + err := models.MatchScrapedSceneStudio(ret.Studio) if err != nil { return err } diff --git a/pkg/scraper/stashbox/graphql/generated_client.go b/pkg/scraper/stashbox/graphql/generated_client.go new file mode 100644 index 000000000..4ea84ce63 --- /dev/null +++ b/pkg/scraper/stashbox/graphql/generated_client.go @@ -0,0 +1,559 @@ +// Code generated by github.com/Yamashou/gqlgenc, DO NOT EDIT. + +package graphql + +import ( + "context" + "net/http" + + "github.com/Yamashou/gqlgenc/client" +) + +type Client struct { + Client *client.Client +} + +func NewClient(cli *http.Client, baseURL string, options ...client.HTTPRequestOption) *Client { + return &Client{Client: client.NewClient(cli, baseURL, options...)} +} + +type Query struct { + FindPerformer *Performer "json:\"findPerformer\" graphql:\"findPerformer\"" + QueryPerformers QueryPerformersResultType "json:\"queryPerformers\" graphql:\"queryPerformers\"" + FindStudio *Studio "json:\"findStudio\" graphql:\"findStudio\"" + QueryStudios QueryStudiosResultType "json:\"queryStudios\" graphql:\"queryStudios\"" + FindTag *Tag "json:\"findTag\" graphql:\"findTag\"" + QueryTags QueryTagsResultType "json:\"queryTags\" graphql:\"queryTags\"" + FindScene *Scene "json:\"findScene\" graphql:\"findScene\"" + FindSceneByFingerprint []*Scene "json:\"findSceneByFingerprint\" graphql:\"findSceneByFingerprint\"" + FindScenesByFingerprints []*Scene "json:\"findScenesByFingerprints\" graphql:\"findScenesByFingerprints\"" + QueryScenes QueryScenesResultType "json:\"queryScenes\" graphql:\"queryScenes\"" + FindEdit *Edit "json:\"findEdit\" graphql:\"findEdit\"" + QueryEdits QueryEditsResultType "json:\"queryEdits\" graphql:\"queryEdits\"" + FindUser *User "json:\"findUser\" graphql:\"findUser\"" + QueryUsers QueryUsersResultType "json:\"queryUsers\" graphql:\"queryUsers\"" + Me *User "json:\"me\" graphql:\"me\"" + SearchPerformer []*Performer "json:\"searchPerformer\" graphql:\"searchPerformer\"" + SearchScene []*Scene "json:\"searchScene\" graphql:\"searchScene\"" + Version Version "json:\"version\" graphql:\"version\"" +} + +type Mutation struct { + SceneCreate *Scene "json:\"sceneCreate\" graphql:\"sceneCreate\"" + SceneUpdate *Scene "json:\"sceneUpdate\" graphql:\"sceneUpdate\"" + SceneDestroy bool "json:\"sceneDestroy\" graphql:\"sceneDestroy\"" + PerformerCreate *Performer "json:\"performerCreate\" graphql:\"performerCreate\"" + PerformerUpdate *Performer "json:\"performerUpdate\" graphql:\"performerUpdate\"" + PerformerDestroy bool "json:\"performerDestroy\" graphql:\"performerDestroy\"" + StudioCreate *Studio "json:\"studioCreate\" graphql:\"studioCreate\"" + StudioUpdate *Studio "json:\"studioUpdate\" graphql:\"studioUpdate\"" + StudioDestroy bool "json:\"studioDestroy\" graphql:\"studioDestroy\"" + TagCreate *Tag "json:\"tagCreate\" graphql:\"tagCreate\"" + TagUpdate *Tag "json:\"tagUpdate\" graphql:\"tagUpdate\"" + TagDestroy bool "json:\"tagDestroy\" graphql:\"tagDestroy\"" + UserCreate *User "json:\"userCreate\" graphql:\"userCreate\"" + UserUpdate *User "json:\"userUpdate\" graphql:\"userUpdate\"" + UserDestroy bool "json:\"userDestroy\" graphql:\"userDestroy\"" + ImageCreate *Image "json:\"imageCreate\" graphql:\"imageCreate\"" + ImageUpdate *Image "json:\"imageUpdate\" graphql:\"imageUpdate\"" + ImageDestroy bool "json:\"imageDestroy\" graphql:\"imageDestroy\"" + RegenerateAPIKey string "json:\"regenerateAPIKey\" graphql:\"regenerateAPIKey\"" + ChangePassword bool "json:\"changePassword\" graphql:\"changePassword\"" + SceneEdit Edit "json:\"sceneEdit\" graphql:\"sceneEdit\"" + PerformerEdit Edit "json:\"performerEdit\" graphql:\"performerEdit\"" + StudioEdit Edit "json:\"studioEdit\" graphql:\"studioEdit\"" + TagEdit Edit "json:\"tagEdit\" graphql:\"tagEdit\"" + EditVote Edit "json:\"editVote\" graphql:\"editVote\"" + EditComment Edit "json:\"editComment\" graphql:\"editComment\"" + ApplyEdit Edit "json:\"applyEdit\" graphql:\"applyEdit\"" + CancelEdit Edit "json:\"cancelEdit\" graphql:\"cancelEdit\"" + SubmitFingerprint bool "json:\"submitFingerprint\" graphql:\"submitFingerprint\"" +} +type URLFragment struct { + URL string "json:\"url\" graphql:\"url\"" + Type string "json:\"type\" graphql:\"type\"" +} +type ImageFragment struct { + ID string "json:\"id\" graphql:\"id\"" + URL string "json:\"url\" graphql:\"url\"" + Width *int "json:\"width\" graphql:\"width\"" + Height *int "json:\"height\" graphql:\"height\"" +} +type StudioFragment struct { + Name string "json:\"name\" graphql:\"name\"" + ID string "json:\"id\" graphql:\"id\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" +} +type TagFragment struct { + Name string "json:\"name\" graphql:\"name\"" + ID string "json:\"id\" graphql:\"id\"" +} +type FuzzyDateFragment struct { + Date string "json:\"date\" graphql:\"date\"" + Accuracy DateAccuracyEnum "json:\"accuracy\" graphql:\"accuracy\"" +} +type MeasurementsFragment struct { + BandSize *int "json:\"band_size\" graphql:\"band_size\"" + CupSize *string "json:\"cup_size\" graphql:\"cup_size\"" + Waist *int "json:\"waist\" graphql:\"waist\"" + Hip *int "json:\"hip\" graphql:\"hip\"" +} +type BodyModificationFragment struct { + Location string "json:\"location\" graphql:\"location\"" + Description *string "json:\"description\" graphql:\"description\"" +} +type PerformerFragment struct { + ID string "json:\"id\" graphql:\"id\"" + Name string "json:\"name\" graphql:\"name\"" + Disambiguation *string "json:\"disambiguation\" graphql:\"disambiguation\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + Gender *GenderEnum "json:\"gender\" graphql:\"gender\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Birthdate *FuzzyDateFragment "json:\"birthdate\" graphql:\"birthdate\"" + Ethnicity *EthnicityEnum "json:\"ethnicity\" graphql:\"ethnicity\"" + Country *string "json:\"country\" graphql:\"country\"" + EyeColor *EyeColorEnum "json:\"eye_color\" graphql:\"eye_color\"" + HairColor *HairColorEnum "json:\"hair_color\" graphql:\"hair_color\"" + Height *int "json:\"height\" graphql:\"height\"" + Measurements MeasurementsFragment "json:\"measurements\" graphql:\"measurements\"" + BreastType *BreastTypeEnum "json:\"breast_type\" graphql:\"breast_type\"" + CareerStartYear *int "json:\"career_start_year\" graphql:\"career_start_year\"" + CareerEndYear *int "json:\"career_end_year\" graphql:\"career_end_year\"" + Tattoos []*BodyModificationFragment "json:\"tattoos\" graphql:\"tattoos\"" + Piercings []*BodyModificationFragment "json:\"piercings\" graphql:\"piercings\"" +} +type PerformerAppearanceFragment struct { + As *string "json:\"as\" graphql:\"as\"" + Performer PerformerFragment "json:\"performer\" graphql:\"performer\"" +} +type FingerprintFragment struct { + Algorithm FingerprintAlgorithm "json:\"algorithm\" graphql:\"algorithm\"" + Hash string "json:\"hash\" graphql:\"hash\"" + Duration int "json:\"duration\" graphql:\"duration\"" +} +type SceneFragment struct { + ID string "json:\"id\" graphql:\"id\"" + Title *string "json:\"title\" graphql:\"title\"" + Details *string "json:\"details\" graphql:\"details\"" + Duration *int "json:\"duration\" graphql:\"duration\"" + Date *string "json:\"date\" graphql:\"date\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Studio *StudioFragment "json:\"studio\" graphql:\"studio\"" + Tags []*TagFragment "json:\"tags\" graphql:\"tags\"" + Performers []*PerformerAppearanceFragment "json:\"performers\" graphql:\"performers\"" + Fingerprints []*FingerprintFragment "json:\"fingerprints\" graphql:\"fingerprints\"" +} +type FindSceneByFingerprint struct { + FindSceneByFingerprint []*SceneFragment "json:\"findSceneByFingerprint\" graphql:\"findSceneByFingerprint\"" +} +type FindScenesByFingerprints struct { + FindScenesByFingerprints []*SceneFragment "json:\"findScenesByFingerprints\" graphql:\"findScenesByFingerprints\"" +} +type SearchScene struct { + SearchScene []*SceneFragment "json:\"searchScene\" graphql:\"searchScene\"" +} +type SubmitFingerprintPayload struct { + SubmitFingerprint bool "json:\"submitFingerprint\" graphql:\"submitFingerprint\"" +} + +const FindSceneByFingerprintQuery = `query FindSceneByFingerprint ($fingerprint: FingerprintQueryInput!) { + findSceneByFingerprint(fingerprint: $fingerprint) { + ... SceneFragment + } +} +fragment SceneFragment on Scene { + id + title + details + duration + date + urls { + ... URLFragment + } + images { + ... ImageFragment + } + studio { + ... StudioFragment + } + tags { + ... TagFragment + } + performers { + ... PerformerAppearanceFragment + } + fingerprints { + ... FingerprintFragment + } +} +fragment TagFragment on Tag { + name + id +} +fragment PerformerFragment on Performer { + id + name + disambiguation + aliases + gender + urls { + ... URLFragment + } + images { + ... ImageFragment + } + birthdate { + ... FuzzyDateFragment + } + ethnicity + country + eye_color + hair_color + height + measurements { + ... MeasurementsFragment + } + breast_type + career_start_year + career_end_year + tattoos { + ... BodyModificationFragment + } + piercings { + ... BodyModificationFragment + } +} +fragment BodyModificationFragment on BodyModification { + location + description +} +fragment MeasurementsFragment on Measurements { + band_size + cup_size + waist + hip +} +fragment FingerprintFragment on Fingerprint { + algorithm + hash + duration +} +fragment URLFragment on URL { + url + type +} +fragment ImageFragment on Image { + id + url + width + height +} +fragment StudioFragment on Studio { + name + id + urls { + ... URLFragment + } + images { + ... ImageFragment + } +} +fragment PerformerAppearanceFragment on PerformerAppearance { + as + performer { + ... PerformerFragment + } +} +fragment FuzzyDateFragment on FuzzyDate { + date + accuracy +} +` + +func (c *Client) FindSceneByFingerprint(ctx context.Context, fingerprint FingerprintQueryInput, httpRequestOptions ...client.HTTPRequestOption) (*FindSceneByFingerprint, error) { + vars := map[string]interface{}{ + "fingerprint": fingerprint, + } + + var res FindSceneByFingerprint + if err := c.Client.Post(ctx, FindSceneByFingerprintQuery, &res, vars, httpRequestOptions...); err != nil { + return nil, err + } + + return &res, nil +} + +const FindScenesByFingerprintsQuery = `query FindScenesByFingerprints ($fingerprints: [String!]!) { + findScenesByFingerprints(fingerprints: $fingerprints) { + ... SceneFragment + } +} +fragment ImageFragment on Image { + id + url + width + height +} +fragment StudioFragment on Studio { + name + id + urls { + ... URLFragment + } + images { + ... ImageFragment + } +} +fragment TagFragment on Tag { + name + id +} +fragment MeasurementsFragment on Measurements { + band_size + cup_size + waist + hip +} +fragment BodyModificationFragment on BodyModification { + location + description +} +fragment SceneFragment on Scene { + id + title + details + duration + date + urls { + ... URLFragment + } + images { + ... ImageFragment + } + studio { + ... StudioFragment + } + tags { + ... TagFragment + } + performers { + ... PerformerAppearanceFragment + } + fingerprints { + ... FingerprintFragment + } +} +fragment PerformerAppearanceFragment on PerformerAppearance { + as + performer { + ... PerformerFragment + } +} +fragment PerformerFragment on Performer { + id + name + disambiguation + aliases + gender + urls { + ... URLFragment + } + images { + ... ImageFragment + } + birthdate { + ... FuzzyDateFragment + } + ethnicity + country + eye_color + hair_color + height + measurements { + ... MeasurementsFragment + } + breast_type + career_start_year + career_end_year + tattoos { + ... BodyModificationFragment + } + piercings { + ... BodyModificationFragment + } +} +fragment FuzzyDateFragment on FuzzyDate { + date + accuracy +} +fragment FingerprintFragment on Fingerprint { + algorithm + hash + duration +} +fragment URLFragment on URL { + url + type +} +` + +func (c *Client) FindScenesByFingerprints(ctx context.Context, fingerprints []string, httpRequestOptions ...client.HTTPRequestOption) (*FindScenesByFingerprints, error) { + vars := map[string]interface{}{ + "fingerprints": fingerprints, + } + + var res FindScenesByFingerprints + if err := c.Client.Post(ctx, FindScenesByFingerprintsQuery, &res, vars, httpRequestOptions...); err != nil { + return nil, err + } + + return &res, nil +} + +const SearchSceneQuery = `query SearchScene ($term: String!) { + searchScene(term: $term) { + ... SceneFragment + } +} +fragment FuzzyDateFragment on FuzzyDate { + date + accuracy +} +fragment MeasurementsFragment on Measurements { + band_size + cup_size + waist + hip +} +fragment FingerprintFragment on Fingerprint { + algorithm + hash + duration +} +fragment SceneFragment on Scene { + id + title + details + duration + date + urls { + ... URLFragment + } + images { + ... ImageFragment + } + studio { + ... StudioFragment + } + tags { + ... TagFragment + } + performers { + ... PerformerAppearanceFragment + } + fingerprints { + ... FingerprintFragment + } +} +fragment TagFragment on Tag { + name + id +} +fragment PerformerAppearanceFragment on PerformerAppearance { + as + performer { + ... PerformerFragment + } +} +fragment PerformerFragment on Performer { + id + name + disambiguation + aliases + gender + urls { + ... URLFragment + } + images { + ... ImageFragment + } + birthdate { + ... FuzzyDateFragment + } + ethnicity + country + eye_color + hair_color + height + measurements { + ... MeasurementsFragment + } + breast_type + career_start_year + career_end_year + tattoos { + ... BodyModificationFragment + } + piercings { + ... BodyModificationFragment + } +} +fragment URLFragment on URL { + url + type +} +fragment ImageFragment on Image { + id + url + width + height +} +fragment StudioFragment on Studio { + name + id + urls { + ... URLFragment + } + images { + ... ImageFragment + } +} +fragment BodyModificationFragment on BodyModification { + location + description +} +` + +func (c *Client) SearchScene(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchScene, error) { + vars := map[string]interface{}{ + "term": term, + } + + var res SearchScene + if err := c.Client.Post(ctx, SearchSceneQuery, &res, vars, httpRequestOptions...); err != nil { + return nil, err + } + + return &res, nil +} + +const SubmitFingerprintQuery = `mutation SubmitFingerprint ($input: FingerprintSubmission!) { + submitFingerprint(input: $input) +} +` + +func (c *Client) SubmitFingerprint(ctx context.Context, input FingerprintSubmission, httpRequestOptions ...client.HTTPRequestOption) (*SubmitFingerprintPayload, error) { + vars := map[string]interface{}{ + "input": input, + } + + var res SubmitFingerprintPayload + if err := c.Client.Post(ctx, SubmitFingerprintQuery, &res, vars, httpRequestOptions...); err != nil { + return nil, err + } + + return &res, nil +} diff --git a/pkg/scraper/stashbox/graphql/generated_models.go b/pkg/scraper/stashbox/graphql/generated_models.go new file mode 100644 index 000000000..a8715092b --- /dev/null +++ b/pkg/scraper/stashbox/graphql/generated_models.go @@ -0,0 +1,1427 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package graphql + +import ( + "fmt" + "io" + "strconv" + "time" +) + +type EditDetails interface { + IsEditDetails() +} + +type EditTarget interface { + IsEditTarget() +} + +type ApplyEditInput struct { + ID string `json:"id"` +} + +type BodyModification struct { + Location string `json:"location"` + Description *string `json:"description"` +} + +type BodyModificationCriterionInput struct { + Location *string `json:"location"` + Description *string `json:"description"` + Modifier CriterionModifier `json:"modifier"` +} + +type BodyModificationInput struct { + Location string `json:"location"` + Description *string `json:"description"` +} + +type BreastTypeCriterionInput struct { + Value *BreastTypeEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type CancelEditInput struct { + ID string `json:"id"` +} + +type DateCriterionInput struct { + Value string `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Edit struct { + ID string `json:"id"` + User *User `json:"user"` + // Object being edited - null if creating a new object + Target EditTarget `json:"target"` + TargetType TargetTypeEnum `json:"target_type"` + // Objects to merge with the target. Only applicable to merges + MergeSources []EditTarget `json:"merge_sources"` + Operation OperationEnum `json:"operation"` + Details EditDetails `json:"details"` + Comments []*EditComment `json:"comments"` + Votes []*VoteComment `json:"votes"` + // = Accepted - Rejected + VoteCount int `json:"vote_count"` + Status VoteStatusEnum `json:"status"` + Applied bool `json:"applied"` + Created time.Time `json:"created"` +} + +type EditComment struct { + User *User `json:"user"` + Date time.Time `json:"date"` + Comment string `json:"comment"` +} + +type EditCommentInput struct { + ID string `json:"id"` + Comment string `json:"comment"` +} + +type EditFilterType struct { + // Filter by user id + UserID *string `json:"user_id"` + // Filter by status + Status *VoteStatusEnum `json:"status"` + // Filter by operation + Operation *OperationEnum `json:"operation"` + // Filter by vote count + VoteCount *IntCriterionInput `json:"vote_count"` + // Filter by applied status + Applied *bool `json:"applied"` + // Filter by target type + TargetType *TargetTypeEnum `json:"target_type"` + // Filter by target id + TargetID *string `json:"target_id"` +} + +type EditInput struct { + // Not required for create type + ID *string `json:"id"` + Operation OperationEnum `json:"operation"` + // Required for amending an existing edit + EditID *string `json:"edit_id"` + // Only required for merge type + MergeSourceIds []string `json:"merge_source_ids"` + Comment *string `json:"comment"` +} + +type EditVoteInput struct { + ID string `json:"id"` + Comment *string `json:"comment"` + Type VoteTypeEnum `json:"type"` +} + +type EthnicityCriterionInput struct { + Value *EthnicityEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type EyeColorCriterionInput struct { + Value *EyeColorEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Fingerprint struct { + Hash string `json:"hash"` + Algorithm FingerprintAlgorithm `json:"algorithm"` + Duration int `json:"duration"` +} + +type FingerprintInput struct { + Hash string `json:"hash"` + Algorithm FingerprintAlgorithm `json:"algorithm"` + Duration int `json:"duration"` +} + +type FingerprintQueryInput struct { + Hash string `json:"hash"` + Algorithm FingerprintAlgorithm `json:"algorithm"` +} + +type FingerprintSubmission struct { + SceneID string `json:"scene_id"` + Fingerprint *FingerprintInput `json:"fingerprint"` +} + +type FuzzyDate struct { + Date string `json:"date"` + Accuracy DateAccuracyEnum `json:"accuracy"` +} + +type FuzzyDateInput struct { + Date string `json:"date"` + Accuracy DateAccuracyEnum `json:"accuracy"` +} + +type HairColorCriterionInput struct { + Value *HairColorEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type IDCriterionInput struct { + Value []string `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Image struct { + ID string `json:"id"` + URL string `json:"url"` + Width *int `json:"width"` + Height *int `json:"height"` +} + +type ImageCreateInput struct { + URL string `json:"url"` +} + +type ImageDestroyInput struct { + ID string `json:"id"` +} + +type ImageUpdateInput struct { + ID string `json:"id"` + URL string `json:"url"` +} + +type IntCriterionInput struct { + Value int `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Measurements struct { + CupSize *string `json:"cup_size"` + BandSize *int `json:"band_size"` + Waist *int `json:"waist"` + Hip *int `json:"hip"` +} + +type MeasurementsInput struct { + CupSize *string `json:"cup_size"` + BandSize *int `json:"band_size"` + Waist *int `json:"waist"` + Hip *int `json:"hip"` +} + +type MultiIDCriterionInput struct { + Value []string `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Performer struct { + ID string `json:"id"` + Name string `json:"name"` + Disambiguation *string `json:"disambiguation"` + Aliases []string `json:"aliases"` + Gender *GenderEnum `json:"gender"` + Urls []*URL `json:"urls"` + Birthdate *FuzzyDate `json:"birthdate"` + Age *int `json:"age"` + Ethnicity *EthnicityEnum `json:"ethnicity"` + Country *string `json:"country"` + EyeColor *EyeColorEnum `json:"eye_color"` + HairColor *HairColorEnum `json:"hair_color"` + // Height in cm + Height *int `json:"height"` + Measurements *Measurements `json:"measurements"` + BreastType *BreastTypeEnum `json:"breast_type"` + CareerStartYear *int `json:"career_start_year"` + CareerEndYear *int `json:"career_end_year"` + Tattoos []*BodyModification `json:"tattoos"` + Piercings []*BodyModification `json:"piercings"` + Images []*Image `json:"images"` + Deleted bool `json:"deleted"` +} + +func (Performer) IsEditTarget() {} + +type PerformerAppearance struct { + Performer *Performer `json:"performer"` + // Performing as alias + As *string `json:"as"` +} + +type PerformerAppearanceInput struct { + PerformerID string `json:"performer_id"` + // Performing as alias + As *string `json:"as"` +} + +type PerformerCreateInput struct { + Name string `json:"name"` + Disambiguation *string `json:"disambiguation"` + Aliases []string `json:"aliases"` + Gender *GenderEnum `json:"gender"` + Urls []*URLInput `json:"urls"` + Birthdate *FuzzyDateInput `json:"birthdate"` + Ethnicity *EthnicityEnum `json:"ethnicity"` + Country *string `json:"country"` + EyeColor *EyeColorEnum `json:"eye_color"` + HairColor *HairColorEnum `json:"hair_color"` + Height *int `json:"height"` + Measurements *MeasurementsInput `json:"measurements"` + BreastType *BreastTypeEnum `json:"breast_type"` + CareerStartYear *int `json:"career_start_year"` + CareerEndYear *int `json:"career_end_year"` + Tattoos []*BodyModificationInput `json:"tattoos"` + Piercings []*BodyModificationInput `json:"piercings"` + ImageIds []string `json:"image_ids"` +} + +type PerformerDestroyInput struct { + ID string `json:"id"` +} + +type PerformerEdit struct { + Name *string `json:"name"` + Disambiguation *string `json:"disambiguation"` + AddedAliases []string `json:"added_aliases"` + RemovedAliases []string `json:"removed_aliases"` + Gender *GenderEnum `json:"gender"` + AddedUrls []*URL `json:"added_urls"` + RemovedUrls []*URL `json:"removed_urls"` + Birthdate *FuzzyDate `json:"birthdate"` + Ethnicity *EthnicityEnum `json:"ethnicity"` + Country *string `json:"country"` + EyeColor *EyeColorEnum `json:"eye_color"` + HairColor *HairColorEnum `json:"hair_color"` + // Height in cm + Height *int `json:"height"` + Measurements *Measurements `json:"measurements"` + BreastType *BreastTypeEnum `json:"breast_type"` + CareerStartYear *int `json:"career_start_year"` + CareerEndYear *int `json:"career_end_year"` + AddedTattoos []*BodyModification `json:"added_tattoos"` + RemovedTattoos []*BodyModification `json:"removed_tattoos"` + AddedPiercings []*BodyModification `json:"added_piercings"` + RemovedPiercings []*BodyModification `json:"removed_piercings"` + AddedImages []*Image `json:"added_images"` + RemovedImages []*Image `json:"removed_images"` +} + +func (PerformerEdit) IsEditDetails() {} + +type PerformerEditDetailsInput struct { + Name *string `json:"name"` + Disambiguation *string `json:"disambiguation"` + Aliases []string `json:"aliases"` + Gender *GenderEnum `json:"gender"` + Urls []*URLInput `json:"urls"` + Birthdate *FuzzyDateInput `json:"birthdate"` + Ethnicity *EthnicityEnum `json:"ethnicity"` + Country *string `json:"country"` + EyeColor *EyeColorEnum `json:"eye_color"` + HairColor *HairColorEnum `json:"hair_color"` + Height *int `json:"height"` + Measurements *MeasurementsInput `json:"measurements"` + BreastType *BreastTypeEnum `json:"breast_type"` + CareerStartYear *int `json:"career_start_year"` + CareerEndYear *int `json:"career_end_year"` + Tattoos []*BodyModificationInput `json:"tattoos"` + Piercings []*BodyModificationInput `json:"piercings"` + ImageIds []string `json:"image_ids"` +} + +type PerformerEditInput struct { + Edit *EditInput `json:"edit"` + // Not required for destroy type + Details *PerformerEditDetailsInput `json:"details"` +} + +type PerformerFilterType struct { + // Searches name and aliases - assumes like query unless quoted + Names *string `json:"names"` + // Searches name only - assumes like query unless quoted + Name *string `json:"name"` + // Search aliases only - assumes like query unless quoted + Alias *string `json:"alias"` + Disambiguation *StringCriterionInput `json:"disambiguation"` + Gender *GenderEnum `json:"gender"` + // Filter to search urls - assumes like query unless quoted + URL *string `json:"url"` + Birthdate *DateCriterionInput `json:"birthdate"` + BirthYear *IntCriterionInput `json:"birth_year"` + Age *IntCriterionInput `json:"age"` + Ethnicity *EthnicityCriterionInput `json:"ethnicity"` + Country *StringCriterionInput `json:"country"` + EyeColor *EyeColorCriterionInput `json:"eye_color"` + HairColor *HairColorCriterionInput `json:"hair_color"` + Height *IntCriterionInput `json:"height"` + CupSize *StringCriterionInput `json:"cup_size"` + BandSize *IntCriterionInput `json:"band_size"` + WaistSize *IntCriterionInput `json:"waist_size"` + HipSize *IntCriterionInput `json:"hip_size"` + BreastType *BreastTypeCriterionInput `json:"breast_type"` + CareerStartYear *IntCriterionInput `json:"career_start_year"` + CareerEndYear *IntCriterionInput `json:"career_end_year"` + Tattoos *BodyModificationCriterionInput `json:"tattoos"` + Piercings *BodyModificationCriterionInput `json:"piercings"` +} + +type PerformerUpdateInput struct { + ID string `json:"id"` + Name *string `json:"name"` + Disambiguation *string `json:"disambiguation"` + Aliases []string `json:"aliases"` + Gender *GenderEnum `json:"gender"` + Urls []*URLInput `json:"urls"` + Birthdate *FuzzyDateInput `json:"birthdate"` + Ethnicity *EthnicityEnum `json:"ethnicity"` + Country *string `json:"country"` + EyeColor *EyeColorEnum `json:"eye_color"` + HairColor *HairColorEnum `json:"hair_color"` + Height *int `json:"height"` + Measurements *MeasurementsInput `json:"measurements"` + BreastType *BreastTypeEnum `json:"breast_type"` + CareerStartYear *int `json:"career_start_year"` + CareerEndYear *int `json:"career_end_year"` + Tattoos []*BodyModificationInput `json:"tattoos"` + Piercings []*BodyModificationInput `json:"piercings"` + ImageIds []string `json:"image_ids"` +} + +type QueryEditsResultType struct { + Count int `json:"count"` + Edits []*Edit `json:"edits"` +} + +type QueryPerformersResultType struct { + Count int `json:"count"` + Performers []*Performer `json:"performers"` +} + +type QueryScenesResultType struct { + Count int `json:"count"` + Scenes []*Scene `json:"scenes"` +} + +type QuerySpec struct { + Page *int `json:"page"` + PerPage *int `json:"per_page"` + Sort *string `json:"sort"` + Direction *SortDirectionEnum `json:"direction"` +} + +type QueryStudiosResultType struct { + Count int `json:"count"` + Studios []*Studio `json:"studios"` +} + +type QueryTagsResultType struct { + Count int `json:"count"` + Tags []*Tag `json:"tags"` +} + +type QueryUsersResultType struct { + Count int `json:"count"` + Users []*User `json:"users"` +} + +type RoleCriterionInput struct { + Value []RoleEnum `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Scene struct { + ID string `json:"id"` + Title *string `json:"title"` + Details *string `json:"details"` + Date *string `json:"date"` + Urls []*URL `json:"urls"` + Studio *Studio `json:"studio"` + Tags []*Tag `json:"tags"` + Images []*Image `json:"images"` + Performers []*PerformerAppearance `json:"performers"` + Fingerprints []*Fingerprint `json:"fingerprints"` + Duration *int `json:"duration"` + Director *string `json:"director"` + Deleted bool `json:"deleted"` +} + +func (Scene) IsEditTarget() {} + +type SceneCreateInput struct { + Title *string `json:"title"` + Details *string `json:"details"` + Urls []*URLInput `json:"urls"` + Date *string `json:"date"` + StudioID *string `json:"studio_id"` + Performers []*PerformerAppearanceInput `json:"performers"` + TagIds []string `json:"tag_ids"` + ImageIds []string `json:"image_ids"` + Fingerprints []*FingerprintInput `json:"fingerprints"` + Duration *int `json:"duration"` + Director *string `json:"director"` +} + +type SceneDestroyInput struct { + ID string `json:"id"` +} + +type SceneEdit struct { + Title *string `json:"title"` + Details *string `json:"details"` + AddedUrls []*URL `json:"added_urls"` + RemovedUrls []*URL `json:"removed_urls"` + Date *string `json:"date"` + StudioID *string `json:"studio_id"` + // Added or modified performer appearance entries + AddedPerformers []*PerformerAppearance `json:"added_performers"` + RemovedPerformers []*PerformerAppearance `json:"removed_performers"` + AddedTags []*Tag `json:"added_tags"` + RemovedTags []*Tag `json:"removed_tags"` + AddedImages []*Image `json:"added_images"` + RemovedImages []*Image `json:"removed_images"` + AddedFingerprints []*Fingerprint `json:"added_fingerprints"` + RemovedFingerprints []*Fingerprint `json:"removed_fingerprints"` + Duration *int `json:"duration"` + Director *string `json:"director"` +} + +func (SceneEdit) IsEditDetails() {} + +type SceneEditDetailsInput struct { + Title *string `json:"title"` + Details *string `json:"details"` + Urls []*URLInput `json:"urls"` + Date *string `json:"date"` + StudioID *string `json:"studio_id"` + Performers []*PerformerAppearanceInput `json:"performers"` + TagIds []string `json:"tag_ids"` + ImageIds []string `json:"image_ids"` + Fingerprints []*FingerprintInput `json:"fingerprints"` + Duration *int `json:"duration"` + Director *string `json:"director"` +} + +type SceneEditInput struct { + Edit *EditInput `json:"edit"` + // Not required for destroy type + Details *SceneEditDetailsInput `json:"details"` + Duration *int `json:"duration"` +} + +type SceneFilterType struct { + // Filter to search title and details - assumes like query unless quoted + Text *string `json:"text"` + // Filter to search title - assumes like query unless quoted + Title *string `json:"title"` + // Filter to search urls - assumes like query unless quoted + URL *string `json:"url"` + // Filter by date + Date *DateCriterionInput `json:"date"` + // Filter to only include scenes with this studio + Studios *MultiIDCriterionInput `json:"studios"` + // Filter to only include scenes with these tags + Tags *MultiIDCriterionInput `json:"tags"` + // Filter to only include scenes with these performers + Performers *MultiIDCriterionInput `json:"performers"` + // Filter to include scenes with performer appearing as alias + Alias *StringCriterionInput `json:"alias"` +} + +type SceneUpdateInput struct { + ID string `json:"id"` + Title *string `json:"title"` + Details *string `json:"details"` + Urls []*URLInput `json:"urls"` + Date *string `json:"date"` + StudioID *string `json:"studio_id"` + Performers []*PerformerAppearanceInput `json:"performers"` + TagIds []string `json:"tag_ids"` + ImageIds []string `json:"image_ids"` + Fingerprints []*FingerprintInput `json:"fingerprints"` + Duration *int `json:"duration"` + Director *string `json:"director"` +} + +type StringCriterionInput struct { + Value string `json:"value"` + Modifier CriterionModifier `json:"modifier"` +} + +type Studio struct { + ID string `json:"id"` + Name string `json:"name"` + Urls []*URL `json:"urls"` + Parent *Studio `json:"parent"` + ChildStudios []*Studio `json:"child_studios"` + Images []*Image `json:"images"` + Deleted bool `json:"deleted"` +} + +func (Studio) IsEditTarget() {} + +type StudioCreateInput struct { + Name string `json:"name"` + Urls []*URLInput `json:"urls"` + ParentID *string `json:"parent_id"` + ChildStudioIds []string `json:"child_studio_ids"` + ImageIds []string `json:"image_ids"` +} + +type StudioDestroyInput struct { + ID string `json:"id"` +} + +type StudioEdit struct { + Name *string `json:"name"` + // Added and modified URLs + AddedUrls []*URL `json:"added_urls"` + RemovedUrls []*URL `json:"removed_urls"` + Parent *Studio `json:"parent"` + AddedChildStudios []*Studio `json:"added_child_studios"` + RemovedChildStudios []*Studio `json:"removed_child_studios"` + AddedImages []*Image `json:"added_images"` + RemovedImages []*Image `json:"removed_images"` +} + +func (StudioEdit) IsEditDetails() {} + +type StudioEditDetailsInput struct { + Name *string `json:"name"` + Urls []*URLInput `json:"urls"` + ParentID *string `json:"parent_id"` + ChildStudioIds []string `json:"child_studio_ids"` + ImageIds []string `json:"image_ids"` +} + +type StudioEditInput struct { + Edit *EditInput `json:"edit"` + // Not required for destroy type + Details *StudioEditDetailsInput `json:"details"` +} + +type StudioFilterType struct { + // Filter to search name - assumes like query unless quoted + Name *string `json:"name"` + // Filter to search url - assumes like query unless quoted + URL *string `json:"url"` + Parent *IDCriterionInput `json:"parent"` +} + +type StudioUpdateInput struct { + ID string `json:"id"` + Name *string `json:"name"` + Urls []*URLInput `json:"urls"` + ParentID *string `json:"parent_id"` + ChildStudioIds []string `json:"child_studio_ids"` + ImageIds []string `json:"image_ids"` +} + +type Tag struct { + ID string `json:"id"` + Name string `json:"name"` + Description *string `json:"description"` + Aliases []string `json:"aliases"` + Deleted bool `json:"deleted"` + Edits []*Edit `json:"edits"` +} + +func (Tag) IsEditTarget() {} + +type TagCreateInput struct { + Name string `json:"name"` + Description *string `json:"description"` + Aliases []string `json:"aliases"` +} + +type TagDestroyInput struct { + ID string `json:"id"` +} + +type TagEdit struct { + Name *string `json:"name"` + Description *string `json:"description"` + AddedAliases []string `json:"added_aliases"` + RemovedAliases []string `json:"removed_aliases"` +} + +func (TagEdit) IsEditDetails() {} + +type TagEditDetailsInput struct { + Name *string `json:"name"` + Description *string `json:"description"` + Aliases []string `json:"aliases"` +} + +type TagEditInput struct { + Edit *EditInput `json:"edit"` + // Not required for destroy type + Details *TagEditDetailsInput `json:"details"` +} + +type TagFilterType struct { + // Filter to search name, aliases and description - assumes like query unless quoted + Text *string `json:"text"` + // Searches name and aliases - assumes like query unless quoted + Names *string `json:"names"` + // Filter to search name - assumes like query unless quoted + Name *string `json:"name"` +} + +type TagUpdateInput struct { + ID string `json:"id"` + Name *string `json:"name"` + Description *string `json:"description"` + Aliases []string `json:"aliases"` +} + +type URL struct { + URL string `json:"url"` + Type string `json:"type"` +} + +type URLInput struct { + URL string `json:"url"` + Type string `json:"type"` +} + +type User struct { + ID string `json:"id"` + Name string `json:"name"` + // Should not be visible to other users + Roles []RoleEnum `json:"roles"` + // Should not be visible to other users + Email *string `json:"email"` + // Should not be visible to other users + APIKey *string `json:"api_key"` + SuccessfulEdits int `json:"successful_edits"` + UnsuccessfulEdits int `json:"unsuccessful_edits"` + SuccessfulVotes int `json:"successful_votes"` + // Votes on unsuccessful edits + UnsuccessfulVotes int `json:"unsuccessful_votes"` + // Calls to the API from this user over a configurable time period + APICalls int `json:"api_calls"` +} + +type UserChangePasswordInput struct { + // Password in plain text + ExistingPassword string `json:"existing_password"` + NewPassword string `json:"new_password"` +} + +type UserCreateInput struct { + Name string `json:"name"` + // Password in plain text + Password string `json:"password"` + Roles []RoleEnum `json:"roles"` + Email string `json:"email"` +} + +type UserDestroyInput struct { + ID string `json:"id"` +} + +type UserFilterType struct { + // Filter to search user name - assumes like query unless quoted + Name *string `json:"name"` + // Filter to search email - assumes like query unless quoted + Email *string `json:"email"` + // Filter by roles + Roles *RoleCriterionInput `json:"roles"` + // Filter by api key + APIKey *string `json:"apiKey"` + // Filter by successful edits + SuccessfulEdits *IntCriterionInput `json:"successful_edits"` + // Filter by unsuccessful edits + UnsuccessfulEdits *IntCriterionInput `json:"unsuccessful_edits"` + // Filter by votes on successful edits + SuccessfulVotes *IntCriterionInput `json:"successful_votes"` + // Filter by votes on unsuccessful edits + UnsuccessfulVotes *IntCriterionInput `json:"unsuccessful_votes"` + // Filter by number of API calls + APICalls *IntCriterionInput `json:"api_calls"` +} + +type UserUpdateInput struct { + ID string `json:"id"` + Name *string `json:"name"` + // Password in plain text + Password *string `json:"password"` + Roles []RoleEnum `json:"roles"` + Email *string `json:"email"` +} + +type Version struct { + Hash string `json:"hash"` + BuildTime string `json:"build_time"` + Version string `json:"version"` +} + +type VoteComment struct { + User *User `json:"user"` + Date *string `json:"date"` + Comment *string `json:"comment"` + Type *VoteTypeEnum `json:"type"` +} + +type BreastTypeEnum string + +const ( + BreastTypeEnumNatural BreastTypeEnum = "NATURAL" + BreastTypeEnumFake BreastTypeEnum = "FAKE" + BreastTypeEnumNa BreastTypeEnum = "NA" +) + +var AllBreastTypeEnum = []BreastTypeEnum{ + BreastTypeEnumNatural, + BreastTypeEnumFake, + BreastTypeEnumNa, +} + +func (e BreastTypeEnum) IsValid() bool { + switch e { + case BreastTypeEnumNatural, BreastTypeEnumFake, BreastTypeEnumNa: + return true + } + return false +} + +func (e BreastTypeEnum) String() string { + return string(e) +} + +func (e *BreastTypeEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = BreastTypeEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid BreastTypeEnum", str) + } + return nil +} + +func (e BreastTypeEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type CriterionModifier string + +const ( + // = + CriterionModifierEquals CriterionModifier = "EQUALS" + // != + CriterionModifierNotEquals CriterionModifier = "NOT_EQUALS" + // > + CriterionModifierGreaterThan CriterionModifier = "GREATER_THAN" + // < + CriterionModifierLessThan CriterionModifier = "LESS_THAN" + // IS NULL + CriterionModifierIsNull CriterionModifier = "IS_NULL" + // IS NOT NULL + CriterionModifierNotNull CriterionModifier = "NOT_NULL" + // INCLUDES ALL + CriterionModifierIncludesAll CriterionModifier = "INCLUDES_ALL" + CriterionModifierIncludes CriterionModifier = "INCLUDES" + CriterionModifierExcludes CriterionModifier = "EXCLUDES" +) + +var AllCriterionModifier = []CriterionModifier{ + CriterionModifierEquals, + CriterionModifierNotEquals, + CriterionModifierGreaterThan, + CriterionModifierLessThan, + CriterionModifierIsNull, + CriterionModifierNotNull, + CriterionModifierIncludesAll, + CriterionModifierIncludes, + CriterionModifierExcludes, +} + +func (e CriterionModifier) IsValid() bool { + switch e { + case CriterionModifierEquals, CriterionModifierNotEquals, CriterionModifierGreaterThan, CriterionModifierLessThan, CriterionModifierIsNull, CriterionModifierNotNull, CriterionModifierIncludesAll, CriterionModifierIncludes, CriterionModifierExcludes: + return true + } + return false +} + +func (e CriterionModifier) String() string { + return string(e) +} + +func (e *CriterionModifier) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = CriterionModifier(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid CriterionModifier", str) + } + return nil +} + +func (e CriterionModifier) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type DateAccuracyEnum string + +const ( + DateAccuracyEnumYear DateAccuracyEnum = "YEAR" + DateAccuracyEnumMonth DateAccuracyEnum = "MONTH" + DateAccuracyEnumDay DateAccuracyEnum = "DAY" +) + +var AllDateAccuracyEnum = []DateAccuracyEnum{ + DateAccuracyEnumYear, + DateAccuracyEnumMonth, + DateAccuracyEnumDay, +} + +func (e DateAccuracyEnum) IsValid() bool { + switch e { + case DateAccuracyEnumYear, DateAccuracyEnumMonth, DateAccuracyEnumDay: + return true + } + return false +} + +func (e DateAccuracyEnum) String() string { + return string(e) +} + +func (e *DateAccuracyEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = DateAccuracyEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid DateAccuracyEnum", str) + } + return nil +} + +func (e DateAccuracyEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type EthnicityEnum string + +const ( + EthnicityEnumCaucasian EthnicityEnum = "CAUCASIAN" + EthnicityEnumBlack EthnicityEnum = "BLACK" + EthnicityEnumAsian EthnicityEnum = "ASIAN" + EthnicityEnumIndian EthnicityEnum = "INDIAN" + EthnicityEnumLatin EthnicityEnum = "LATIN" + EthnicityEnumMiddleEastern EthnicityEnum = "MIDDLE_EASTERN" + EthnicityEnumMixed EthnicityEnum = "MIXED" + EthnicityEnumOther EthnicityEnum = "OTHER" +) + +var AllEthnicityEnum = []EthnicityEnum{ + EthnicityEnumCaucasian, + EthnicityEnumBlack, + EthnicityEnumAsian, + EthnicityEnumIndian, + EthnicityEnumLatin, + EthnicityEnumMiddleEastern, + EthnicityEnumMixed, + EthnicityEnumOther, +} + +func (e EthnicityEnum) IsValid() bool { + switch e { + case EthnicityEnumCaucasian, EthnicityEnumBlack, EthnicityEnumAsian, EthnicityEnumIndian, EthnicityEnumLatin, EthnicityEnumMiddleEastern, EthnicityEnumMixed, EthnicityEnumOther: + return true + } + return false +} + +func (e EthnicityEnum) String() string { + return string(e) +} + +func (e *EthnicityEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = EthnicityEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid EthnicityEnum", str) + } + return nil +} + +func (e EthnicityEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type EyeColorEnum string + +const ( + EyeColorEnumBlue EyeColorEnum = "BLUE" + EyeColorEnumBrown EyeColorEnum = "BROWN" + EyeColorEnumGrey EyeColorEnum = "GREY" + EyeColorEnumGreen EyeColorEnum = "GREEN" + EyeColorEnumHazel EyeColorEnum = "HAZEL" + EyeColorEnumRed EyeColorEnum = "RED" +) + +var AllEyeColorEnum = []EyeColorEnum{ + EyeColorEnumBlue, + EyeColorEnumBrown, + EyeColorEnumGrey, + EyeColorEnumGreen, + EyeColorEnumHazel, + EyeColorEnumRed, +} + +func (e EyeColorEnum) IsValid() bool { + switch e { + case EyeColorEnumBlue, EyeColorEnumBrown, EyeColorEnumGrey, EyeColorEnumGreen, EyeColorEnumHazel, EyeColorEnumRed: + return true + } + return false +} + +func (e EyeColorEnum) String() string { + return string(e) +} + +func (e *EyeColorEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = EyeColorEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid EyeColorEnum", str) + } + return nil +} + +func (e EyeColorEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type FingerprintAlgorithm string + +const ( + FingerprintAlgorithmMd5 FingerprintAlgorithm = "MD5" + FingerprintAlgorithmOshash FingerprintAlgorithm = "OSHASH" +) + +var AllFingerprintAlgorithm = []FingerprintAlgorithm{ + FingerprintAlgorithmMd5, + FingerprintAlgorithmOshash, +} + +func (e FingerprintAlgorithm) IsValid() bool { + switch e { + case FingerprintAlgorithmMd5, FingerprintAlgorithmOshash: + return true + } + return false +} + +func (e FingerprintAlgorithm) String() string { + return string(e) +} + +func (e *FingerprintAlgorithm) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = FingerprintAlgorithm(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid FingerprintAlgorithm", str) + } + return nil +} + +func (e FingerprintAlgorithm) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type GenderEnum string + +const ( + GenderEnumMale GenderEnum = "MALE" + GenderEnumFemale GenderEnum = "FEMALE" + GenderEnumTransgenderMale GenderEnum = "TRANSGENDER_MALE" + GenderEnumTransgenderFemale GenderEnum = "TRANSGENDER_FEMALE" + GenderEnumIntersex GenderEnum = "INTERSEX" +) + +var AllGenderEnum = []GenderEnum{ + GenderEnumMale, + GenderEnumFemale, + GenderEnumTransgenderMale, + GenderEnumTransgenderFemale, + GenderEnumIntersex, +} + +func (e GenderEnum) IsValid() bool { + switch e { + case GenderEnumMale, GenderEnumFemale, GenderEnumTransgenderMale, GenderEnumTransgenderFemale, GenderEnumIntersex: + return true + } + return false +} + +func (e GenderEnum) String() string { + return string(e) +} + +func (e *GenderEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = GenderEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid GenderEnum", str) + } + return nil +} + +func (e GenderEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type HairColorEnum string + +const ( + HairColorEnumBlonde HairColorEnum = "BLONDE" + HairColorEnumBrunette HairColorEnum = "BRUNETTE" + HairColorEnumBlack HairColorEnum = "BLACK" + HairColorEnumRed HairColorEnum = "RED" + HairColorEnumAuburn HairColorEnum = "AUBURN" + HairColorEnumGrey HairColorEnum = "GREY" + HairColorEnumBald HairColorEnum = "BALD" + HairColorEnumVarious HairColorEnum = "VARIOUS" + HairColorEnumOther HairColorEnum = "OTHER" +) + +var AllHairColorEnum = []HairColorEnum{ + HairColorEnumBlonde, + HairColorEnumBrunette, + HairColorEnumBlack, + HairColorEnumRed, + HairColorEnumAuburn, + HairColorEnumGrey, + HairColorEnumBald, + HairColorEnumVarious, + HairColorEnumOther, +} + +func (e HairColorEnum) IsValid() bool { + switch e { + case HairColorEnumBlonde, HairColorEnumBrunette, HairColorEnumBlack, HairColorEnumRed, HairColorEnumAuburn, HairColorEnumGrey, HairColorEnumBald, HairColorEnumVarious, HairColorEnumOther: + return true + } + return false +} + +func (e HairColorEnum) String() string { + return string(e) +} + +func (e *HairColorEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = HairColorEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid HairColorEnum", str) + } + return nil +} + +func (e HairColorEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type OperationEnum string + +const ( + OperationEnumCreate OperationEnum = "CREATE" + OperationEnumModify OperationEnum = "MODIFY" + OperationEnumDestroy OperationEnum = "DESTROY" + OperationEnumMerge OperationEnum = "MERGE" +) + +var AllOperationEnum = []OperationEnum{ + OperationEnumCreate, + OperationEnumModify, + OperationEnumDestroy, + OperationEnumMerge, +} + +func (e OperationEnum) IsValid() bool { + switch e { + case OperationEnumCreate, OperationEnumModify, OperationEnumDestroy, OperationEnumMerge: + return true + } + return false +} + +func (e OperationEnum) String() string { + return string(e) +} + +func (e *OperationEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = OperationEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid OperationEnum", str) + } + return nil +} + +func (e OperationEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type RoleEnum string + +const ( + RoleEnumRead RoleEnum = "READ" + RoleEnumVote RoleEnum = "VOTE" + RoleEnumEdit RoleEnum = "EDIT" + RoleEnumModify RoleEnum = "MODIFY" + RoleEnumAdmin RoleEnum = "ADMIN" +) + +var AllRoleEnum = []RoleEnum{ + RoleEnumRead, + RoleEnumVote, + RoleEnumEdit, + RoleEnumModify, + RoleEnumAdmin, +} + +func (e RoleEnum) IsValid() bool { + switch e { + case RoleEnumRead, RoleEnumVote, RoleEnumEdit, RoleEnumModify, RoleEnumAdmin: + return true + } + return false +} + +func (e RoleEnum) String() string { + return string(e) +} + +func (e *RoleEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = RoleEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid RoleEnum", str) + } + return nil +} + +func (e RoleEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type SortDirectionEnum string + +const ( + SortDirectionEnumAsc SortDirectionEnum = "ASC" + SortDirectionEnumDesc SortDirectionEnum = "DESC" +) + +var AllSortDirectionEnum = []SortDirectionEnum{ + SortDirectionEnumAsc, + SortDirectionEnumDesc, +} + +func (e SortDirectionEnum) IsValid() bool { + switch e { + case SortDirectionEnumAsc, SortDirectionEnumDesc: + return true + } + return false +} + +func (e SortDirectionEnum) String() string { + return string(e) +} + +func (e *SortDirectionEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = SortDirectionEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid SortDirectionEnum", str) + } + return nil +} + +func (e SortDirectionEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type TargetTypeEnum string + +const ( + TargetTypeEnumScene TargetTypeEnum = "SCENE" + TargetTypeEnumStudio TargetTypeEnum = "STUDIO" + TargetTypeEnumPerformer TargetTypeEnum = "PERFORMER" + TargetTypeEnumTag TargetTypeEnum = "TAG" +) + +var AllTargetTypeEnum = []TargetTypeEnum{ + TargetTypeEnumScene, + TargetTypeEnumStudio, + TargetTypeEnumPerformer, + TargetTypeEnumTag, +} + +func (e TargetTypeEnum) IsValid() bool { + switch e { + case TargetTypeEnumScene, TargetTypeEnumStudio, TargetTypeEnumPerformer, TargetTypeEnumTag: + return true + } + return false +} + +func (e TargetTypeEnum) String() string { + return string(e) +} + +func (e *TargetTypeEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = TargetTypeEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid TargetTypeEnum", str) + } + return nil +} + +func (e TargetTypeEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type VoteStatusEnum string + +const ( + VoteStatusEnumAccepted VoteStatusEnum = "ACCEPTED" + VoteStatusEnumRejected VoteStatusEnum = "REJECTED" + VoteStatusEnumPending VoteStatusEnum = "PENDING" + VoteStatusEnumImmediateAccepted VoteStatusEnum = "IMMEDIATE_ACCEPTED" + VoteStatusEnumImmediateRejected VoteStatusEnum = "IMMEDIATE_REJECTED" +) + +var AllVoteStatusEnum = []VoteStatusEnum{ + VoteStatusEnumAccepted, + VoteStatusEnumRejected, + VoteStatusEnumPending, + VoteStatusEnumImmediateAccepted, + VoteStatusEnumImmediateRejected, +} + +func (e VoteStatusEnum) IsValid() bool { + switch e { + case VoteStatusEnumAccepted, VoteStatusEnumRejected, VoteStatusEnumPending, VoteStatusEnumImmediateAccepted, VoteStatusEnumImmediateRejected: + return true + } + return false +} + +func (e VoteStatusEnum) String() string { + return string(e) +} + +func (e *VoteStatusEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = VoteStatusEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid VoteStatusEnum", str) + } + return nil +} + +func (e VoteStatusEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type VoteTypeEnum string + +const ( + VoteTypeEnumComment VoteTypeEnum = "COMMENT" + VoteTypeEnumAccept VoteTypeEnum = "ACCEPT" + VoteTypeEnumReject VoteTypeEnum = "REJECT" + // Immediately accepts the edit - bypassing the vote + VoteTypeEnumImmediateAccept VoteTypeEnum = "IMMEDIATE_ACCEPT" + // Immediately rejects the edit - bypassing the vote + VoteTypeEnumImmediateReject VoteTypeEnum = "IMMEDIATE_REJECT" +) + +var AllVoteTypeEnum = []VoteTypeEnum{ + VoteTypeEnumComment, + VoteTypeEnumAccept, + VoteTypeEnumReject, + VoteTypeEnumImmediateAccept, + VoteTypeEnumImmediateReject, +} + +func (e VoteTypeEnum) IsValid() bool { + switch e { + case VoteTypeEnumComment, VoteTypeEnumAccept, VoteTypeEnumReject, VoteTypeEnumImmediateAccept, VoteTypeEnumImmediateReject: + return true + } + return false +} + +func (e VoteTypeEnum) String() string { + return string(e) +} + +func (e *VoteTypeEnum) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = VoteTypeEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid VoteTypeEnum", str) + } + return nil +} + +func (e VoteTypeEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/pkg/scraper/stashbox/stash_box.go b/pkg/scraper/stashbox/stash_box.go new file mode 100644 index 000000000..d2c9a3e78 --- /dev/null +++ b/pkg/scraper/stashbox/stash_box.go @@ -0,0 +1,315 @@ +package stashbox + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + "strconv" + "strings" + "time" + + "github.com/Yamashou/gqlgenc/client" + + "github.com/stashapp/stash/pkg/logger" + "github.com/stashapp/stash/pkg/models" + "github.com/stashapp/stash/pkg/scraper/stashbox/graphql" + "github.com/stashapp/stash/pkg/utils" +) + +// Timeout to get the image. Includes transfer time. May want to make this +// configurable at some point. +const imageGetTimeout = time.Second * 30 + +// Client represents the client interface to a stash-box server instance. +type Client struct { + client *graphql.Client +} + +// NewClient returns a new instance of a stash-box client. +func NewClient(box models.StashBox) *Client { + authHeader := func(req *http.Request) { + req.Header.Set("ApiKey", box.APIKey) + } + + client := &graphql.Client{ + Client: client.NewClient(http.DefaultClient, box.Endpoint, authHeader), + } + + return &Client{ + client: client, + } +} + +// QueryStashBoxScene queries stash-box for scenes using a query string. +func (c Client) QueryStashBoxScene(queryStr string) ([]*models.ScrapedScene, error) { + scenes, err := c.client.SearchScene(context.TODO(), queryStr) + if err != nil { + return nil, err + } + + sceneFragments := scenes.SearchScene + + var ret []*models.ScrapedScene + for _, s := range sceneFragments { + ss, err := sceneFragmentToScrapedScene(s) + if err != nil { + return nil, err + } + ret = append(ret, ss) + } + + return ret, nil +} + +// FindStashBoxScenesByFingerprints queries stash-box for scenes using every +// scene's MD5 checksum and/or oshash. +func (c Client) FindStashBoxScenesByFingerprints(sceneIDs []string) ([]*models.ScrapedScene, error) { + qb := models.NewSceneQueryBuilder() + + var fingerprints []string + + for _, sceneID := range sceneIDs { + idInt, _ := strconv.Atoi(sceneID) + scene, err := qb.Find(idInt) + if err != nil { + return nil, err + } + + if scene == nil { + return nil, fmt.Errorf("scene with id %d not found", idInt) + } + + if scene.Checksum.Valid { + fingerprints = append(fingerprints, scene.Checksum.String) + } + + if scene.OSHash.Valid { + fingerprints = append(fingerprints, scene.OSHash.String) + } + } + + return c.findStashBoxScenesByFingerprints(fingerprints) +} + +func (c Client) findStashBoxScenesByFingerprints(fingerprints []string) ([]*models.ScrapedScene, error) { + scenes, err := c.client.FindScenesByFingerprints(context.TODO(), fingerprints) + + if err != nil { + return nil, err + } + + sceneFragments := scenes.FindScenesByFingerprints + + var ret []*models.ScrapedScene + for _, s := range sceneFragments { + ss, err := sceneFragmentToScrapedScene(s) + if err != nil { + return nil, err + } + ret = append(ret, ss) + } + + return ret, nil +} + +func findURL(urls []*graphql.URLFragment, urlType string) *string { + for _, u := range urls { + if u.Type == urlType { + ret := u.URL + return &ret + } + } + + return nil +} + +func enumToStringPtr(e fmt.Stringer) *string { + if e != nil { + ret := e.String() + return &ret + } + + return nil +} + +func formatMeasurements(m graphql.MeasurementsFragment) *string { + if m.BandSize != nil && m.CupSize != nil && m.Hip != nil && m.Waist != nil { + ret := fmt.Sprintf("%d%s-%d-%d", *m.BandSize, *m.CupSize, *m.Waist, *m.Hip) + return &ret + } + + return nil +} + +func formatCareerLength(start, end *int) *string { + if start == nil && end == nil { + return nil + } + + var ret string + if end == nil { + ret = fmt.Sprintf("%d -", *start) + } else { + ret = fmt.Sprintf("%d - %d", *start, *end) + } + + return &ret +} + +func formatBodyModifications(m []*graphql.BodyModificationFragment) *string { + if len(m) == 0 { + return nil + } + + var retSlice []string + for _, f := range m { + if f.Description == nil { + retSlice = append(retSlice, f.Location) + } else { + retSlice = append(retSlice, fmt.Sprintf("%s, %s", f.Location, *f.Description)) + } + } + + ret := strings.Join(retSlice, "; ") + return &ret +} + +func fetchImage(url string) (*string, error) { + client := &http.Client{ + Timeout: imageGetTimeout, + } + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + + resp, err := client.Do(req) + + if err != nil { + return nil, err + } + + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + // determine the image type and set the base64 type + contentType := resp.Header.Get("Content-Type") + if contentType == "" { + contentType = http.DetectContentType(body) + } + + img := "data:" + contentType + ";base64," + utils.GetBase64StringFromData(body) + return &img, nil +} + +func performerFragmentToScrapedScenePerformer(p graphql.PerformerFragment) *models.ScrapedScenePerformer { + sp := &models.ScrapedScenePerformer{ + Name: p.Name, + Country: p.Country, + Measurements: formatMeasurements(p.Measurements), + CareerLength: formatCareerLength(p.CareerStartYear, p.CareerEndYear), + Tattoos: formatBodyModifications(p.Tattoos), + Piercings: formatBodyModifications(p.Piercings), + Twitter: findURL(p.Urls, "TWITTER"), + // TODO - Image - should be returned as a set of URLs. Will need a + // graphql schema change to accommodate this. Leave off for now. + } + + if p.Height != nil { + hs := strconv.Itoa(*p.Height) + sp.Height = &hs + } + + if p.Birthdate != nil { + b := p.Birthdate.Date + sp.Birthdate = &b + } + + if p.Gender != nil { + sp.Gender = enumToStringPtr(p.Gender) + } + + if p.Ethnicity != nil { + sp.Ethnicity = enumToStringPtr(p.Ethnicity) + } + + if p.EyeColor != nil { + sp.EyeColor = enumToStringPtr(p.EyeColor) + } + + if p.BreastType != nil { + sp.FakeTits = enumToStringPtr(p.BreastType) + } + + return sp +} + +func getFirstImage(images []*graphql.ImageFragment) *string { + ret, err := fetchImage(images[0].URL) + if err != nil { + logger.Warnf("Error fetching image %s: %s", images[0].URL, err.Error()) + } + + return ret +} + +func sceneFragmentToScrapedScene(s *graphql.SceneFragment) (*models.ScrapedScene, error) { + ss := &models.ScrapedScene{ + Title: s.Title, + Date: s.Date, + Details: s.Details, + URL: findURL(s.Urls, "STUDIO"), + // Image + // stash_id + } + + if len(s.Images) > 0 { + // TODO - #454 code sorts images by aspect ratio according to a wanted + // orientation. I'm just grabbing the first for now + ss.Image = getFirstImage(s.Images) + } + + if s.Studio != nil { + ss.Studio = &models.ScrapedSceneStudio{ + Name: s.Studio.Name, + URL: findURL(s.Studio.Urls, "HOME"), + } + + err := models.MatchScrapedSceneStudio(ss.Studio) + if err != nil { + return nil, err + } + } + + for _, p := range s.Performers { + sp := performerFragmentToScrapedScenePerformer(p.Performer) + + err := models.MatchScrapedScenePerformer(sp) + if err != nil { + return nil, err + } + + ss.Performers = append(ss.Performers, sp) + } + + for _, t := range s.Tags { + st := &models.ScrapedSceneTag{ + Name: t.Name, + } + + err := models.MatchScrapedSceneTag(st) + if err != nil { + return nil, err + } + + ss.Tags = append(ss.Tags, st) + } + + return ss, nil +} diff --git a/tools.go b/tools.go index 5e0f780d9..9bc7b212d 100644 --- a/tools.go +++ b/tools.go @@ -4,5 +4,6 @@ package main import ( _ "github.com/99designs/gqlgen" + _ "github.com/Yamashou/gqlgenc" _ "github.com/vektra/mockery/v2" ) diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx index ab7ea6b3d..3299e4bca 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx @@ -14,6 +14,8 @@ import { useListSceneScrapers, useSceneUpdate, mutateReloadScrapers, + useConfiguration, + queryStashBoxScene, } from "src/core/StashService"; import { PerformerSelect, @@ -62,6 +64,8 @@ export const SceneEditPanel: React.FC = (props: IProps) => { const [coverImagePreview, setCoverImagePreview] = useState(); + const stashConfig = useConfiguration(); + // Network state const [isLoading, setIsLoading] = useState(true); @@ -117,7 +121,7 @@ export const SceneEditPanel: React.FC = (props: IProps) => { ); setQueryableScrapers(newQueryableScrapers); - }, [Scrapers]); + }, [Scrapers, stashConfig]); useEffect(() => { let changed = false; @@ -251,11 +255,40 @@ export const SceneEditPanel: React.FC = (props: IProps) => { ImageUtils.onImageChange(event, onImageLoad); } + async function onScrapeStashBoxClicked(stashBoxIndex: number) { + setIsLoading(true); + try { + const result = await queryStashBoxScene(stashBoxIndex, props.scene.id); + if (!result.data || !result.data.queryStashBoxScene) { + return; + } + + if (result.data.queryStashBoxScene.length > 0) { + setScrapedScene(result.data.queryStashBoxScene[0]); + } else { + Toast.success({ + content: "No scenes found", + }); + } + } catch (e) { + Toast.error(e); + } finally { + setIsLoading(false); + } + } + + // function onStashBoxQueryClicked(/* stashBoxIndex: number */) { + // TODO + // } + async function onScrapeClicked(scraper: GQL.Scraper) { setIsLoading(true); try { const result = await queryScrapeScene(scraper.id, getSceneInput()); if (!result.data || !result.data.scrapeScene) { + Toast.success({ + content: "No scenes found", + }); return; } setScrapedScene(result.data.scrapeScene); @@ -309,8 +342,23 @@ export const SceneEditPanel: React.FC = (props: IProps) => { } function renderScraperMenu() { + const stashBoxes = stashConfig.data?.configuration.general.stashBoxes ?? []; + + // TODO - change name based on stashbox configuration return ( - + + {stashBoxes.map((s, index) => ( + onScrapeStashBoxClicked(index)} + > + stash-box + + ))} {queryableScrapers.map((s) => ( onScrapeClicked(s)}> {s.name} @@ -326,6 +374,44 @@ export const SceneEditPanel: React.FC = (props: IProps) => { ); } + function maybeRenderStashboxQueryButton() { + // const stashBoxes = stashConfig.data?.configuration.general.stashBoxes ?? []; + // if (stashBoxes.length === 0) { + // return; + // } + // TODO - hide this button for now, with the view to add it when we get + // the query dialog going + // if (stashBoxes.length === 1) { + // return ( + // + // ); + // } + // // TODO - change name based on stashbox configuration + // return ( + // + // + // + // + // + // {stashBoxes.map((s, index) => ( + // onStashBoxQueryClicked(index)} + // > + // stash-box + // + // ))} + // + // + // ); + } + function urlScrapable(scrapedUrl: string): boolean { return (Scrapers?.data?.listSceneScrapers ?? []).some((s) => (s?.scene?.urls ?? []).some((u) => scrapedUrl.includes(u)) @@ -432,7 +518,7 @@ export const SceneEditPanel: React.FC = (props: IProps) => {
{maybeRenderScrapeDialog()}
-
+
@@ -444,7 +530,10 @@ export const SceneEditPanel: React.FC = (props: IProps) => { Delete
- {renderScraperMenu()} + + {maybeRenderStashboxQueryButton()} + {renderScraperMenu()} +
diff --git a/ui/v2.5/src/core/StashService.ts b/ui/v2.5/src/core/StashService.ts index 797efa047..2c7097789 100644 --- a/ui/v2.5/src/core/StashService.ts +++ b/ui/v2.5/src/core/StashService.ts @@ -498,6 +498,17 @@ export const queryScrapeScene = ( fetchPolicy: "network-only", }); +export const queryStashBoxScene = (stashBoxIndex: number, sceneID: string) => + client.query({ + query: GQL.QueryStashBoxSceneDocument, + variables: { + input: { + stash_box_index: stashBoxIndex, + scene_ids: [sceneID], + }, + }, + }); + export const mutateReloadScrapers = () => client.mutate({ mutation: GQL.ReloadScrapersDocument, diff --git a/vendor/github.com/99designs/gqlgen/.gitignore b/vendor/github.com/99designs/gqlgen/.gitignore index 3dbd96815..b918d6a6f 100644 --- a/vendor/github.com/99designs/gqlgen/.gitignore +++ b/vendor/github.com/99designs/gqlgen/.gitignore @@ -4,6 +4,8 @@ /integration/node_modules /integration/schema-fetched.graphql /example/chat/package-lock.json +/example/federation/package-lock.json +/example/federation/node_modules /codegen/gen /gen diff --git a/vendor/github.com/99designs/gqlgen/.golangci.yml b/vendor/github.com/99designs/gqlgen/.golangci.yml index 2239d630a..8d5138680 100644 --- a/vendor/github.com/99designs/gqlgen/.golangci.yml +++ b/vendor/github.com/99designs/gqlgen/.golangci.yml @@ -1,3 +1,39 @@ +run: + tests: true + skip-dirs: + - bin + linters-settings: errcheck: ignore: fmt:.*,[rR]ead|[wW]rite|[cC]lose,io:Copy + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dupl + - errcheck + - gocritic + - gofmt + - goimports + - gosimple + - govet + - ineffassign + - interfacer + - misspell + - nakedret + - prealloc + - staticcheck + - structcheck + - unconvert + - unused + - varcheck + +issues: + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - dupl diff --git a/vendor/github.com/99designs/gqlgen/LICENSE b/vendor/github.com/99designs/gqlgen/LICENSE index 18e1b2493..10bb21c07 100644 --- a/vendor/github.com/99designs/gqlgen/LICENSE +++ b/vendor/github.com/99designs/gqlgen/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018 Adam Scarr +Copyright (c) 2020 gqlgen authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/99designs/gqlgen/README.md b/vendor/github.com/99designs/gqlgen/README.md index 0b302bdd5..0543bc373 100644 --- a/vendor/github.com/99designs/gqlgen/README.md +++ b/vendor/github.com/99designs/gqlgen/README.md @@ -1,20 +1,24 @@ -# gqlgen [![CircleCI](https://badgen.net/circleci/github/99designs/gqlgen/master)](https://circleci.com/gh/99designs/gqlgen) [![Read the Docs](https://badgen.net/badge/docs/available/green)](http://gqlgen.com/) +# gqlgen [![Continuous Integration](https://github.com/99designs/gqlgen/workflows/Continuous%20Integration/badge.svg)](https://github.com/99designs/gqlgen/actions) [![Read the Docs](https://badgen.net/badge/docs/available/green)](http://gqlgen.com/) [![GoDoc](https://godoc.org/github.com/99designs/gqlgen?status.svg)](https://godoc.org/github.com/99designs/gqlgen) + +![gqlgen](https://user-images.githubusercontent.com/46195831/89802919-0bb8ef00-db2a-11ea-8ba4-88e7a58b2fd2.png) ## What is gqlgen? -[gqlgen](https://github.com/99designs/gqlgen) is a Go library for building GraphQL servers without any fuss. gqlgen is: +[gqlgen](https://github.com/99designs/gqlgen) is a Go library for building GraphQL servers without any fuss.
- - **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. +- **gqlgen is based on a Schema first approach** — You get to Define your API using the GraphQL [Schema Definition Language](http://graphql.org/learn/schema/). +- **gqlgen priortizes Type safety** — You should never see `map[string]interface{}` here. +- **gqlgen enables Codegen** — We generate the boring bits, so you can focus on building your app quickly. -[Feature Comparison](https://gqlgen.com/feature-comparison/) +Still not convinced enough to use **gqlgen**? Compare **gqlgen** with other Go graphql [implementations](https://gqlgen.com/feature-comparison/) ## Getting Started +- To install gqlgen run the comand `go get github.com/99designs/gqlgen` in your project directory.
+- You could initialize a new project using the recommended folder structure by running this command `go run github.com/99designs/gqlgen init`. -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. +You could find a more comprehensive guide to help you get started [here](https://gqlgen.com/getting-started/).
+We also have a couple of real-world [examples](https://github.com/99designs/gqlgen/tree/master/example) that show how to GraphQL applicatons with **gqlgen** seamlessly, +You can see these [examples](https://github.com/99designs/gqlgen/tree/master/example) here or visit [godoc](https://godoc.org/github.com/99designs/gqlgen). ## Reporting Issues @@ -22,10 +26,88 @@ If you think you've found a bug, or something isn't behaving the way you think i ## Contributing -Read our [Contribution Guidelines](https://github.com/99designs/gqlgen/blob/master/CONTRIBUTING.md) for information on how you can help out gqlgen. +We welcome contributions, Read our [Contribution Guidelines](https://github.com/99designs/gqlgen/blob/master/CONTRIBUTING.md) to learn more about contributing to **gqlgen** +## Frequently asked questions + +### How do I prevent fetching child objects that might not be used? + +When you have nested or recursive schema like this: + +```graphql +type User { + id: ID! + name: String! + friends: [User!]! +} +``` + +You need to tell gqlgen that it should only fetch friends if the user requested it. There are two ways to do this; + +- #### Using Custom Models + +Write a custom model that omits the friends field: + +```go +type User struct { + ID int + Name string +} +``` + +And reference the model in `gqlgen.yml`: + +```yaml +# gqlgen.yml +models: + User: + model: github.com/you/pkg/model.User # go import path to the User struct above +``` + +- #### Using Explicit Resolvers + +If you want to Keep using the generated model, mark the field as requiring a resolver explicitly in `gqlgen.yml` like this: + +```yaml +# gqlgen.yml +models: + User: + fields: + friends: + resolver: true # force a resolver to be generated +``` + +After doing either of the above and running generate we will need to provide a resolver for friends: + +```go +func (r *userResolver) Friends(ctx context.Context, obj *User) ([]*User, error) { + // select * from user where friendid = obj.ID + return friends, nil +} +``` + +### Can I change the type of the ID from type String to Type Int? + +Yes! You can by remapping it in config as seen below: + +```yaml +models: + ID: # The GraphQL type ID is backed by + model: + - github.com/99designs/gqlgen/graphql.IntID # An go integer + - github.com/99designs/gqlgen/graphql.ID # or a go string +``` + +This means gqlgen will be able to automatically bind to strings or ints for models you have written yourself, but the +first model in this list is used as the default type and it will always be used when: + +- Generating models based on schema +- As arguments in resolvers + +There isnt any way around this, gqlgen has no way to know what you want in a given context. ## 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) +- [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/) +- [Dive into GraphQL by Iván Corrales Solera](https://medium.com/@ivan.corrales.solera/dive-into-graphql-9bfedf22e1a) +- [Sample Project built on gqlgen with Postgres by Oleg Shalygin](https://github.com/oshalygin/gqlgen-pg-todo-example) diff --git a/vendor/github.com/99designs/gqlgen/api/generate.go b/vendor/github.com/99designs/gqlgen/api/generate.go index 3dd083f52..3a19c017d 100644 --- a/vendor/github.com/99designs/gqlgen/api/generate.go +++ b/vendor/github.com/99designs/gqlgen/api/generate.go @@ -6,25 +6,60 @@ import ( "github.com/99designs/gqlgen/codegen" "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/plugin" + "github.com/99designs/gqlgen/plugin/federation" "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) + if cfg.Model.IsDefined() { + _ = syscall.Unlink(cfg.Model.Filename) + } - plugins := []plugin.Plugin{ - modelgen.New(), - resolvergen.New(), + plugins := []plugin.Plugin{} + if cfg.Model.IsDefined() { + plugins = append(plugins, modelgen.New()) + } + plugins = append(plugins, resolvergen.New()) + if cfg.Federation.IsDefined() { + plugins = append([]plugin.Plugin{federation.New()}, plugins...) } for _, o := range option { o(cfg, &plugins) } + for _, p := range plugins { + if inj, ok := p.(plugin.EarlySourceInjector); ok { + if s := inj.InjectSourceEarly(); s != nil { + cfg.Sources = append(cfg.Sources, s) + } + } + } + + if err := cfg.LoadSchema(); err != nil { + return errors.Wrap(err, "failed to load schema") + } + + for _, p := range plugins { + if inj, ok := p.(plugin.LateSourceInjector); ok { + if s := inj.InjectSourceLate(cfg.Schema); s != nil { + cfg.Sources = append(cfg.Sources, s) + } + } + } + + // LoadSchema again now we have everything + if err := cfg.LoadSchema(); err != nil { + return errors.Wrap(err, "failed to load schema") + } + + if err := cfg.Init(); err != nil { + return errors.Wrap(err, "generating core failed") + } + for _, p := range plugins { if mut, ok := p.(plugin.ConfigMutator); ok { err := mut.MutateConfig(cfg) @@ -36,7 +71,7 @@ func Generate(cfg *config.Config, option ...Option) error { // 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") + return errors.Wrap(err, "merging type systems failed") } if err = codegen.GenerateCode(data); err != nil { @@ -52,8 +87,14 @@ func Generate(cfg *config.Config, option ...Option) error { } } - if err := validate(cfg); err != nil { - return errors.Wrap(err, "validation failed") + if err = codegen.GenerateCode(data); err != nil { + return errors.Wrap(err, "generating core failed") + } + + if !cfg.SkipValidation { + if err := validate(cfg); err != nil { + return errors.Wrap(err, "validation failed") + } } return nil @@ -68,9 +109,11 @@ func validate(cfg *config.Config) error { 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") + + cfg.Packages.LoadAll(roots...) + errs := cfg.Packages.Errors() + if len(errs) > 0 { + return errs } return nil } diff --git a/vendor/github.com/99designs/gqlgen/appveyor.yml b/vendor/github.com/99designs/gqlgen/appveyor.yml deleted file mode 100644 index db4751114..000000000 --- a/vendor/github.com/99designs/gqlgen/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -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 ./... diff --git a/vendor/github.com/99designs/gqlgen/cmd/ambient.go b/vendor/github.com/99designs/gqlgen/cmd/ambient.go index 7838fdf16..0f3655d34 100644 --- a/vendor/github.com/99designs/gqlgen/cmd/ambient.go +++ b/vendor/github.com/99designs/gqlgen/cmd/ambient.go @@ -5,6 +5,6 @@ import ( // 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" + _ "github.com/vektah/gqlparser/v2" + _ "github.com/vektah/gqlparser/v2/ast" ) diff --git a/vendor/github.com/99designs/gqlgen/cmd/gen.go b/vendor/github.com/99designs/gqlgen/cmd/gen.go index c69858b44..b875bb43d 100644 --- a/vendor/github.com/99designs/gqlgen/cmd/gen.go +++ b/vendor/github.com/99designs/gqlgen/cmd/gen.go @@ -1,44 +1,43 @@ package cmd import ( - "fmt" "os" "github.com/99designs/gqlgen/api" "github.com/99designs/gqlgen/codegen/config" "github.com/pkg/errors" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) -var genCmd = cli.Command{ +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"}, + &cli.BoolFlag{Name: "verbose, v", Usage: "show logs"}, + &cli.StringFlag{Name: "config, c", Usage: "the config filename"}, }, - Action: func(ctx *cli.Context) { + Action: func(ctx *cli.Context) error { 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) + return err } } 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) + cfg, err = config.LoadDefaultConfig() + } + + if err != nil { + return err } } if err = api.Generate(cfg); err != nil { - fmt.Fprintln(os.Stderr, err.Error()) - os.Exit(3) + return err } + return nil }, } diff --git a/vendor/github.com/99designs/gqlgen/cmd/init.go b/vendor/github.com/99designs/gqlgen/cmd/init.go index e07bed970..121805af5 100644 --- a/vendor/github.com/99designs/gqlgen/cmd/init.go +++ b/vendor/github.com/99designs/gqlgen/cmd/init.go @@ -3,28 +3,79 @@ package cmd import ( "bytes" "fmt" + "html/template" "io/ioutil" "os" + "path/filepath" "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" + "github.com/99designs/gqlgen/internal/code" + "github.com/99designs/gqlgen/plugin/servergen" + "github.com/urfave/cli/v2" ) -var configComment = ` -# .gqlgen.yml example -# -# Refer to https://gqlgen.com/config/ -# for detailed .gqlgen.yml documentation. -` +var configTemplate = template.Must(template.New("name").Parse( + `# Where are all the schema files located? globs are supported eg src/**/*.graphqls +schema: + - graph/*.graphqls -var schemaDefault = ` -# GraphQL schema example +# Where should the generated server code go? +exec: + filename: graph/generated/generated.go + package: generated + +# Uncomment to enable federation +# federation: +# filename: graph/generated/federation.go +# package: generated + +# Where should any generated models go? +model: + filename: graph/model/models_gen.go + package: model + +# Where should the resolver implementations go? +resolver: + layout: follow-schema + dir: graph + package: graph + +# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models +# struct_tag: json + +# Optional: turn on to use []Thing instead of []*Thing +# omit_slice_element_pointers: false + +# Optional: set to speed up generation time by not performing a final validation pass. +# skip_validation: true + +# gqlgen will search for any type names in the schema in these go packages +# if they match it will use them, otherwise it will generate them. +autobind: + - "{{.}}/graph/model" + +# This section declares type mapping between the GraphQL and go type systems +# +# The first line in each type will be used as defaults for resolver arguments and +# modelgen, the others will be allowed when binding to fields. Configure them to +# your liking +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.ID + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Int: + model: + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 +`)) + +var schemaDefault = `# GraphQL schema example # # https://gqlgen.com/getting-started/ @@ -54,91 +105,95 @@ type Mutation { } ` -var initCmd = cli.Command{ +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"}, + &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.go"}, + &cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "graph/schema.graphqls"}, }, - Action: func(ctx *cli.Context) { - initSchema(ctx.String("schema")) - config := initConfig(ctx) + Action: func(ctx *cli.Context) error { + configFilename := ctx.String("config") + serverFilename := ctx.String("server") - GenerateGraphServer(config, ctx.String("server")) + pkgName := code.ImportPathForDir(".") + if pkgName == "" { + return fmt.Errorf("unable to determine import path for current directory, you probably need to run go mod init first") + } + + if err := initSchema(ctx.String("schema")); err != nil { + return err + } + if !configExists(configFilename) { + if err := initConfig(configFilename, pkgName); err != nil { + return err + } + } + + GenerateGraphServer(serverFilename) + return nil }, } -func GenerateGraphServer(cfg *config.Config, serverFilename string) { - err := api.Generate(cfg, api.AddPlugin(servergen.New(serverFilename))) +func GenerateGraphServer(serverFilename string) { + cfg, err := config.LoadConfigFromDefaultLocations() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) } + if err := api.Generate(cfg, api.AddPlugin(servergen.New(serverFilename))); 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 { +func configExists(configFilename string) bool { var cfg *config.Config - var err error - configFilename := ctx.String("config") + if configFilename != "" { - cfg, err = config.LoadConfig(configFilename) + cfg, _ = 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) + cfg, _ = config.LoadConfigFromDefaultLocations() } + return cfg != nil +} +func initConfig(configFilename string, pkgName string) error { if configFilename == "" { configFilename = "gqlgen.yml" } - cfg = config.DefaultConfig() - cfg.Resolver = config.PackageConfig{ - Filename: "resolver.go", - Type: "Resolver", + if err := os.MkdirAll(filepath.Dir(configFilename), 0755); err != nil { + return fmt.Errorf("unable to create config dir: " + err.Error()) } 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) + if err := configTemplate.Execute(&buf, pkgName); err != nil { + panic(err) } - return cfg + if err := ioutil.WriteFile(configFilename, buf.Bytes(), 0644); err != nil { + return fmt.Errorf("unable to write cfg file: " + err.Error()) + } + + return nil } -func initSchema(schemaFilename string) { +func initSchema(schemaFilename string) error { _, err := os.Stat(schemaFilename) if !os.IsNotExist(err) { - return + return nil } - 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) + if err := os.MkdirAll(filepath.Dir(schemaFilename), 0755); err != nil { + return fmt.Errorf("unable to create schema dir: " + err.Error()) } + + if err = ioutil.WriteFile(schemaFilename, []byte(strings.TrimSpace(schemaDefault)), 0644); err != nil { + return fmt.Errorf("unable to write schema file: " + err.Error()) + } + return nil } diff --git a/vendor/github.com/99designs/gqlgen/cmd/root.go b/vendor/github.com/99designs/gqlgen/cmd/root.go index dc2970ac8..2776aa284 100644 --- a/vendor/github.com/99designs/gqlgen/cmd/root.go +++ b/vendor/github.com/99designs/gqlgen/cmd/root.go @@ -7,9 +7,10 @@ import ( "os" "github.com/99designs/gqlgen/graphql" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" // Required since otherwise dep will prune away these unused packages before codegen has a chance to run + _ "github.com/99designs/gqlgen/graphql/handler" _ "github.com/99designs/gqlgen/handler" ) @@ -31,7 +32,7 @@ func Execute() { } app.Action = genCmd.Action - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ genCmd, initCmd, versionCmd, diff --git a/vendor/github.com/99designs/gqlgen/cmd/version.go b/vendor/github.com/99designs/gqlgen/cmd/version.go index 8b7442d4e..d3a05deda 100644 --- a/vendor/github.com/99designs/gqlgen/cmd/version.go +++ b/vendor/github.com/99designs/gqlgen/cmd/version.go @@ -4,13 +4,14 @@ import ( "fmt" "github.com/99designs/gqlgen/graphql" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) -var versionCmd = cli.Command{ +var versionCmd = &cli.Command{ Name: "version", Usage: "print the version string", - Action: func(ctx *cli.Context) { + Action: func(ctx *cli.Context) error { fmt.Println(graphql.Version) + return nil }, } diff --git a/vendor/github.com/99designs/gqlgen/codegen/args.go b/vendor/github.com/99designs/gqlgen/codegen/args.go index d1498bddb..20a26e975 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/args.go +++ b/vendor/github.com/99designs/gqlgen/codegen/args.go @@ -8,7 +8,7 @@ import ( "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" "github.com/pkg/errors" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type ArgSet struct { @@ -26,6 +26,22 @@ type FieldArgument struct { Value interface{} // value set in Data } +//ImplDirectives get not Builtin and location ARGUMENT_DEFINITION directive +func (f *FieldArgument) ImplDirectives() []*Directive { + d := make([]*Directive, 0) + for i := range f.Directives { + if !f.Directives[i].Builtin && f.Directives[i].IsLocation(ast.LocationArgumentDefinition) { + d = append(d, f.Directives[i]) + } + } + + return d +} + +func (f *FieldArgument) DirectiveObjName() string { + return "rawArgs" +} + func (f *FieldArgument) Stream() bool { return f.Object != nil && f.Object.Stream } diff --git a/vendor/github.com/99designs/gqlgen/codegen/args.gotpl b/vendor/github.com/99designs/gqlgen/codegen/args.gotpl index 4c7212182..b25d444b5 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/args.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/args.gotpl @@ -5,27 +5,20 @@ func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string] {{- 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) + ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField({{$arg.Name|quote}})) + {{- if $arg.ImplDirectives }} + directive0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp) } + {{ template "implDirectives" $arg }} + tmp, err = directive{{$arg.ImplDirectives|len}}(ctx) if err != nil { return nil, err } if data, ok := tmp.({{ $arg.TypeReference.GO | ref }}) ; ok { arg{{$i}} = data + {{- if $arg.TypeReference.IsNilable }} + } else if tmp == nil { + arg{{$i}} = nil + {{- end }} } else { return nil, fmt.Errorf(`unexpected type %T from directive, should be {{ $arg.TypeReference.GO }}`, tmp) } diff --git a/vendor/github.com/99designs/gqlgen/codegen/config/binder.go b/vendor/github.com/99designs/gqlgen/codegen/config/binder.go index cea904ada..2be7b7bdd 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/config/binder.go +++ b/vendor/github.com/99designs/gqlgen/codegen/config/binder.go @@ -8,37 +8,24 @@ import ( "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" + "github.com/vektah/gqlparser/v2/ast" ) // Binder connects graphql types to golang types using static analysis type Binder struct { - pkgs []*packages.Package + pkgs *code.Packages schema *ast.Schema cfg *Config References []*TypeReference + SawInvalid bool } -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] - } - } - } - +func (c *Config) NewBinder() *Binder { return &Binder{ - pkgs: pkgs, - schema: s, + pkgs: c.Packages, + schema: c.Schema, cfg: c, - }, nil + } } func (b *Binder) TypePosition(typ types.Type) token.Position { @@ -58,11 +45,26 @@ func (b *Binder) ObjectPosition(typ types.Object) token.Position { Filename: "unknown", } } - pkg := b.getPkg(typ.Pkg().Path()) + pkg := b.pkgs.Load(typ.Pkg().Path()) return pkg.Fset.Position(typ.Pos()) } +func (b *Binder) FindTypeFromName(name string) (types.Type, error) { + pkgName, typeName := code.PkgAndType(name) + return b.FindType(pkgName, typeName) +} + func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) { + if pkgName == "" { + if typeName == "map[string]interface{}" { + return MapType, nil + } + + if typeName == "interface{}" { + return InterfaceType, nil + } + } + obj, err := b.FindObject(pkgName, typeName) if err != nil { return nil, err @@ -74,15 +76,6 @@ func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) { 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) @@ -122,7 +115,7 @@ func (b *Binder) FindObject(pkgName string, typeName string) (types.Object, erro fullName = pkgName + "." + typeName } - pkg := b.getPkg(pkgName) + pkg := b.pkgs.LoadWithTypes(pkgName) if pkg == nil { return nil, errors.Errorf("required package was not loaded: %s", fullName) } @@ -173,7 +166,8 @@ func (b *Binder) PointerTo(ref *TypeReference) *TypeReference { type TypeReference struct { Definition *ast.Definition GQL *ast.Type - GO types.Type + GO types.Type // Type of the field being bound. Could be a pointer or a value type of Target. + Target types.Type // The actual type that we know how to bind to. May require pointer juggling when traversing to fields. 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 @@ -184,6 +178,7 @@ func (ref *TypeReference) Elem() *TypeReference { if p, isPtr := ref.GO.(*types.Pointer); isPtr { return &TypeReference{ GO: p.Elem(), + Target: ref.Target, GQL: ref.GQL, CastType: ref.CastType, Definition: ref.Definition, @@ -196,6 +191,7 @@ func (ref *TypeReference) Elem() *TypeReference { if ref.IsSlice() { return &TypeReference{ GO: ref.GO.(*types.Slice).Elem(), + Target: ref.Target, GQL: ref.GQL.Elem, CastType: ref.CastType, Definition: ref.Definition, @@ -213,10 +209,7 @@ func (t *TypeReference) IsPtr() bool { } func (t *TypeReference) IsNilable() bool { - _, isPtr := t.GO.(*types.Pointer) - _, isMap := t.GO.(*types.Map) - _, isInterface := t.GO.(*types.Interface) - return isPtr || isMap || isInterface + return IsNilable(t.GO) } func (t *TypeReference) IsSlice() bool { @@ -244,7 +237,12 @@ func (t *TypeReference) UniquenessKey() string { nullability = "N" } - return nullability + t.Definition.Name + "2" + templates.TypeIdentifier(t.GO) + var elemNullability = "" + if t.GQL.Elem != nil && t.GQL.Elem.NonNull { + // Fix for #896 + elemNullability = "ᚄ" + } + return nullability + t.Definition.Name + "2" + templates.TypeIdentifier(t.GO) + elemNullability } func (t *TypeReference) MarshalFunc() string { @@ -271,6 +269,10 @@ func (t *TypeReference) UnmarshalFunc() string { return "unmarshal" + t.UniquenessKey() } +func (t *TypeReference) IsTargetNilable() bool { + return IsNilable(t.Target) +} + func (b *Binder) PushRef(ret *TypeReference) { b.References = append(b.References, ret) } @@ -292,6 +294,11 @@ func isIntf(t types.Type) bool { } func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret *TypeReference, err error) { + if !isValid(bindTarget) { + b.SawInvalid = true + return nil, fmt.Errorf("%s has an invalid type", schemaType.Name()) + } + var pkgName, typeName string def := b.schema.Types[schemaType.Name()] defer func() { @@ -350,7 +357,7 @@ func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret 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. + // TODO delete before v1. Backwards compatibility case for named types wrapping strings (see #595) ref.GO = obj.Type() ref.CastType = underlying @@ -366,6 +373,7 @@ func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret ref.GO = obj.Type() } + ref.Target = ref.GO ref.GO = b.CopyModifiersFromAst(schemaType, ref.GO) if bindTarget != nil { @@ -378,13 +386,21 @@ func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret return ref, nil } - return nil, fmt.Errorf("%s has type compatible with %s", schemaType.Name(), bindTarget.String()) + return nil, fmt.Errorf("%s is incompatible with %s", schemaType.Name(), bindTarget.String()) +} + +func isValid(t types.Type) bool { + basic, isBasic := t.(*types.Basic) + if !isBasic { + return true + } + return basic.Kind() != types.Invalid } 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 { + if _, isStruct := child.Underlying().(*types.Struct); isStruct && !b.cfg.OmitSliceElementPointers { child = types.NewPointer(child) } return types.NewSlice(child) @@ -395,13 +411,25 @@ func (b *Binder) CopyModifiersFromAst(t *ast.Type, base types.Type) types.Type { _, isInterface = named.Underlying().(*types.Interface) } - if !isInterface && !t.NonNull { + if !isInterface && !IsNilable(base) && !t.NonNull { return types.NewPointer(base) } return base } +func IsNilable(t types.Type) bool { + if namedType, isNamed := t.(*types.Named); isNamed { + return IsNilable(namedType.Underlying()) + } + _, isPtr := t.(*types.Pointer) + _, isMap := t.(*types.Map) + _, isInterface := t.(*types.Interface) + _, isSlice := t.(*types.Slice) + _, isChan := t.(*types.Chan) + return isPtr || isMap || isInterface || isSlice || isChan +} + func hasMethod(it types.Type, name string) bool { if ptr, isPtr := it.(*types.Pointer); isPtr { it = ptr.Elem() diff --git a/vendor/github.com/99designs/gqlgen/codegen/config/config.go b/vendor/github.com/99designs/gqlgen/codegen/config/config.go index 1725adab0..ba939fcf5 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/config/config.go +++ b/vendor/github.com/99designs/gqlgen/codegen/config/config.go @@ -2,27 +2,38 @@ package config import ( "fmt" - "go/types" "io/ioutil" "os" "path/filepath" + "regexp" "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" + "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" + "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"` + SchemaFilename StringList `yaml:"schema,omitempty"` + Exec PackageConfig `yaml:"exec"` + Model PackageConfig `yaml:"model,omitempty"` + Federation PackageConfig `yaml:"federation,omitempty"` + Resolver ResolverConfig `yaml:"resolver,omitempty"` + AutoBind []string `yaml:"autobind"` + Models TypeMap `yaml:"models,omitempty"` + StructTag string `yaml:"struct_tag,omitempty"` + Directives map[string]DirectiveConfig `yaml:"directives,omitempty"` + OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"` + SkipValidation bool `yaml:"skip_validation,omitempty"` + Sources []*ast.Source `yaml:"-"` + Packages *code.Packages `yaml:"-"` + Schema *ast.Schema `yaml:"-"` + + // Deprecated use Federation instead. Will be removed next release + Federated bool `yaml:"federated,omitempty"` } var cfgFilenames = []string{".gqlgen.yml", "gqlgen.yml", "gqlgen.yaml"} @@ -33,9 +44,30 @@ func DefaultConfig() *Config { SchemaFilename: StringList{"schema.graphql"}, Model: PackageConfig{Filename: "models_gen.go"}, Exec: PackageConfig{Filename: "generated.go"}, + Directives: map[string]DirectiveConfig{}, + Models: TypeMap{}, } } +// LoadDefaultConfig loads the default config so that it is ready to be used +func LoadDefaultConfig() (*Config, error) { + config := DefaultConfig() + + for _, filename := range config.SchemaFilename { + filename = filepath.ToSlash(filename) + var err error + var schemaRaw []byte + schemaRaw, err = ioutil.ReadFile(filename) + if err != nil { + return nil, errors.Wrap(err, "unable to open schema") + } + + config.Sources = append(config.Sources, &ast.Source{Name: filename, Input: string(schemaRaw)}) + } + + return config, nil +} + // 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) { @@ -51,6 +83,13 @@ func LoadConfigFromDefaultLocations() (*Config, error) { return LoadConfig(cfgFile) } +var path2regex = strings.NewReplacer( + `.`, `\.`, + `*`, `.+`, + `\`, `[\\/]`, + `/`, `[\\/]`, +) + // LoadConfig reads the gqlgen.yml config file func LoadConfig(filename string) (*Config, error) { config := DefaultConfig() @@ -64,12 +103,50 @@ func LoadConfig(filename string) (*Config, error) { return nil, errors.Wrap(err, "unable to parse config") } + defaultDirectives := map[string]DirectiveConfig{ + "skip": {SkipRuntime: true}, + "include": {SkipRuntime: true}, + "deprecated": {SkipRuntime: true}, + } + + for key, value := range defaultDirectives { + if _, defined := config.Directives[key]; !defined { + config.Directives[key] = value + } + } + 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) + var matches []string + + // for ** we want to override default globbing patterns and walk all + // subdirectories to match schema files. + if strings.Contains(f, "**") { + pathParts := strings.SplitN(f, "**", 2) + rest := strings.TrimPrefix(strings.TrimPrefix(pathParts[1], `\`), `/`) + // turn the rest of the glob into a regex, anchored only at the end because ** allows + // for any number of dirs in between and walk will let us match against the full path name + globRe := regexp.MustCompile(path2regex.Replace(rest) + `$`) + + if err := filepath.Walk(pathParts[0], func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if globRe.MatchString(strings.TrimPrefix(path, pathParts[0])) { + matches = append(matches, path) + } + + return nil + }); err != nil { + return nil, errors.Wrapf(err, "failed to walk schema at root %s", pathParts[0]) + } + } else { + matches, err = filepath.Glob(f) + if err != nil { + return nil, errors.Wrapf(err, "failed to glob schema filename %s", f) + } } for _, m := range matches { @@ -80,13 +157,126 @@ func LoadConfig(filename string) (*Config, error) { } } + for _, filename := range config.SchemaFilename { + filename = filepath.ToSlash(filename) + var err error + var schemaRaw []byte + schemaRaw, err = ioutil.ReadFile(filename) + if err != nil { + return nil, errors.Wrap(err, "unable to open schema") + } + + config.Sources = append(config.Sources, &ast.Source{Name: filename, Input: string(schemaRaw)}) + } + return config, nil } -type PackageConfig struct { - Filename string `yaml:"filename,omitempty"` - Package string `yaml:"package,omitempty"` - Type string `yaml:"type,omitempty"` +func (c *Config) Init() error { + if c.Packages == nil { + c.Packages = &code.Packages{} + } + + if c.Schema == nil { + if err := c.LoadSchema(); err != nil { + return err + } + } + + err := c.injectTypesFromSchema() + if err != nil { + return err + } + + err = c.autobind() + if err != nil { + return err + } + + c.injectBuiltins() + + // prefetch all packages in one big packages.Load call + pkgs := []string{ + "github.com/99designs/gqlgen/graphql", + "github.com/99designs/gqlgen/graphql/introspection", + } + pkgs = append(pkgs, c.Models.ReferencedPackages()...) + pkgs = append(pkgs, c.AutoBind...) + c.Packages.LoadAll(pkgs...) + + // check everything is valid on the way out + err = c.check() + if err != nil { + return err + } + + return nil +} + +func (c *Config) injectTypesFromSchema() error { + c.Directives["goModel"] = DirectiveConfig{ + SkipRuntime: true, + } + + c.Directives["goField"] = DirectiveConfig{ + SkipRuntime: true, + } + + for _, schemaType := range c.Schema.Types { + if schemaType == c.Schema.Query || schemaType == c.Schema.Mutation || schemaType == c.Schema.Subscription { + continue + } + + if bd := schemaType.Directives.ForName("goModel"); bd != nil { + if ma := bd.Arguments.ForName("model"); ma != nil { + if mv, err := ma.Value.Value(nil); err == nil { + c.Models.Add(schemaType.Name, mv.(string)) + } + } + if ma := bd.Arguments.ForName("models"); ma != nil { + if mvs, err := ma.Value.Value(nil); err == nil { + for _, mv := range mvs.([]interface{}) { + c.Models.Add(schemaType.Name, mv.(string)) + } + } + } + } + + if schemaType.Kind == ast.Object || schemaType.Kind == ast.InputObject { + for _, field := range schemaType.Fields { + if fd := field.Directives.ForName("goField"); fd != nil { + forceResolver := c.Models[schemaType.Name].Fields[field.Name].Resolver + fieldName := c.Models[schemaType.Name].Fields[field.Name].FieldName + + if ra := fd.Arguments.ForName("forceResolver"); ra != nil { + if fr, err := ra.Value.Value(nil); err == nil { + forceResolver = fr.(bool) + } + } + + if na := fd.Arguments.ForName("name"); na != nil { + if fr, err := na.Value.Value(nil); err == nil { + fieldName = fr.(string) + } + } + + if c.Models[schemaType.Name].Fields == nil { + c.Models[schemaType.Name] = TypeMapEntry{ + Model: c.Models[schemaType.Name].Model, + Fields: map[string]TypeMapField{}, + } + } + + c.Models[schemaType.Name].Fields[field.Name] = TypeMapField{ + FieldName: fieldName, + Resolver: forceResolver, + } + } + } + } + } + + return nil } type TypeMapEntry struct { @@ -95,8 +285,9 @@ type TypeMapEntry struct { } type TypeMapField struct { - Resolver bool `yaml:"resolver"` - FieldName string `yaml:"fieldName"` + Resolver bool `yaml:"resolver"` + FieldName string `yaml:"fieldName"` + GeneratedMethod string `yaml:"-"` } type StringList []string @@ -128,90 +319,85 @@ func (a StringList) Has(file string) bool { 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()) +func (c *Config) check() error { + if c.Models == nil { + c.Models = TypeMap{} } - 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") + type FilenamePackage struct { + Filename string + Package string + Declaree string } - return c.normalize() -} + fileList := map[string][]FilenamePackage{} -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") + fileList[c.Exec.ImportPath()] = append(fileList[c.Exec.ImportPath()], FilenamePackage{ + Filename: c.Exec.Filename, + Package: c.Exec.Package, + Declaree: "exec", + }) + + if c.Model.IsDefined() { + if err := c.Model.Check(); err != nil { + return errors.Wrap(err, "config.model") + } + fileList[c.Model.ImportPath()] = append(fileList[c.Model.ImportPath()], FilenamePackage{ + Filename: c.Model.Filename, + Package: c.Model.Package, + Declaree: "model", + }) } if c.Resolver.IsDefined() { if err := c.Resolver.Check(); err != nil { return errors.Wrap(err, "config.resolver") } + fileList[c.Resolver.ImportPath()] = append(fileList[c.Resolver.ImportPath()], FilenamePackage{ + Filename: c.Resolver.Filename, + Package: c.Resolver.Package, + Declaree: "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) + if c.Federation.IsDefined() { + if err := c.Federation.Check(); err != nil { + return errors.Wrap(err, "config.federation") } - 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)) + fileList[c.Federation.ImportPath()] = append(fileList[c.Federation.ImportPath()], FilenamePackage{ + Filename: c.Federation.Filename, + Package: c.Federation.Package, + Declaree: "federation", + }) + if c.Federation.ImportPath() != c.Exec.ImportPath() { + return fmt.Errorf("federation and exec must be in the same package") } - pkgConfigsByDir[current.Dir()] = current + } + if c.Federated { + return fmt.Errorf("federated has been removed, instead use\nfederation:\n filename: path/to/federated.go") } - return c.normalize() -} + for importPath, pkg := range fileList { + for _, file1 := range pkg { + for _, file2 := range pkg { + if file1.Package != file2.Package { + return fmt.Errorf("%s and %s define the same import path (%s) with different package names (%s vs %s)", + file1.Declaree, + file2.Declaree, + importPath, + file1.Package, + file2.Package, + ) + } + } + } + } -func stripPath(path string) string { - return filepath.Base(path) + return nil } type TypeMap map[string]TypeMapEntry @@ -259,10 +445,14 @@ func (tm TypeMap) ReferencedPackages() []string { return pkgs } -func (tm TypeMap) Add(Name string, goType string) { - modelCfg := tm[Name] +func (tm TypeMap) Add(name string, goType string) { + modelCfg := tm[name] modelCfg.Model = append(modelCfg.Model, goType) - tm[Name] = modelCfg + tm[name] = modelCfg +} + +type DirectiveConfig struct { + SkipRuntime bool `yaml:"skip_runtime"` } func inStrSlice(haystack []string, needle string) bool { @@ -307,29 +497,54 @@ func findCfgInDir(dir string) string { return "" } -func (c *Config) normalize() error { - if err := c.Model.normalize(); err != nil { - return errors.Wrap(err, "model") +func (c *Config) autobind() error { + if len(c.AutoBind) == 0 { + return nil } - if err := c.Exec.normalize(); err != nil { - return errors.Wrap(err, "exec") - } + ps := c.Packages.LoadAll(c.AutoBind...) - if c.Resolver.IsDefined() { - if err := c.Resolver.normalize(); err != nil { - return errors.Wrap(err, "resolver") + for _, t := range c.Schema.Types { + if c.Models.UserDefined(t.Name) { + continue + } + + for i, p := range ps { + if p == nil { + return fmt.Errorf("unable to load %s - make sure you're using an import path to a package that exists", c.AutoBind[i]) + } + if t := p.Types.Scope().Lookup(t.Name); t != nil { + c.Models.Add(t.Name(), t.Pkg().Path()+"."+t.Name()) + break + } } } - if c.Models == nil { - c.Models = TypeMap{} + for i, t := range c.Models { + for j, m := range t.Model { + pkg, typename := code.PkgAndType(m) + + // skip anything that looks like an import path + if strings.Contains(pkg, "/") { + continue + } + + for _, p := range ps { + if p.Name != pkg { + continue + } + if t := p.Types.Scope().Lookup(typename); t != nil { + c.Models[i].Model[j] = t.Pkg().Path() + "." + t.Name() + break + } + } + } } return nil } -func (c *Config) InjectBuiltins(s *ast.Schema) { +func (c *Config) injectBuiltins() { builtins := TypeMap{ "__Directive": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}}, "__DirectiveLocation": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}}, @@ -370,35 +585,36 @@ func (c *Config) InjectBuiltins(s *ast.Schema) { } for typeName, entry := range extraBuiltins { - if t, ok := s.Types[typeName]; !c.Models.Exists(typeName) && ok && t.Kind == ast.Scalar { + if t, ok := c.Schema.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]}) +func (c *Config) LoadSchema() error { + if c.Packages != nil { + c.Packages = &code.Packages{} } - schema, err := gqlparser.LoadSchema(sources...) + if err := c.check(); err != nil { + return err + } + + schema, err := gqlparser.LoadSchema(c.Sources...) if err != nil { - return nil, nil, err + return err } - return schema, schemaStrings, nil + + if schema.Query == nil { + schema.Query = &ast.Definition{ + Kind: ast.Object, + Name: "Query", + } + schema.Types["Query"] = schema.Query + } + + c.Schema = schema + return nil } func abs(path string) string { diff --git a/vendor/github.com/99designs/gqlgen/codegen/config/package.go b/vendor/github.com/99designs/gqlgen/codegen/config/package.go new file mode 100644 index 000000000..a96459381 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/codegen/config/package.go @@ -0,0 +1,62 @@ +package config + +import ( + "fmt" + "go/types" + "path/filepath" + "strings" + + "github.com/99designs/gqlgen/internal/code" +) + +type PackageConfig struct { + Filename string `yaml:"filename,omitempty"` + Package string `yaml:"package,omitempty"` +} + +func (c *PackageConfig) ImportPath() string { + if !c.IsDefined() { + return "" + } + return code.ImportPathForDir(c.Dir()) +} + +func (c *PackageConfig) Dir() string { + if !c.IsDefined() { + return "" + } + return filepath.Dir(c.Filename) +} + +func (c *PackageConfig) Pkg() *types.Package { + if !c.IsDefined() { + return nil + } + return types.NewPackage(c.ImportPath(), c.Package) +} + +func (c *PackageConfig) IsDefined() bool { + return 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 == "" { + return fmt.Errorf("filename must be specified") + } + if !strings.HasSuffix(c.Filename, ".go") { + return fmt.Errorf("filename should be path to a go source file") + } + + 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 +} diff --git a/vendor/github.com/99designs/gqlgen/codegen/config/resolver.go b/vendor/github.com/99designs/gqlgen/codegen/config/resolver.go new file mode 100644 index 000000000..cd03f1887 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/codegen/config/resolver.go @@ -0,0 +1,100 @@ +package config + +import ( + "fmt" + "go/types" + "path/filepath" + "strings" + + "github.com/99designs/gqlgen/internal/code" +) + +type ResolverConfig struct { + Filename string `yaml:"filename,omitempty"` + FilenameTemplate string `yaml:"filename_template,omitempty"` + Package string `yaml:"package,omitempty"` + Type string `yaml:"type,omitempty"` + Layout ResolverLayout `yaml:"layout,omitempty"` + DirName string `yaml:"dir"` +} + +type ResolverLayout string + +var ( + LayoutSingleFile ResolverLayout = "single-file" + LayoutFollowSchema ResolverLayout = "follow-schema" +) + +func (r *ResolverConfig) Check() error { + if r.Layout == "" { + r.Layout = LayoutSingleFile + } + if r.Type == "" { + r.Type = "Resolver" + } + + switch r.Layout { + case LayoutSingleFile: + if r.Filename == "" { + return fmt.Errorf("filename must be specified with layout=%s", r.Layout) + } + if !strings.HasSuffix(r.Filename, ".go") { + return fmt.Errorf("filename should be path to a go source file with layout=%s", r.Layout) + } + r.Filename = abs(r.Filename) + case LayoutFollowSchema: + if r.DirName == "" { + return fmt.Errorf("dirname must be specified with layout=%s", r.Layout) + } + r.DirName = abs(r.DirName) + if r.Filename == "" { + r.Filename = filepath.Join(r.DirName, "resolver.go") + } else { + r.Filename = abs(r.Filename) + } + default: + return fmt.Errorf("invalid layout %s. must be %s or %s", r.Layout, LayoutSingleFile, LayoutFollowSchema) + } + + if strings.ContainsAny(r.Package, "./\\") { + return fmt.Errorf("package should be the output package name only, do not include the output filename") + } + + if r.Package == "" && r.Dir() != "" { + r.Package = code.NameForDir(r.Dir()) + } + + return nil +} + +func (r *ResolverConfig) ImportPath() string { + if r.Dir() == "" { + return "" + } + return code.ImportPathForDir(r.Dir()) +} + +func (r *ResolverConfig) Dir() string { + switch r.Layout { + case LayoutSingleFile: + if r.Filename == "" { + return "" + } + return filepath.Dir(r.Filename) + case LayoutFollowSchema: + return r.DirName + default: + panic("invalid layout " + r.Layout) + } +} + +func (r *ResolverConfig) Pkg() *types.Package { + if r.Dir() == "" { + return nil + } + return types.NewPackage(r.ImportPath(), r.Package) +} + +func (r *ResolverConfig) IsDefined() bool { + return r.Filename != "" || r.DirName != "" +} diff --git a/vendor/github.com/99designs/gqlgen/codegen/data.go b/vendor/github.com/99designs/gqlgen/codegen/data.go index f2ea70b4a..bedbef9d4 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/data.go +++ b/vendor/github.com/99designs/gqlgen/codegen/data.go @@ -4,9 +4,10 @@ import ( "fmt" "sort" - "github.com/99designs/gqlgen/codegen/config" "github.com/pkg/errors" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/codegen/config" ) // Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement @@ -14,8 +15,7 @@ import ( type Data struct { Config *config.Config Schema *ast.Schema - SchemaStr map[string]string - Directives map[string]*Directive + Directives DirectiveList Objects Objects Inputs Objects Interfaces map[string]*Interface @@ -30,7 +30,6 @@ type Data struct { type builder struct { Config *config.Config Schema *ast.Schema - SchemaStr map[string]string Binder *config.Binder Directives map[string]*Directive } @@ -38,26 +37,12 @@ type builder struct { func BuildData(cfg *config.Config) (*Data, error) { b := builder{ Config: cfg, + Schema: cfg.Schema, } + b.Binder = b.Config.NewBinder() + 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 @@ -74,7 +59,6 @@ func BuildData(cfg *config.Config) (*Data, error) { Config: cfg, Directives: dataDirectives, Schema: b.Schema, - SchemaStr: b.SchemaStr, Interfaces: map[string]*Interface{}, } @@ -96,7 +80,10 @@ func BuildData(cfg *config.Config) (*Data, error) { s.Inputs = append(s.Inputs, input) case ast.Union, ast.Interface: - s.Interfaces[schemaType.Name] = b.buildInterface(schemaType) + s.Interfaces[schemaType.Name], err = b.buildInterface(schemaType) + if err != nil { + return nil, errors.Wrap(err, "unable to bind to interface") + } } } @@ -118,10 +105,7 @@ func BuildData(cfg *config.Config) (*Data, error) { return nil, err } - s.ReferencedTypes, err = b.buildTypes() - if err != nil { - return nil, err - } + s.ReferencedTypes = b.buildTypes() sort.Slice(s.Objects, func(i, j int) bool { return s.Objects[i].Definition.Name < s.Objects[j].Definition.Name @@ -131,6 +115,17 @@ func BuildData(cfg *config.Config) (*Data, error) { return s.Inputs[i].Definition.Name < s.Inputs[j].Definition.Name }) + if b.Binder.SawInvalid { + // if we have a syntax error, show it + err := cfg.Packages.Errors() + if len(err) > 0 { + return nil, err + } + + // otherwise show a generic error message + return nil, fmt.Errorf("invalid types were encountered while traversing the go source code, this probably means the invalid code generated isnt correct. add try adding -v to debug") + } + return &s, nil } diff --git a/vendor/github.com/99designs/gqlgen/codegen/directive.go b/vendor/github.com/99designs/gqlgen/codegen/directive.go index 5a27e8ace..5d4c038ff 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/directive.go +++ b/vendor/github.com/99designs/gqlgen/codegen/directive.go @@ -7,15 +7,46 @@ import ( "github.com/99designs/gqlgen/codegen/templates" "github.com/pkg/errors" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) +type DirectiveList map[string]*Directive + +//LocationDirectives filter directives by location +func (dl DirectiveList) LocationDirectives(location string) DirectiveList { + return locationDirectives(dl, ast.DirectiveLocation(location)) +} + type Directive struct { + *ast.DirectiveDefinition Name string Args []*FieldArgument Builtin bool } +//IsLocation check location directive +func (d *Directive) IsLocation(location ...ast.DirectiveLocation) bool { + for _, l := range d.Locations { + for _, a := range location { + if l == a { + return true + } + } + } + + return false +} + +func locationDirectives(directives DirectiveList, location ...ast.DirectiveLocation) map[string]*Directive { + mDirectives := make(map[string]*Directive) + for name, d := range directives { + if d.IsLocation(location...) { + mDirectives[name] = d + } + } + return mDirectives +} + func (b *builder) buildDirectives() (map[string]*Directive, error) { directives := make(map[string]*Directive, len(b.Schema.Directives)) @@ -24,11 +55,6 @@ func (b *builder) buildDirectives() (map[string]*Directive, error) { 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) @@ -53,9 +79,10 @@ func (b *builder) buildDirectives() (map[string]*Directive, error) { } directives[name] = &Directive{ - Name: name, - Args: args, - Builtin: builtin, + DirectiveDefinition: dir, + Name: name, + Args: args, + Builtin: b.Config.Directives[name].SkipRuntime, } } @@ -92,8 +119,10 @@ func (b *builder) getDirectives(list ast.DirectiveList) ([]*Directive, error) { }) } dirs[i] = &Directive{ - Name: d.Name, - Args: args, + Name: d.Name, + Args: args, + DirectiveDefinition: list[i].Definition, + Builtin: b.Config.Directives[d.Name].SkipRuntime, } } @@ -119,18 +148,12 @@ func (d *Directive) CallArgs() string { return strings.Join(args, ", ") } -func (d *Directive) ResolveArgs(obj string, next string) string { - args := []string{"ctx", obj, next} +func (d *Directive) ResolveArgs(obj string, next int) string { + args := []string{"ctx", obj, fmt.Sprintf("directive%d", 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 := arg.VarName + if arg.Value == nil && arg.Default == nil { dArg = "nil" } @@ -144,7 +167,7 @@ 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 += fmt.Sprintf(", %s %s", templates.ToGoPrivate(arg.Name), templates.CurrentImports.LookupType(arg.TypeReference.GO)) } res += ") (res interface{}, err error)" diff --git a/vendor/github.com/99designs/gqlgen/codegen/directives.gotpl b/vendor/github.com/99designs/gqlgen/codegen/directives.gotpl new file mode 100644 index 000000000..e6d2455f6 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/codegen/directives.gotpl @@ -0,0 +1,149 @@ +{{ define "implDirectives" }}{{ $in := .DirectiveObjName }} + {{- range $i, $directive := .ImplDirectives -}} + directive{{add $i 1}} := func(ctx context.Context) (interface{}, error) { + {{- range $arg := $directive.Args }} + {{- if notNil "Value" $arg }} + {{ $arg.VarName }}, err := ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, {{ $arg.Value | dump }}) + if err != nil{ + return nil, err + } + {{- else if notNil "Default" $arg }} + {{ $arg.VarName }}, err := ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, {{ $arg.Default | dump }}) + if err != nil{ + return nil, err + } + {{- end }} + {{- end }} + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } + return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs $in $i }}) + } + {{ end -}} +{{ end }} + +{{define "queryDirectives"}} + for _, d := range obj.Directives { + switch d.Name { + {{- range $directive := . }} + case "{{$directive.Name}}": + {{- if $directive.Args }} + rawArgs := d.ArgumentMap(ec.Variables) + args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + {{- end }} + n := next + next = func(ctx context.Context) (interface{}, error) { + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } + return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}}) + } + {{- end }} + } + } + tmp, err := next(ctx) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if data, ok := tmp.(graphql.Marshaler); ok { + return data + } + ec.Errorf(ctx, `unexpected type %T from directive, should be graphql.Marshaler`, tmp) + return graphql.Null +{{end}} + +{{ if .Directives.LocationDirectives "QUERY" }} +func (ec *executionContext) _queryMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler { + {{ template "queryDirectives" .Directives.LocationDirectives "QUERY" }} +} +{{ end }} + +{{ if .Directives.LocationDirectives "MUTATION" }} +func (ec *executionContext) _mutationMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler { + {{ template "queryDirectives" .Directives.LocationDirectives "MUTATION" }} +} +{{ end }} + +{{ if .Directives.LocationDirectives "SUBSCRIPTION" }} +func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) func() graphql.Marshaler { + for _, d := range obj.Directives { + switch d.Name { + {{- range $directive := .Directives.LocationDirectives "SUBSCRIPTION" }} + case "{{$directive.Name}}": + {{- if $directive.Args }} + rawArgs := d.ArgumentMap(ec.Variables) + args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs) + if err != nil { + ec.Error(ctx, err) + return func() graphql.Marshaler { + return graphql.Null + } + } + {{- end }} + n := next + next = func(ctx context.Context) (interface{}, error) { + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } + return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}}) + } + {{- end }} + } + } + tmp, err := next(ctx) + if err != nil { + ec.Error(ctx, err) + return func() graphql.Marshaler { + return graphql.Null + } + } + if data, ok := tmp.(func() graphql.Marshaler); ok { + return data + } + ec.Errorf(ctx, `unexpected type %T from directive, should be graphql.Marshaler`, tmp) + return func() graphql.Marshaler { + return graphql.Null + } +} +{{ end }} + +{{ if .Directives.LocationDirectives "FIELD" }} + func (ec *executionContext) _fieldMiddleware(ctx context.Context, obj interface{}, next graphql.Resolver) interface{} { + {{- if .Directives.LocationDirectives "FIELD" }} + fc := graphql.GetFieldContext(ctx) + for _, d := range fc.Field.Directives { + switch d.Name { + {{- range $directive := .Directives.LocationDirectives "FIELD" }} + case "{{$directive.Name}}": + {{- 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) { + if ec.directives.{{$directive.Name|ucFirst}} == nil { + return nil, errors.New("directive {{$directive.Name}} is not implemented") + } + 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 + } +{{ end }} diff --git a/vendor/github.com/99designs/gqlgen/codegen/field.go b/vendor/github.com/99designs/gqlgen/codegen/field.go index f5f7b2213..26ed6b551 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/field.go +++ b/vendor/github.com/99designs/gqlgen/codegen/field.go @@ -11,7 +11,7 @@ import ( "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" "github.com/pkg/errors" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type Field struct { @@ -27,6 +27,7 @@ type Field struct { 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 + Stream bool // does this field return a channel? Directives []*Directive } @@ -73,17 +74,26 @@ func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, e return &f, nil } -func (b *builder) bindField(obj *Object, f *Field) error { +func (b *builder) bindField(obj *Object, f *Field) (errret error) { defer func() { if f.TypeReference == nil { tr, err := b.Binder.TypeReference(f.Type, nil) if err != nil { - panic(err) + errret = err } f.TypeReference = tr } + if f.TypeReference != nil { + dirs, err := b.getDirectives(f.TypeReference.Definition.Directives) + if err != nil { + errret = err + } + f.Directives = append(dirs, f.Directives...) + } }() + f.Stream = obj.Stream + switch { case f.Name == "__schema": f.GoFieldType = GoFieldMethod @@ -95,6 +105,18 @@ func (b *builder) bindField(obj *Object, f *Field) error { f.GoReceiverName = "ec" f.GoFieldName = "introspectType" return nil + case f.Name == "_entities": + f.GoFieldType = GoFieldMethod + f.GoReceiverName = "ec" + f.GoFieldName = "__resolve_entities" + f.MethodHasContext = true + return nil + case f.Name == "_service": + f.GoFieldType = GoFieldMethod + f.GoReceiverName = "ec" + f.GoFieldName = "__resolve__service" + f.MethodHasContext = true + return nil case obj.Root: f.IsResolver = true return nil @@ -181,75 +203,155 @@ func (b *builder) bindField(obj *Object, f *Field) error { } } -// 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 +// findBindTarget attempts to match the name to a field or method on a Type +// with the following priorites: +// 1. Any Fields with a struct tag (see config.StructTag). Errors if more than one match is found +// 2. Any method or field with a matching name. Errors if more than one match is found +// 3. Same logic again for embedded fields +func (b *builder) findBindTarget(t types.Type, name string) (types.Object, error) { + // NOTE: a struct tag will override both methods and fields + // Bind to struct tag + found, err := b.findBindStructTagTarget(t, name) + if found != nil || err != nil { + return found, err } - strukt, ok := named.Underlying().(*types.Struct) - if !ok { - return nil, fmt.Errorf("not a struct") + // Search for a method to bind to + foundMethod, err := b.findBindMethodTarget(t, name) + if err != nil { + return nil, err } - return b.findBindStructTarget(strukt, name) + + // Search for a field to bind to + foundField, err := b.findBindFieldTarget(t, name) + if err != nil { + return nil, err + } + + switch { + case foundField == nil && foundMethod != nil: + // Bind to method + return foundMethod, nil + case foundField != nil && foundMethod == nil: + // Bind to field + return foundField, nil + case foundField != nil && foundMethod != nil: + // Error + return nil, errors.Errorf("found more than one way to bind for %s", name) + } + + // Search embeds + return b.findBindEmbedsTarget(t, 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() { +func (b *builder) findBindStructTagTarget(in types.Type, name string) (types.Object, error) { + if b.Config.StructTag == "" { + return nil, nil + } + + switch t := in.(type) { + case *types.Named: + return b.findBindStructTagTarget(t.Underlying(), name) + case *types.Struct: + var found types.Object + for i := 0; i < t.NumFields(); i++ { + field := t.Field(i) + if !field.Exported() || field.Embedded() { continue } - tags := reflect.StructTag(strukt.Tag(i)) + tags := reflect.StructTag(t.Tag(i)) if val, ok := tags.Lookup(b.Config.StructTag); ok && equalFieldName(val, name) { - if foundField != nil { + if found != nil { return nil, errors.Errorf("tag %s is ambigious; multiple fields have the same tag value of %s", b.Config.StructTag, val) } - foundField = field + found = field } } - if foundField != nil { - return foundField, nil - } + + return found, 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 + return nil, nil +} + +func (b *builder) findBindMethodTarget(in types.Type, name string) (types.Object, error) { + switch t := in.(type) { + case *types.Named: + if _, ok := t.Underlying().(*types.Interface); ok { + return b.findBindMethodTarget(t.Underlying(), name) } + + return b.findBindMethoderTarget(t.Method, t.NumMethods(), name) + case *types.Interface: + // FIX-ME: Should use ExplicitMethod here? What's the difference? + return b.findBindMethoderTarget(t.Method, t.NumMethods(), name) } - // Then look in embedded structs - for i := 0; i < strukt.NumFields(); i++ { - field := strukt.Field(i) - if !field.Exported() { + return nil, nil +} + +func (b *builder) findBindMethoderTarget(methodFunc func(i int) *types.Func, methodCount int, name string) (types.Object, error) { + var found types.Object + for i := 0; i < methodCount; i++ { + method := methodFunc(i) + if !method.Exported() || !strings.EqualFold(method.Name(), name) { continue } - if !field.Anonymous() { + if found != nil { + return nil, errors.Errorf("found more than one matching method to bind for %s", name) + } + + found = method + } + + return found, nil +} + +func (b *builder) findBindFieldTarget(in types.Type, name string) (types.Object, error) { + switch t := in.(type) { + case *types.Named: + return b.findBindFieldTarget(t.Underlying(), name) + case *types.Struct: + var found types.Object + for i := 0; i < t.NumFields(); i++ { + field := t.Field(i) + if !field.Exported() || !equalFieldName(field.Name(), name) { + continue + } + + if found != nil { + return nil, errors.Errorf("found more than one matching field to bind for %s", name) + } + + found = field + } + + return found, nil + } + + return nil, nil +} + +func (b *builder) findBindEmbedsTarget(in types.Type, name string) (types.Object, error) { + switch t := in.(type) { + case *types.Named: + return b.findBindEmbedsTarget(t.Underlying(), name) + case *types.Struct: + return b.findBindStructEmbedsTarget(t, name) + case *types.Interface: + return b.findBindInterfaceEmbedsTarget(t, name) + } + + return nil, nil +} + +func (b *builder) findBindStructEmbedsTarget(strukt *types.Struct, name string) (types.Object, error) { + var found types.Object + for i := 0; i < strukt.NumFields(); i++ { + field := strukt.Field(i) + if !field.Embedded() { continue } @@ -258,33 +360,68 @@ func (b *builder) findBindStructTarget(strukt *types.Struct, name string) (types 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())) + f, err := b.findBindTarget(fieldType, name) + if err != nil { + return nil, err + } + + if f != nil && found != nil { + return nil, errors.Errorf("found more than one way to bind for %s", name) + } + + if f != nil { + found = f } } - return nil, nil + return found, nil +} + +func (b *builder) findBindInterfaceEmbedsTarget(iface *types.Interface, name string) (types.Object, error) { + var found types.Object + for i := 0; i < iface.NumEmbeddeds(); i++ { + embeddedType := iface.EmbeddedType(i) + + f, err := b.findBindTarget(embeddedType, name) + if err != nil { + return nil, err + } + + if f != nil && found != nil { + return nil, errors.Errorf("found more than one way to bind for %s", name) + } + + if f != nil { + found = f + } + } + + return found, nil } func (f *Field) HasDirectives() bool { - return len(f.Directives) > 0 + return len(f.ImplDirectives()) > 0 +} + +func (f *Field) DirectiveObjName() string { + if f.Object.Root { + return "nil" + } + return f.GoReceiverName +} + +func (f *Field) ImplDirectives() []*Directive { + var d []*Directive + loc := ast.LocationFieldDefinition + if f.Object.IsInputType() { + loc = ast.LocationInputFieldDefinition + } + for i := range f.Directives { + if !f.Directives[i].Builtin && f.Directives[i].IsLocation(loc, ast.LocationObject) { + d = append(d, f.Directives[i]) + } + } + return d } func (f *Field) IsReserved() bool { @@ -338,7 +475,7 @@ func (f *Field) ShortResolverDeclaration() string { res := "(ctx context.Context" if !f.Object.Root { - res += fmt.Sprintf(", obj *%s", templates.CurrentImports.LookupType(f.Object.Type)) + res += fmt.Sprintf(", obj %s", templates.CurrentImports.LookupType(f.Object.Reference())) } for _, arg := range f.Args { res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO)) @@ -354,7 +491,7 @@ func (f *Field) ShortResolverDeclaration() string { } func (f *Field) ComplexitySignature() string { - res := fmt.Sprintf("func(childComplexity int") + res := "func(childComplexity int" for _, arg := range f.Args { res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO)) } @@ -363,16 +500,16 @@ func (f *Field) ComplexitySignature() string { } 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)+")") + args := make([]string, len(f.Args)) + for i, arg := range f.Args { + args[i] = "args[" + strconv.Quote(arg.Name) + "].(" + templates.CurrentImports.LookupType(arg.TypeReference.GO) + ")" } return strings.Join(args, ", ") } func (f *Field) CallArgs() string { - var args []string + args := make([]string, 0, len(f.Args)+2) if f.IsResolver { args = append(args, "rctx") @@ -380,10 +517,8 @@ func (f *Field) CallArgs() string { if !f.Object.Root { args = append(args, "obj") } - } else { - if f.MethodHasContext { - args = append(args, "ctx") - } + } else if f.MethodHasContext { + args = append(args, "ctx") } for _, arg := range f.Args { diff --git a/vendor/github.com/99designs/gqlgen/codegen/field.gotpl b/vendor/github.com/99designs/gqlgen/codegen/field.gotpl index 9718a08aa..993625b74 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/field.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/field.gotpl @@ -1,29 +1,57 @@ {{- 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 }} +func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) (ret {{ if $object.Stream }}func(){{ end }}graphql.Marshaler) { + {{- $null := "graphql.Null" }} + {{- if $object.Stream }} + {{- $null = "nil" }} + {{- end }} + defer func () { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = {{ $null }} + } + }() + fc := &graphql.FieldContext{ + Object: {{$object.Name|quote}}, + Field: field, + Args: nil, + IsMethod: {{or $field.IsMethod $field.IsResolver}}, + } + + ctx = graphql.WithFieldContext(ctx, fc) + {{- if $field.Args }} + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs) if err != nil { ec.Error(ctx, err) - return nil + return {{ $null }} } + fc.Args = args + {{- end }} + {{- if $.Directives.LocationDirectives "FIELD" }} + resTmp := ec._fieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) { + {{ template "field" $field }} + }) + {{ else }} + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + {{ template "field" $field }} + }) + if err != nil { + ec.Error(ctx, err) + return {{ $null }} + } + {{- end }} + if resTmp == nil { + {{- if $field.TypeReference.GQL.NonNull }} + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + {{- end }} + return {{ $null }} + } + {{- if $object.Stream }} return func() graphql.Marshaler { - res, ok := <-results + res, ok := <-resTmp.(<-chan {{$field.TypeReference.GO | ref}}) if !ok { return nil } @@ -35,66 +63,60 @@ 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 - } + {{- else }} res := resTmp.({{$field.TypeReference.GO | ref}}) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res) - } -{{ end }} + {{- end }} +} {{- end }}{{- end}} + +{{ define "field" }} + {{- if .HasDirectives -}} + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + {{ template "fieldDefinition" . }} + } + {{ template "implDirectives" . }} + tmp, err := directive{{.ImplDirectives|len}}(rctx) + if err != nil { + return nil, err + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.({{if .Stream}}<-chan {{end}}{{ .TypeReference.GO | ref }}) ; ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be {{if .Stream}}<-chan {{end}}{{ .TypeReference.GO }}`, tmp) + {{- else -}} + ctx = rctx // use context from middleware stack in children + {{ template "fieldDefinition" . }} + {{- end -}} +{{ end }} + +{{ define "fieldDefinition" }} + {{- if .IsResolver -}} + return ec.resolvers.{{ .ShortInvocation }} + {{- else if .IsMap -}} + switch v := {{.GoReceiverName}}[{{.Name|quote}}].(type) { + case {{if .Stream}}<-chan {{end}}{{.TypeReference.GO | ref}}: + return v, nil + case {{if .Stream}}<-chan {{end}}{{.TypeReference.Elem.GO | ref}}: + return &v, nil + case nil: + return ({{.TypeReference.GO | ref}})(nil), nil + default: + return nil, fmt.Errorf("unexpected type %T for field %s", v, {{ .Name | quote}}) + } + {{- else if .IsMethod -}} + {{- if .NoErr -}} + return {{.GoReceiverName}}.{{.GoFieldName}}({{ .CallArgs }}), nil + {{- else -}} + return {{.GoReceiverName}}.{{.GoFieldName}}({{ .CallArgs }}) + {{- end -}} + {{- else if .IsVariable -}} + return {{.GoReceiverName}}.{{.GoFieldName}}, nil + {{- end }} +{{- end }} diff --git a/vendor/github.com/99designs/gqlgen/codegen/generate.go b/vendor/github.com/99designs/gqlgen/codegen/generate.go index eafa3f874..f1ed2ca27 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/generate.go +++ b/vendor/github.com/99designs/gqlgen/codegen/generate.go @@ -11,5 +11,6 @@ func GenerateCode(data *Data) error { Data: data, RegionTags: true, GeneratedHeader: true, + Packages: data.Config.Packages, }) } diff --git a/vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl b/vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl index 5753f1d13..864d15deb 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl @@ -8,8 +8,8 @@ {{ reserveImport "errors" }} {{ reserveImport "bytes" }} -{{ reserveImport "github.com/vektah/gqlparser" }} -{{ reserveImport "github.com/vektah/gqlparser/ast" }} +{{ reserveImport "github.com/vektah/gqlparser/v2" "gqlparser" }} +{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }} {{ reserveImport "github.com/99designs/gqlgen/graphql" }} {{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }} @@ -39,7 +39,7 @@ type ResolverRoot interface { type DirectiveRoot struct { {{ range $directive := .Directives }} - {{ $directive.Declaration }} + {{- $directive.Declaration }} {{ end }} } @@ -112,129 +112,86 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } -func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - {{- if .QueryRoot }} - ec := executionContext{graphql.GetRequestContext(ctx), e} +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e} + first := true - buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._{{.QueryRoot.Name}}(ctx, op.SelectionSet) + switch rc.Operation.Operation { + {{- if .QueryRoot }} case ast.Query: + return func(ctx context.Context) *graphql.Response { + if !first { return nil } + first = false + {{ if .Directives.LocationDirectives "QUERY" -}} + data := ec._queryMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){ + return ec._{{.QueryRoot.Name}}(ctx, rc.Operation.SelectionSet), nil + }) + {{- else -}} + data := ec._{{.QueryRoot.Name}}(ctx, rc.Operation.SelectionSet) + {{- end }} 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, + Data: buf.Bytes(), } } - {{- else }} - return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported")) - {{- end }} + {{ end }} + + {{- if .MutationRoot }} case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { return nil } + first = false + {{ if .Directives.LocationDirectives "MUTATION" -}} + data := ec._mutationMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){ + return ec._{{.MutationRoot.Name}}(ctx, rc.Operation.SelectionSet), nil + }) + {{- else -}} + data := ec._{{.MutationRoot.Name}}(ctx, rc.Operation.SelectionSet) + {{- end }} + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + {{ end }} + + {{- if .SubscriptionRoot }} case ast.Subscription: + {{ if .Directives.LocationDirectives "SUBSCRIPTION" -}} + next := ec._subscriptionMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){ + return ec._{{.SubscriptionRoot.Name}}(ctx, rc.Operation.SelectionSet),nil + }) + {{- else -}} + next := ec._{{.SubscriptionRoot.Name}}(ctx, rc.Operation.SelectionSet) + {{- end }} + + var buf bytes.Buffer + return func(ctx context.Context) *graphql.Response { + buf.Reset() + data := next() + + if data == nil { + return nil + } + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + {{ end }} + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) + } } type executionContext struct { - *graphql.RequestContext + *graphql.OperationContext *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") @@ -249,8 +206,9 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er 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 }} -) +var sources = []*ast.Source{ +{{- range $source := .Config.Sources }} + {Name: {{$source.Name|quote}}, Input: {{$source.Input|rawQuote}}, BuiltIn: {{$source.BuiltIn}}}, +{{- end }} +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) diff --git a/vendor/github.com/99designs/gqlgen/codegen/input.gotpl b/vendor/github.com/99designs/gqlgen/codegen/input.gotpl index c8ac7ad3a..56f9347c4 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/input.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/input.gotpl @@ -1,8 +1,8 @@ {{- range $input := .Inputs }} {{- if not .HasUnmarshal }} - func (ec *executionContext) unmarshalInput{{ .Name }}(ctx context.Context, v interface{}) ({{.Type | ref}}, error) { + func (ec *executionContext) unmarshalInput{{ .Name }}(ctx context.Context, obj interface{}) ({{.Type | ref}}, error) { var it {{.Type | ref}} - var asMap = v.(map[string]interface{}) + var asMap = obj.(map[string]interface{}) {{ range $field := .Fields}} {{- if $field.Default}} if _, present := asMap[{{$field.Name|quote}}] ; !present { @@ -16,27 +16,21 @@ {{- 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) + ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField({{$field.Name|quote}})) + {{- if $field.ImplDirectives }} + directive0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v) } + {{ template "implDirectives" $field }} + tmp, err := directive{{$field.ImplDirectives|len}}(ctx) if err != nil { return it, err } if data, ok := tmp.({{ $field.TypeReference.GO | ref }}) ; ok { it.{{$field.GoFieldName}} = data + {{- if $field.TypeReference.IsNilable }} + } else if tmp == nil { + it.{{$field.GoFieldName}} = nil + {{- end }} } else { return it, fmt.Errorf(`unexpected type %T from directive, should be {{ $field.TypeReference.GO }}`, tmp) } diff --git a/vendor/github.com/99designs/gqlgen/codegen/interface.go b/vendor/github.com/99designs/gqlgen/codegen/interface.go index f59e8ed07..a55ce1e6b 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/interface.go +++ b/vendor/github.com/99designs/gqlgen/codegen/interface.go @@ -1,9 +1,13 @@ package codegen import ( + "fmt" "go/types" - "github.com/vektah/gqlparser/ast" + "github.com/pkg/errors" + "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/codegen/config" ) type Interface struct { @@ -16,11 +20,11 @@ type Interface struct { type InterfaceImplementor struct { *ast.Definition - Interface *Interface - Type types.Type + Type types.Type + TakeRef bool } -func (b *builder) buildInterface(typ *ast.Definition) *Interface { +func (b *builder) buildInterface(typ *ast.Definition) (*Interface, error) { obj, err := b.Binder.DefaultUserObject(typ.Name) if err != nil { panic(err) @@ -32,32 +36,53 @@ func (b *builder) buildInterface(typ *ast.Definition) *Interface { InTypemap: b.Config.Models.UserDefined(typ.Name), } + interfaceType, err := findGoInterface(i.Type) + if interfaceType == nil || err != nil { + return nil, fmt.Errorf("%s is not an interface", i.Type) + } + for _, implementor := range b.Schema.GetPossibleTypes(typ) { obj, err := b.Binder.DefaultUserObject(implementor.Name) if err != nil { - panic(err) + return nil, fmt.Errorf("%s has no backing go type", implementor.Name) } - i.Implementors = append(i.Implementors, InterfaceImplementor{ - Definition: implementor, - Type: obj, - Interface: i, - }) + implementorType, err := findGoNamedType(obj) + if err != nil { + return nil, errors.Wrapf(err, "can not find backing go type %s", obj.String()) + } else if implementorType == nil { + return nil, fmt.Errorf("can not find backing go type %s", obj.String()) + } + + anyValid := false + + // first check if the value receiver can be nil, eg can we type switch on case Thing: + if types.Implements(implementorType, interfaceType) { + i.Implementors = append(i.Implementors, InterfaceImplementor{ + Definition: implementor, + Type: obj, + TakeRef: !types.IsInterface(obj), + }) + anyValid = true + } + + // then check if the pointer receiver can be nil, eg can we type switch on case *Thing: + if types.Implements(types.NewPointer(implementorType), interfaceType) { + i.Implementors = append(i.Implementors, InterfaceImplementor{ + Definition: implementor, + Type: types.NewPointer(obj), + }) + anyValid = true + } + + if !anyValid { + return nil, fmt.Errorf("%s does not satisfy the interface %s", implementorType.String(), i.Type.String()) + } } - return i + return i, nil } -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) +func (i *InterfaceImplementor) CanBeNil() bool { + return config.IsNilable(i.Type) } diff --git a/vendor/github.com/99designs/gqlgen/codegen/interface.gotpl b/vendor/github.com/99designs/gqlgen/codegen/interface.gotpl index 81a580765..e9d560c8f 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/interface.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/interface.gotpl @@ -1,16 +1,17 @@ {{- range $interface := .Interfaces }} -func (ec *executionContext) _{{$interface.Name}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.Type | ref}}) graphql.Marshaler { - switch obj := (*obj).(type) { +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) + case {{$implementor.Type | ref}}: + {{- if $implementor.CanBeNil }} + if obj == nil { + return graphql.Null + } + {{- end }} + return ec._{{$implementor.Name}}(ctx, sel, {{ if $implementor.TakeRef }}&{{ end }}obj) {{- end }} default: panic(fmt.Errorf("unexpected type %T", obj)) diff --git a/vendor/github.com/99designs/gqlgen/codegen/object.go b/vendor/github.com/99designs/gqlgen/codegen/object.go index 539c3164c..7b91c9004 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/object.go +++ b/vendor/github.com/99designs/gqlgen/codegen/object.go @@ -8,7 +8,7 @@ import ( "github.com/99designs/gqlgen/codegen/config" "github.com/pkg/errors" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type GoFieldType int @@ -82,11 +82,9 @@ func (b *builder) buildObject(typ *ast.Definition) (*Object, error) { } func (o *Object) Reference() types.Type { - switch o.Type.(type) { - case *types.Pointer, *types.Slice, *types.Map: + if config.IsNilable(o.Type) { return o.Type } - return types.NewPointer(o.Type) } @@ -114,8 +112,7 @@ func (o *Object) HasUnmarshal() bool { return true } for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ { - switch o.Type.(*types.Named).Method(i).Name() { - case "UnmarshalGQL": + if o.Type.(*types.Named).Method(i).Name() == "UnmarshalGQL" { return true } } diff --git a/vendor/github.com/99designs/gqlgen/codegen/object.gotpl b/vendor/github.com/99designs/gqlgen/codegen/object.gotpl index 98a75740e..33775a0b4 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/object.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/object.gotpl @@ -4,8 +4,8 @@ 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{ + fields := graphql.CollectFields(ec.OperationContext, sel, {{$object.Name|lcFirst}}Implementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ Object: {{$object.Name|quote}}, }) if len(fields) != 1 { @@ -24,9 +24,9 @@ func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.Selec } {{- 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) + fields := graphql.CollectFields(ec.OperationContext, sel, {{$object.Name|lcFirst}}Implementors) {{if $object.Root}} - ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ Object: {{$object.Name|quote}}, }) {{end}} diff --git a/vendor/github.com/99designs/gqlgen/codegen/templates/import.go b/vendor/github.com/99designs/gqlgen/codegen/templates/import.go index effe9a0df..17bd96ab2 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/templates/import.go +++ b/vendor/github.com/99designs/gqlgen/codegen/templates/import.go @@ -4,6 +4,7 @@ import ( "fmt" "go/types" "strconv" + "strings" "github.com/99designs/gqlgen/internal/code" ) @@ -15,12 +16,13 @@ type Import struct { } type Imports struct { - imports []*Import - destDir string + imports []*Import + destDir string + packages *code.Packages } func (i *Import) String() string { - if i.Alias == i.Name { + if strings.HasSuffix(i.Path, i.Alias) { return strconv.Quote(i.Path) } @@ -48,7 +50,7 @@ func (s *Imports) Reserve(path string, aliases ...string) (string, error) { return "", nil } - name := code.NameForPackage(path) + name := s.packages.NameForPackage(path) var alias string if len(aliases) != 1 { alias = name @@ -93,7 +95,7 @@ func (s *Imports) Lookup(path string) string { } imp := &Import{ - Name: code.NameForPackage(path), + Name: s.packages.NameForPackage(path), Path: path, } s.imports = append(s.imports, imp) diff --git a/vendor/github.com/99designs/gqlgen/codegen/templates/templates.go b/vendor/github.com/99designs/gqlgen/codegen/templates/templates.go index f2fcb568e..79b0c5c7d 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/templates/templates.go +++ b/vendor/github.com/99designs/gqlgen/codegen/templates/templates.go @@ -15,6 +15,8 @@ import ( "text/template" "unicode" + "github.com/99designs/gqlgen/internal/code" + "github.com/99designs/gqlgen/internal/imports" "github.com/pkg/errors" ) @@ -40,9 +42,16 @@ type Options struct { Filename string RegionTags bool GeneratedHeader bool + // PackageDoc is documentation written above the package line + PackageDoc string + // FileNotice is notice written below the package line + FileNotice string // Data will be passed to the template execution. Data interface{} Funcs template.FuncMap + + // Packages cache, you can find me on config.Config + Packages *code.Packages } // Render renders a gql plugin template from the given Options. Render is an @@ -53,7 +62,7 @@ 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)} + CurrentImports = &Imports{packages: cfg.Packages, destDir: filepath.Dir(cfg.Filename)} // load path relative to calling source file _, callerFile, _, _ := runtime.Caller(1) @@ -131,9 +140,16 @@ func Render(cfg Options) error { if cfg.GeneratedHeader { result.WriteString("// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\n") } + if cfg.PackageDoc != "" { + result.WriteString(cfg.PackageDoc + "\n") + } result.WriteString("package ") result.WriteString(cfg.PackageName) result.WriteString("\n\n") + if cfg.FileNotice != "" { + result.WriteString(cfg.FileNotice) + result.WriteString("\n\n") + } result.WriteString("import (\n") result.WriteString(CurrentImports.String()) result.WriteString(")\n") @@ -143,7 +159,13 @@ func Render(cfg Options) error { } CurrentImports = nil - return write(cfg.Filename, result.Bytes()) + err = write(cfg.Filename, result.Bytes(), cfg.Packages) + if err != nil { + return err + } + + cfg.Packages.Evict(code.ImportPathForDir(filepath.Dir(cfg.Filename))) + return nil } func center(width int, pad string, s string) string { @@ -157,8 +179,8 @@ func center(width int, pad string, s string) string { func Funcs() template.FuncMap { return template.FuncMap{ - "ucFirst": ucFirst, - "lcFirst": lcFirst, + "ucFirst": UcFirst, + "lcFirst": LcFirst, "quote": strconv.Quote, "rawQuote": rawQuote, "dump": Dump, @@ -180,7 +202,7 @@ func Funcs() template.FuncMap { } } -func ucFirst(s string) string { +func UcFirst(s string) string { if s == "" { return "" } @@ -189,7 +211,7 @@ func ucFirst(s string) string { return string(r) } -func lcFirst(s string) string { +func LcFirst(s string) string { if s == "" { return "" } @@ -211,6 +233,7 @@ var pkgReplacer = strings.NewReplacer( "/", "ᚋ", ".", "ᚗ", "-", "ᚑ", + "~", "א", ) func TypeIdentifier(t types.Type) string { @@ -260,6 +283,9 @@ func Call(p *types.Func) string { } func ToGo(name string) string { + if name == "_" { + return "_" + } runes := make([]rune, 0, len(name)) wordWalker(name, func(info *wordInfo) { @@ -270,7 +296,7 @@ func ToGo(name string) string { if strings.ToUpper(word) == word || strings.ToLower(word) == word { // FOO or foo → Foo // FOo → FOo - word = ucFirst(strings.ToLower(word)) + word = UcFirst(strings.ToLower(word)) } } runes = append(runes, []rune(word)...) @@ -280,24 +306,28 @@ func ToGo(name string) string { } func ToGoPrivate(name string) string { + if name == "_" { + return "_" + } runes := make([]rune, 0, len(name)) first := true wordWalker(name, func(info *wordInfo) { word := info.Word - if first { + switch { + case 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) + word = LcFirst(info.Word) } first = false - } else if info.MatchCommonInitial { + case info.MatchCommonInitial: word = strings.ToUpper(word) - } else if !info.HasCommonInitial { - word = ucFirst(strings.ToLower(word)) + case !info.HasCommonInitial: + word = UcFirst(strings.ToLower(word)) } runes = append(runes, []rune(word)...) }) @@ -314,14 +344,15 @@ type wordInfo struct { // 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) + runes := []rune(strings.TrimFunc(str, isDelimiter)) 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) { + switch { + case i+1 == len(runes): eow = true - } else if isDelimiter(runes[i+1]) { + case isDelimiter(runes[i+1]): // underscore; shift the remainder forward over any run of underscores eow = true n := 1 @@ -336,7 +367,7 @@ func wordWalker(str string, f func(*wordInfo)) { copy(runes[i+1:], runes[i+n+1:]) runes = runes[:len(runes)-n] - } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { + case unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]): // lower->non-lower eow = true } @@ -429,6 +460,7 @@ var commonInitialisms = map[string]bool{ "IP": true, "JSON": true, "LHS": true, + "PGP": true, "QPS": true, "RAM": true, "RHS": true, @@ -549,13 +581,13 @@ func render(filename string, tpldata interface{}) (*bytes.Buffer, error) { return buf, t.Execute(buf, tpldata) } -func write(filename string, b []byte) error { +func write(filename string, b []byte, packages *code.Packages) 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) + formatted, err := imports.Prune(filename, b, packages) if err != nil { fmt.Fprintf(os.Stderr, "gofmt failed on %s: %s\n", filepath.Base(filename), err.Error()) formatted = b diff --git a/vendor/github.com/99designs/gqlgen/codegen/type.go b/vendor/github.com/99designs/gqlgen/codegen/type.go index e00837323..06b370be7 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/type.go +++ b/vendor/github.com/99designs/gqlgen/codegen/type.go @@ -1,18 +1,32 @@ package codegen import ( + "fmt" + "github.com/99designs/gqlgen/codegen/config" ) -func (b *builder) buildTypes() (map[string]*config.TypeReference, error) { +func (b *builder) buildTypes() map[string]*config.TypeReference { ret := map[string]*config.TypeReference{} - for _, ref := range b.Binder.References { - for ref != nil { - ret[ref.UniquenessKey()] = ref + processType(ret, ref) + } + return ret +} - ref = ref.Elem() +func processType(ret map[string]*config.TypeReference, ref *config.TypeReference) { + key := ref.UniquenessKey() + if existing, found := ret[key]; found { + // Simplistic check of content which is obviously different. + existingGQL := fmt.Sprintf("%v", existing.GQL) + newGQL := fmt.Sprintf("%v", ref.GQL) + if existingGQL != newGQL { + panic(fmt.Sprintf("non-unique key \"%s\", trying to replace %s with %s", key, existingGQL, newGQL)) } } - return ret, nil + ret[key] = ref + + if ref.IsSlice() { + processType(ret, ref.Elem()) + } } diff --git a/vendor/github.com/99designs/gqlgen/codegen/type.gotpl b/vendor/github.com/99designs/gqlgen/codegen/type.gotpl index cb2782c39..2bd0c1943 100644 --- a/vendor/github.com/99designs/gqlgen/codegen/type.gotpl +++ b/vendor/github.com/99designs/gqlgen/codegen/type.gotpl @@ -1,13 +1,10 @@ {{- range $type := .ReferencedTypes }} {{ with $type.UnmarshalFunc }} func (ec *executionContext) {{ . }}(ctx context.Context, v interface{}) ({{ $type.GO | ref }}, error) { - {{- if $type.IsNilable }} + {{- if and $type.IsNilable (not $type.GQL.NonNull) }} 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 }} + {{- if $type.IsSlice }} var vSlice []interface{} if v != nil { if tmp1, ok := v.([]interface{}); ok { @@ -19,9 +16,10 @@ var err error res := make([]{{$type.GO.Elem | ref}}, len(vSlice)) for i := range vSlice { + ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithIndex(i)) res[i], err = ec.{{ $type.Elem.UnmarshalFunc }}(ctx, vSlice[i]) if err != nil { - return nil, err + return nil, graphql.WrapErrorWithInputPath(ctx, err) } } return res, nil @@ -29,17 +27,38 @@ {{- if $type.Unmarshaler }} {{- if $type.CastType }} tmp, err := {{ $type.Unmarshaler | call }}(v) - return {{ $type.GO | ref }}(tmp), err + {{- if $type.IsNilable }} + res := {{ $type.Elem.GO | ref }}(tmp) + {{- else}} + res := {{ $type.GO | ref }}(tmp) + {{- end }} {{- else}} - return {{ $type.Unmarshaler | call }}(v) + res, err := {{ $type.Unmarshaler | call }}(v) + {{- end }} + {{- if and $type.IsTargetNilable (not $type.IsNilable) }} + return *res, graphql.WrapErrorWithInputPath(ctx, err) + {{- else if and (not $type.IsTargetNilable) $type.IsNilable }} + return &res, graphql.WrapErrorWithInputPath(ctx, err) + {{- else}} + return res, graphql.WrapErrorWithInputPath(ctx, err) {{- 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 if $type.IsMarshaler }} + {{- if $type.IsNilable }} + var res = new({{ $type.Elem.GO | ref }}) + {{- else}} + var res {{ $type.GO | ref }} + {{- end }} + err := res.UnmarshalGQL(v) + return res, graphql.WrapErrorWithInputPath(ctx, err) {{- else }} - return ec.unmarshalInput{{ $type.GQL.Name }}(ctx, v) + res, err := ec.unmarshalInput{{ $type.GQL.Name }}(ctx, v) + {{- if $type.IsNilable }} + return &res, graphql.WrapErrorWithInputPath(ctx, err) + {{- else}} + return res, graphql.WrapErrorWithInputPath(ctx, err) + {{- end }} {{- end }} {{- end }} } @@ -47,17 +66,6 @@ {{ 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 { @@ -75,11 +83,11 @@ for i := range v { {{- if not $type.IsScalar }} i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -104,22 +112,35 @@ {{ if not $type.IsScalar }} wg.Wait() {{ end }} return ret {{- else }} - + {{- if $type.IsNilable }} + if v == nil { + {{- if $type.GQL.NonNull }} + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + {{- end }} + return graphql.Null + } + {{- end }} {{- 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 }}) + {{- $v := "v" }} + {{- if and $type.IsTargetNilable (not $type.IsNilable) }} + {{- $v = "&v" }} + {{- else if and (not $type.IsTargetNilable) $type.IsNilable }} + {{- $v = "*v" }} + {{- end }} + {{- 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)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(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 }}) + 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) diff --git a/vendor/github.com/99designs/gqlgen/complexity/complexity.go b/vendor/github.com/99designs/gqlgen/complexity/complexity.go index d5b46bf45..1877aae5f 100644 --- a/vendor/github.com/99designs/gqlgen/complexity/complexity.go +++ b/vendor/github.com/99designs/gqlgen/complexity/complexity.go @@ -2,7 +2,7 @@ package complexity import ( "github.com/99designs/gqlgen/graphql" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) func Calculate(es graphql.ExecutableSchema, op *ast.OperationDefinition, vars map[string]interface{}) int { diff --git a/vendor/github.com/99designs/gqlgen/go.mod b/vendor/github.com/99designs/gqlgen/go.mod index 9ff313d86..16affcf04 100644 --- a/vendor/github.com/99designs/gqlgen/go.mod +++ b/vendor/github.com/99designs/gqlgen/go.mod @@ -1,14 +1,19 @@ module github.com/99designs/gqlgen +go 1.12 + require ( - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/agnivade/levenshtein v1.0.3 // 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/gorilla/websocket v1.4.2 github.com/hashicorp/golang-lru v0.5.0 - github.com/kr/pretty v0.1.0 // indirect + github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 + github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 + github.com/mattn/go-colorable v0.1.4 + github.com/mattn/go-isatty v0.0.12 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 @@ -16,13 +21,13 @@ require ( 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/stretchr/testify v1.4.0 + github.com/urfave/cli/v2 v2.1.1 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 + github.com/vektah/gqlparser v1.3.1 + github.com/vektah/gqlparser/v2 v2.0.1 + golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 + gopkg.in/yaml.v2 v2.2.4 sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755 sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 // indirect ) diff --git a/vendor/github.com/99designs/gqlgen/go.sum b/vendor/github.com/99designs/gqlgen/go.sum index b2d54b1f7..02d393c3b 100644 --- a/vendor/github.com/99designs/gqlgen/go.sum +++ b/vendor/github.com/99designs/gqlgen/go.sum @@ -1,11 +1,20 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= +github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= 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/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM= +github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= 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= @@ -14,8 +23,8 @@ github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkH 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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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= @@ -23,6 +32,15 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 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= @@ -35,46 +53,61 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb 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/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 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/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= 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= +github.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU= +github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74= +github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o= +github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= 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/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= diff --git a/vendor/github.com/99designs/gqlgen/graphql/cache.go b/vendor/github.com/99designs/gqlgen/graphql/cache.go new file mode 100644 index 000000000..fe86ca350 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/cache.go @@ -0,0 +1,29 @@ +package graphql + +import "context" + +// Cache is a shared store for APQ and query AST caching +type Cache interface { + // Get looks up a key's value from the cache. + Get(ctx context.Context, key string) (value interface{}, ok bool) + + // Add adds a value to the cache. + Add(ctx context.Context, key string, value interface{}) +} + +// MapCache is the simplest implementation of a cache, because it can not evict it should only be used in tests +type MapCache map[string]interface{} + +// Get looks up a key's value from the cache. +func (m MapCache) Get(ctx context.Context, key string) (value interface{}, ok bool) { + v, ok := m[key] + return v, ok +} + +// Add adds a value to the cache. +func (m MapCache) Add(ctx context.Context, key string, value interface{}) { m[key] = value } + +type NoCache struct{} + +func (n NoCache) Get(ctx context.Context, key string) (value interface{}, ok bool) { return nil, false } +func (n NoCache) Add(ctx context.Context, key string, value interface{}) {} diff --git a/vendor/github.com/99designs/gqlgen/graphql/context.go b/vendor/github.com/99designs/gqlgen/graphql/context.go deleted file mode 100644 index 356f5175b..000000000 --- a/vendor/github.com/99designs/gqlgen/graphql/context.go +++ /dev/null @@ -1,274 +0,0 @@ -package graphql - -import ( - "context" - "fmt" - "sync" - - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" -) - -type Resolver func(ctx context.Context) (res interface{}, err error) -type FieldMiddleware func(ctx context.Context, next Resolver) (res interface{}, err error) -type RequestMiddleware func(ctx context.Context, next func(ctx context.Context) []byte) []byte -type ComplexityLimitFunc func(ctx context.Context) int - -type RequestContext struct { - RawQuery string - Variables map[string]interface{} - Doc *ast.QueryDocument - - ComplexityLimit int - OperationComplexity int - DisableIntrospection bool - - // ErrorPresenter will be used to generate the error - // message from errors given to Error(). - ErrorPresenter ErrorPresenterFunc - Recover RecoverFunc - ResolverMiddleware FieldMiddleware - DirectiveMiddleware FieldMiddleware - RequestMiddleware RequestMiddleware - Tracer Tracer - - errorsMu sync.Mutex - Errors gqlerror.List - extensionsMu sync.Mutex - Extensions map[string]interface{} -} - -func DefaultResolverMiddleware(ctx context.Context, next Resolver) (res interface{}, err error) { - return next(ctx) -} - -func DefaultDirectiveMiddleware(ctx context.Context, next Resolver) (res interface{}, err error) { - return next(ctx) -} - -func DefaultRequestMiddleware(ctx context.Context, next func(ctx context.Context) []byte) []byte { - return next(ctx) -} - -func NewRequestContext(doc *ast.QueryDocument, query string, variables map[string]interface{}) *RequestContext { - return &RequestContext{ - Doc: doc, - RawQuery: query, - Variables: variables, - ResolverMiddleware: DefaultResolverMiddleware, - DirectiveMiddleware: DefaultDirectiveMiddleware, - RequestMiddleware: DefaultRequestMiddleware, - Recover: DefaultRecover, - ErrorPresenter: DefaultErrorPresenter, - Tracer: &NopTracer{}, - } -} - -type key string - -const ( - request key = "request_context" - resolver key = "resolver_context" -) - -func GetRequestContext(ctx context.Context) *RequestContext { - if val, ok := ctx.Value(request).(*RequestContext); ok { - return val - } - return nil -} - -func WithRequestContext(ctx context.Context, rc *RequestContext) context.Context { - return context.WithValue(ctx, request, rc) -} - -type ResolverContext struct { - Parent *ResolverContext - // The name of the type this field belongs to - Object string - // These are the args after processing, they can be mutated in middleware to change what the resolver will get. - Args map[string]interface{} - // The raw field - Field CollectedField - // The index of array in path. - Index *int - // The result object of resolver - Result interface{} - // IsMethod indicates if the resolver is a method - IsMethod bool -} - -func (r *ResolverContext) Path() []interface{} { - var path []interface{} - for it := r; it != nil; it = it.Parent { - if it.Index != nil { - path = append(path, *it.Index) - } else if it.Field.Field != nil { - path = append(path, it.Field.Alias) - } - } - - // because we are walking up the chain, all the elements are backwards, do an inplace flip. - for i := len(path)/2 - 1; i >= 0; i-- { - opp := len(path) - 1 - i - path[i], path[opp] = path[opp], path[i] - } - - return path -} - -func GetResolverContext(ctx context.Context) *ResolverContext { - if val, ok := ctx.Value(resolver).(*ResolverContext); ok { - return val - } - return nil -} - -func WithResolverContext(ctx context.Context, rc *ResolverContext) context.Context { - rc.Parent = GetResolverContext(ctx) - return context.WithValue(ctx, resolver, rc) -} - -// This is just a convenient wrapper method for CollectFields -func CollectFieldsCtx(ctx context.Context, satisfies []string) []CollectedField { - resctx := GetResolverContext(ctx) - return CollectFields(GetRequestContext(ctx), resctx.Field.Selections, satisfies) -} - -// CollectAllFields returns a slice of all GraphQL field names that were selected for the current resolver context. -// The slice will contain the unique set of all field names requested regardless of fragment type conditions. -func CollectAllFields(ctx context.Context) []string { - resctx := GetResolverContext(ctx) - collected := CollectFields(GetRequestContext(ctx), resctx.Field.Selections, nil) - uniq := make([]string, 0, len(collected)) -Next: - for _, f := range collected { - for _, name := range uniq { - if name == f.Name { - continue Next - } - } - uniq = append(uniq, f.Name) - } - return uniq -} - -// Errorf sends an error string to the client, passing it through the formatter. -func (c *RequestContext) Errorf(ctx context.Context, format string, args ...interface{}) { - c.errorsMu.Lock() - defer c.errorsMu.Unlock() - - c.Errors = append(c.Errors, c.ErrorPresenter(ctx, fmt.Errorf(format, args...))) -} - -// Error sends an error to the client, passing it through the formatter. -func (c *RequestContext) Error(ctx context.Context, err error) { - c.errorsMu.Lock() - defer c.errorsMu.Unlock() - - c.Errors = append(c.Errors, c.ErrorPresenter(ctx, err)) -} - -// HasError returns true if the current field has already errored -func (c *RequestContext) HasError(rctx *ResolverContext) bool { - c.errorsMu.Lock() - defer c.errorsMu.Unlock() - path := rctx.Path() - - for _, err := range c.Errors { - if equalPath(err.Path, path) { - return true - } - } - return false -} - -// GetErrors returns a list of errors that occurred in the current field -func (c *RequestContext) GetErrors(rctx *ResolverContext) gqlerror.List { - c.errorsMu.Lock() - defer c.errorsMu.Unlock() - path := rctx.Path() - - var errs gqlerror.List - for _, err := range c.Errors { - if equalPath(err.Path, path) { - errs = append(errs, err) - } - } - return errs -} - -func equalPath(a []interface{}, b []interface{}) bool { - if len(a) != len(b) { - return false - } - - for i := 0; i < len(a); i++ { - if a[i] != b[i] { - return false - } - } - - return true -} - -// AddError is a convenience method for adding an error to the current response -func AddError(ctx context.Context, err error) { - GetRequestContext(ctx).Error(ctx, err) -} - -// AddErrorf is a convenience method for adding an error to the current response -func AddErrorf(ctx context.Context, format string, args ...interface{}) { - GetRequestContext(ctx).Errorf(ctx, format, args...) -} - -// RegisterExtension registers an extension, returns error if extension has already been registered -func (c *RequestContext) RegisterExtension(key string, value interface{}) error { - c.extensionsMu.Lock() - defer c.extensionsMu.Unlock() - - if c.Extensions == nil { - c.Extensions = make(map[string]interface{}) - } - - if _, ok := c.Extensions[key]; ok { - return fmt.Errorf("extension already registered for key %s", key) - } - - c.Extensions[key] = value - return nil -} - -// ChainFieldMiddleware add chain by FieldMiddleware -func ChainFieldMiddleware(handleFunc ...FieldMiddleware) FieldMiddleware { - n := len(handleFunc) - - if n > 1 { - lastI := n - 1 - return func(ctx context.Context, next Resolver) (interface{}, error) { - var ( - chainHandler Resolver - curI int - ) - chainHandler = func(currentCtx context.Context) (interface{}, error) { - if curI == lastI { - return next(currentCtx) - } - curI++ - res, err := handleFunc[curI](currentCtx, chainHandler) - curI-- - return res, err - - } - return handleFunc[0](ctx, chainHandler) - } - } - - if n == 1 { - return handleFunc[0] - } - - return func(ctx context.Context, next Resolver) (interface{}, error) { - return next(ctx) - } -} diff --git a/vendor/github.com/99designs/gqlgen/graphql/context_field.go b/vendor/github.com/99designs/gqlgen/graphql/context_field.go new file mode 100644 index 000000000..3c3385042 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/context_field.go @@ -0,0 +1,92 @@ +package graphql + +import ( + "context" + "time" + + "github.com/vektah/gqlparser/v2/ast" +) + +type key string + +const resolverCtx key = "resolver_context" + +// Deprecated: Use FieldContext instead +type ResolverContext = FieldContext + +type FieldContext struct { + Parent *FieldContext + // The name of the type this field belongs to + Object string + // These are the args after processing, they can be mutated in middleware to change what the resolver will get. + Args map[string]interface{} + // The raw field + Field CollectedField + // The index of array in path. + Index *int + // The result object of resolver + Result interface{} + // IsMethod indicates if the resolver is a method + IsMethod bool +} + +type FieldStats struct { + // When field execution started + Started time.Time + + // When argument marshaling finished + ArgumentsCompleted time.Time + + // When the field completed running all middleware. Not available inside field middleware! + Completed time.Time +} + +func (r *FieldContext) Path() ast.Path { + var path ast.Path + for it := r; it != nil; it = it.Parent { + if it.Index != nil { + path = append(path, ast.PathIndex(*it.Index)) + } else if it.Field.Field != nil { + path = append(path, ast.PathName(it.Field.Alias)) + } + } + + // because we are walking up the chain, all the elements are backwards, do an inplace flip. + for i := len(path)/2 - 1; i >= 0; i-- { + opp := len(path) - 1 - i + path[i], path[opp] = path[opp], path[i] + } + + return path +} + +// Deprecated: Use GetFieldContext instead +func GetResolverContext(ctx context.Context) *ResolverContext { + return GetFieldContext(ctx) +} + +func GetFieldContext(ctx context.Context) *FieldContext { + if val, ok := ctx.Value(resolverCtx).(*FieldContext); ok { + return val + } + return nil +} + +func WithFieldContext(ctx context.Context, rc *FieldContext) context.Context { + rc.Parent = GetFieldContext(ctx) + return context.WithValue(ctx, resolverCtx, rc) +} + +func equalPath(a ast.Path, b ast.Path) bool { + if len(a) != len(b) { + return false + } + + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + + return true +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/context_field_input.go b/vendor/github.com/99designs/gqlgen/graphql/context_field_input.go new file mode 100644 index 000000000..0ed6f8b66 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/context_field_input.go @@ -0,0 +1,85 @@ +package graphql + +import ( + "context" + + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +const fieldInputCtx key = "field_input_context" + +type FieldInputContext struct { + ParentField *FieldContext + ParentInput *FieldInputContext + Field *string + Index *int +} + +func (fic *FieldInputContext) Path() ast.Path { + var inputPath ast.Path + for it := fic; it != nil; it = it.ParentInput { + if it.Index != nil { + inputPath = append(inputPath, ast.PathIndex(*it.Index)) + } else if it.Field != nil { + inputPath = append(inputPath, ast.PathName(*it.Field)) + } + } + + // because we are walking up the chain, all the elements are backwards, do an inplace flip. + for i := len(inputPath)/2 - 1; i >= 0; i-- { + opp := len(inputPath) - 1 - i + inputPath[i], inputPath[opp] = inputPath[opp], inputPath[i] + } + + if fic.ParentField != nil { + fieldPath := fic.ParentField.Path() + return append(fieldPath, inputPath...) + + } + + return inputPath +} + +func NewFieldInputWithField(field string) *FieldInputContext { + return &FieldInputContext{Field: &field} +} + +func NewFieldInputWithIndex(index int) *FieldInputContext { + return &FieldInputContext{Index: &index} +} + +func WithFieldInputContext(ctx context.Context, fic *FieldInputContext) context.Context { + if fieldContext := GetFieldContext(ctx); fieldContext != nil { + fic.ParentField = fieldContext + } + if fieldInputContext := GetFieldInputContext(ctx); fieldInputContext != nil { + fic.ParentInput = fieldInputContext + } + + return context.WithValue(ctx, fieldInputCtx, fic) +} + +func GetFieldInputContext(ctx context.Context) *FieldInputContext { + if val, ok := ctx.Value(fieldInputCtx).(*FieldInputContext); ok { + return val + } + return nil +} + +func WrapErrorWithInputPath(ctx context.Context, err error) error { + if err == nil { + return nil + } + + inputContext := GetFieldInputContext(ctx) + path := inputContext.Path() + if gerr, ok := err.(*gqlerror.Error); ok { + if gerr.Path == nil { + gerr.Path = path + } + return gerr + } else { + return gqlerror.WrapPath(path, err) + } +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/context_operation.go b/vendor/github.com/99designs/gqlgen/graphql/context_operation.go new file mode 100644 index 000000000..d19b9fd34 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/context_operation.go @@ -0,0 +1,107 @@ +package graphql + +import ( + "context" + "errors" + + "github.com/vektah/gqlparser/v2/ast" +) + +// Deprecated: Please update all references to OperationContext instead +type RequestContext = OperationContext + +type OperationContext struct { + RawQuery string + Variables map[string]interface{} + OperationName string + Doc *ast.QueryDocument + + Operation *ast.OperationDefinition + DisableIntrospection bool + Recover RecoverFunc + ResolverMiddleware FieldMiddleware + + Stats Stats +} + +func (c *OperationContext) Validate(ctx context.Context) error { + if c.Doc == nil { + return errors.New("field 'Doc'is required") + } + if c.RawQuery == "" { + return errors.New("field 'RawQuery' is required") + } + if c.Variables == nil { + c.Variables = make(map[string]interface{}) + } + if c.ResolverMiddleware == nil { + return errors.New("field 'ResolverMiddleware' is required") + } + if c.Recover == nil { + c.Recover = DefaultRecover + } + + return nil +} + +const operationCtx key = "operation_context" + +// Deprecated: Please update all references to GetOperationContext instead +func GetRequestContext(ctx context.Context) *RequestContext { + return GetOperationContext(ctx) +} + +func GetOperationContext(ctx context.Context) *OperationContext { + if val, ok := ctx.Value(operationCtx).(*OperationContext); ok && val != nil { + return val + } + panic("missing operation context") +} + +func WithOperationContext(ctx context.Context, rc *OperationContext) context.Context { + return context.WithValue(ctx, operationCtx, rc) +} + +// HasOperationContext checks if the given context is part of an ongoing operation +// +// Some errors can happen outside of an operation, eg json unmarshal errors. +func HasOperationContext(ctx context.Context) bool { + _, ok := ctx.Value(operationCtx).(*OperationContext) + return ok +} + +// This is just a convenient wrapper method for CollectFields +func CollectFieldsCtx(ctx context.Context, satisfies []string) []CollectedField { + resctx := GetFieldContext(ctx) + return CollectFields(GetOperationContext(ctx), resctx.Field.Selections, satisfies) +} + +// CollectAllFields returns a slice of all GraphQL field names that were selected for the current resolver context. +// The slice will contain the unique set of all field names requested regardless of fragment type conditions. +func CollectAllFields(ctx context.Context) []string { + resctx := GetFieldContext(ctx) + collected := CollectFields(GetOperationContext(ctx), resctx.Field.Selections, nil) + uniq := make([]string, 0, len(collected)) +Next: + for _, f := range collected { + for _, name := range uniq { + if name == f.Name { + continue Next + } + } + uniq = append(uniq, f.Name) + } + return uniq +} + +// Errorf sends an error string to the client, passing it through the formatter. +// Deprecated: use graphql.AddErrorf(ctx, err) instead +func (c *OperationContext) Errorf(ctx context.Context, format string, args ...interface{}) { + AddErrorf(ctx, format, args...) +} + +// Error sends an error to the client, passing it through the formatter. +// Deprecated: use graphql.AddError(ctx, err) instead +func (c *OperationContext) Error(ctx context.Context, err error) { + AddError(ctx, err) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/context_response.go b/vendor/github.com/99designs/gqlgen/graphql/context_response.go new file mode 100644 index 000000000..cc952ed72 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/context_response.go @@ -0,0 +1,157 @@ +package graphql + +import ( + "context" + "fmt" + "sync" + + "github.com/vektah/gqlparser/v2/gqlerror" +) + +type responseContext struct { + errorPresenter ErrorPresenterFunc + recover RecoverFunc + + errors gqlerror.List + errorsMu sync.Mutex + + extensions map[string]interface{} + extensionsMu sync.Mutex +} + +const resultCtx key = "result_context" + +func getResponseContext(ctx context.Context) *responseContext { + val, ok := ctx.Value(resultCtx).(*responseContext) + if !ok { + panic("missing response context") + } + return val +} + +func WithResponseContext(ctx context.Context, presenterFunc ErrorPresenterFunc, recoverFunc RecoverFunc) context.Context { + return context.WithValue(ctx, resultCtx, &responseContext{ + errorPresenter: presenterFunc, + recover: recoverFunc, + }) +} + +// AddErrorf writes a formatted error to the client, first passing it through the error presenter. +func AddErrorf(ctx context.Context, format string, args ...interface{}) { + c := getResponseContext(ctx) + + c.errorsMu.Lock() + defer c.errorsMu.Unlock() + + c.errors = append(c.errors, c.errorPresenter(ctx, fmt.Errorf(format, args...))) +} + +// AddError sends an error to the client, first passing it through the error presenter. +func AddError(ctx context.Context, err error) { + c := getResponseContext(ctx) + + c.errorsMu.Lock() + defer c.errorsMu.Unlock() + + c.errors = append(c.errors, c.errorPresenter(ctx, err)) +} + +func Recover(ctx context.Context, err interface{}) (userMessage error) { + c := getResponseContext(ctx) + return c.recover(ctx, err) +} + +// HasFieldError returns true if the given field has already errored +func HasFieldError(ctx context.Context, rctx *FieldContext) bool { + c := getResponseContext(ctx) + + c.errorsMu.Lock() + defer c.errorsMu.Unlock() + + if len(c.errors) == 0 { + return false + } + + path := rctx.Path() + for _, err := range c.errors { + if equalPath(err.Path, path) { + return true + } + } + return false +} + +// GetFieldErrors returns a list of errors that occurred in the given field +func GetFieldErrors(ctx context.Context, rctx *FieldContext) gqlerror.List { + c := getResponseContext(ctx) + + c.errorsMu.Lock() + defer c.errorsMu.Unlock() + + if len(c.errors) == 0 { + return nil + } + + path := rctx.Path() + var errs gqlerror.List + for _, err := range c.errors { + if equalPath(err.Path, path) { + errs = append(errs, err) + } + } + return errs +} + +func GetErrors(ctx context.Context) gqlerror.List { + resCtx := getResponseContext(ctx) + resCtx.errorsMu.Lock() + defer resCtx.errorsMu.Unlock() + + if len(resCtx.errors) == 0 { + return nil + } + + errs := resCtx.errors + cpy := make(gqlerror.List, len(errs)) + for i := range errs { + errCpy := *errs[i] + cpy[i] = &errCpy + } + return cpy +} + +// RegisterExtension allows you to add a new extension into the graphql response +func RegisterExtension(ctx context.Context, key string, value interface{}) { + c := getResponseContext(ctx) + c.extensionsMu.Lock() + defer c.extensionsMu.Unlock() + + if c.extensions == nil { + c.extensions = make(map[string]interface{}) + } + + if _, ok := c.extensions[key]; ok { + panic(fmt.Errorf("extension already registered for key %s", key)) + } + + c.extensions[key] = value +} + +// GetExtensions returns any extensions registered in the current result context +func GetExtensions(ctx context.Context) map[string]interface{} { + ext := getResponseContext(ctx).extensions + if ext == nil { + return map[string]interface{}{} + } + + return ext +} + +func GetExtension(ctx context.Context, name string) interface{} { + ext := getResponseContext(ctx).extensions + if ext == nil { + return nil + } + + return ext[name] +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/errcode/codes.go b/vendor/github.com/99designs/gqlgen/graphql/errcode/codes.go new file mode 100644 index 000000000..774ab7a9e --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/errcode/codes.go @@ -0,0 +1,49 @@ +package errcode + +import ( + "github.com/vektah/gqlparser/v2/gqlerror" +) + +const ValidationFailed = "GRAPHQL_VALIDATION_FAILED" +const ParseFailed = "GRAPHQL_PARSE_FAILED" + +type ErrorKind int + +const ( + // issues with graphql (validation, parsing). 422s in http, GQL_ERROR in websocket + KindProtocol ErrorKind = iota + // user errors, 200s in http, GQL_DATA in websocket + KindUser +) + +var codeType = map[string]ErrorKind{ + ValidationFailed: KindProtocol, + ParseFailed: KindProtocol, +} + +// RegisterErrorType should be called by extensions that want to customize the http status codes for errors they return +func RegisterErrorType(code string, kind ErrorKind) { + codeType[code] = kind +} + +// Set the error code on a given graphql error extension +func Set(err *gqlerror.Error, value string) { + if err.Extensions == nil { + err.Extensions = map[string]interface{}{} + } + + err.Extensions["code"] = value +} + +// get the kind of the first non User error, defaults to User if no errors have a custom extension +func GetErrorKind(errs gqlerror.List) ErrorKind { + for _, err := range errs { + if code, ok := err.Extensions["code"].(string); ok { + if kind, ok := codeType[code]; ok && kind != KindUser { + return kind + } + } + } + + return KindUser +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/error.go b/vendor/github.com/99designs/gqlgen/graphql/error.go index af8b4ce40..201058a2f 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/error.go +++ b/vendor/github.com/99designs/gqlgen/graphql/error.go @@ -3,10 +3,10 @@ package graphql import ( "context" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" ) -type ErrorPresenterFunc func(context.Context, error) *gqlerror.Error +type ErrorPresenterFunc func(ctx context.Context, err error) *gqlerror.Error type ExtendedError interface { Extensions() map[string]interface{} @@ -15,7 +15,7 @@ type ExtendedError interface { func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error { if gqlerr, ok := err.(*gqlerror.Error); ok { if gqlerr.Path == nil { - gqlerr.Path = GetResolverContext(ctx).Path() + gqlerr.Path = GetFieldContext(ctx).Path() } return gqlerr } @@ -27,7 +27,7 @@ func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error { return &gqlerror.Error{ Message: err.Error(), - Path: GetResolverContext(ctx).Path(), + Path: GetFieldContext(ctx).Path(), Extensions: extensions, } } diff --git a/vendor/github.com/99designs/gqlgen/graphql/exec.go b/vendor/github.com/99designs/gqlgen/graphql/executable_schema.go similarity index 77% rename from vendor/github.com/99designs/gqlgen/graphql/exec.go rename to vendor/github.com/99designs/gqlgen/graphql/executable_schema.go index 3e00a4d57..dc53b6881 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/exec.go +++ b/vendor/github.com/99designs/gqlgen/graphql/executable_schema.go @@ -1,29 +1,29 @@ +//go:generate go run github.com/matryer/moq -out executable_schema_mock.go . ExecutableSchema + package graphql import ( "context" "fmt" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type ExecutableSchema interface { Schema() *ast.Schema Complexity(typeName, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) - Query(ctx context.Context, op *ast.OperationDefinition) *Response - Mutation(ctx context.Context, op *ast.OperationDefinition) *Response - Subscription(ctx context.Context, op *ast.OperationDefinition) func() *Response + Exec(ctx context.Context) ResponseHandler } // CollectFields returns the set of fields from an ast.SelectionSet where all collected fields satisfy at least one of the GraphQL types // passed through satisfies. Providing an empty or nil slice for satisfies will return collect all fields regardless of fragment // type conditions. -func CollectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies []string) []CollectedField { +func CollectFields(reqCtx *OperationContext, selSet ast.SelectionSet, satisfies []string) []CollectedField { return collectFields(reqCtx, selSet, satisfies, map[string]bool{}) } -func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies []string, visited map[string]bool) []CollectedField { +func collectFields(reqCtx *OperationContext, selSet ast.SelectionSet, satisfies []string, visited map[string]bool) []CollectedField { groupedFields := make([]CollectedField, 0, len(selSet)) for _, sel := range selSet { @@ -32,7 +32,7 @@ func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies [] if !shouldIncludeNode(sel.Directives, reqCtx.Variables) { continue } - f := getOrCreateAndAppendField(&groupedFields, sel.Alias, func() CollectedField { + f := getOrCreateAndAppendField(&groupedFields, sel.Alias, sel.ObjectDefinition, func() CollectedField { return CollectedField{Field: sel} }) @@ -45,7 +45,7 @@ func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies [] continue } for _, childField := range collectFields(reqCtx, sel.SelectionSet, satisfies, visited) { - f := getOrCreateAndAppendField(&groupedFields, childField.Name, func() CollectedField { return childField }) + f := getOrCreateAndAppendField(&groupedFields, childField.Name, childField.ObjectDefinition, func() CollectedField { return childField }) f.Selections = append(f.Selections, childField.Selections...) } @@ -70,7 +70,7 @@ func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies [] } for _, childField := range collectFields(reqCtx, fragment.SelectionSet, satisfies, visited) { - f := getOrCreateAndAppendField(&groupedFields, childField.Name, func() CollectedField { return childField }) + f := getOrCreateAndAppendField(&groupedFields, childField.Name, childField.ObjectDefinition, func() CollectedField { return childField }) f.Selections = append(f.Selections, childField.Selections...) } default: @@ -96,9 +96,9 @@ func instanceOf(val string, satisfies []string) bool { return false } -func getOrCreateAndAppendField(c *[]CollectedField, name string, creator func() CollectedField) *CollectedField { +func getOrCreateAndAppendField(c *[]CollectedField, name string, objectDefinition *ast.Definition, creator func() CollectedField) *CollectedField { for i, cf := range *c { - if cf.Alias == name { + if cf.Alias == name && (cf.ObjectDefinition == objectDefinition || (cf.ObjectDefinition != nil && objectDefinition != nil && cf.ObjectDefinition.Name == objectDefinition.Name)) { return &(*c)[i] } } diff --git a/vendor/github.com/99designs/gqlgen/graphql/executable_schema_mock.go b/vendor/github.com/99designs/gqlgen/graphql/executable_schema_mock.go new file mode 100644 index 000000000..0c021d3d0 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/executable_schema_mock.go @@ -0,0 +1,175 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package graphql + +import ( + "context" + "github.com/vektah/gqlparser/v2/ast" + "sync" +) + +var ( + lockExecutableSchemaMockComplexity sync.RWMutex + lockExecutableSchemaMockExec sync.RWMutex + lockExecutableSchemaMockSchema sync.RWMutex +) + +// Ensure, that ExecutableSchemaMock does implement ExecutableSchema. +// If this is not the case, regenerate this file with moq. +var _ ExecutableSchema = &ExecutableSchemaMock{} + +// ExecutableSchemaMock is a mock implementation of ExecutableSchema. +// +// func TestSomethingThatUsesExecutableSchema(t *testing.T) { +// +// // make and configure a mocked ExecutableSchema +// mockedExecutableSchema := &ExecutableSchemaMock{ +// ComplexityFunc: func(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) { +// panic("mock out the Complexity method") +// }, +// ExecFunc: func(ctx context.Context) ResponseHandler { +// panic("mock out the Exec method") +// }, +// SchemaFunc: func() *ast.Schema { +// panic("mock out the Schema method") +// }, +// } +// +// // use mockedExecutableSchema in code that requires ExecutableSchema +// // and then make assertions. +// +// } +type ExecutableSchemaMock struct { + // ComplexityFunc mocks the Complexity method. + ComplexityFunc func(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) + + // ExecFunc mocks the Exec method. + ExecFunc func(ctx context.Context) ResponseHandler + + // SchemaFunc mocks the Schema method. + SchemaFunc func() *ast.Schema + + // calls tracks calls to the methods. + calls struct { + // Complexity holds details about calls to the Complexity method. + Complexity []struct { + // TypeName is the typeName argument value. + TypeName string + // FieldName is the fieldName argument value. + FieldName string + // ChildComplexity is the childComplexity argument value. + ChildComplexity int + // Args is the args argument value. + Args map[string]interface{} + } + // Exec holds details about calls to the Exec method. + Exec []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // Schema holds details about calls to the Schema method. + Schema []struct { + } + } +} + +// Complexity calls ComplexityFunc. +func (mock *ExecutableSchemaMock) Complexity(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (int, bool) { + if mock.ComplexityFunc == nil { + panic("ExecutableSchemaMock.ComplexityFunc: method is nil but ExecutableSchema.Complexity was just called") + } + callInfo := struct { + TypeName string + FieldName string + ChildComplexity int + Args map[string]interface{} + }{ + TypeName: typeName, + FieldName: fieldName, + ChildComplexity: childComplexity, + Args: args, + } + lockExecutableSchemaMockComplexity.Lock() + mock.calls.Complexity = append(mock.calls.Complexity, callInfo) + lockExecutableSchemaMockComplexity.Unlock() + return mock.ComplexityFunc(typeName, fieldName, childComplexity, args) +} + +// ComplexityCalls gets all the calls that were made to Complexity. +// Check the length with: +// len(mockedExecutableSchema.ComplexityCalls()) +func (mock *ExecutableSchemaMock) ComplexityCalls() []struct { + TypeName string + FieldName string + ChildComplexity int + Args map[string]interface{} +} { + var calls []struct { + TypeName string + FieldName string + ChildComplexity int + Args map[string]interface{} + } + lockExecutableSchemaMockComplexity.RLock() + calls = mock.calls.Complexity + lockExecutableSchemaMockComplexity.RUnlock() + return calls +} + +// Exec calls ExecFunc. +func (mock *ExecutableSchemaMock) Exec(ctx context.Context) ResponseHandler { + if mock.ExecFunc == nil { + panic("ExecutableSchemaMock.ExecFunc: method is nil but ExecutableSchema.Exec was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + lockExecutableSchemaMockExec.Lock() + mock.calls.Exec = append(mock.calls.Exec, callInfo) + lockExecutableSchemaMockExec.Unlock() + return mock.ExecFunc(ctx) +} + +// ExecCalls gets all the calls that were made to Exec. +// Check the length with: +// len(mockedExecutableSchema.ExecCalls()) +func (mock *ExecutableSchemaMock) ExecCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + lockExecutableSchemaMockExec.RLock() + calls = mock.calls.Exec + lockExecutableSchemaMockExec.RUnlock() + return calls +} + +// Schema calls SchemaFunc. +func (mock *ExecutableSchemaMock) Schema() *ast.Schema { + if mock.SchemaFunc == nil { + panic("ExecutableSchemaMock.SchemaFunc: method is nil but ExecutableSchema.Schema was just called") + } + callInfo := struct { + }{} + lockExecutableSchemaMockSchema.Lock() + mock.calls.Schema = append(mock.calls.Schema, callInfo) + lockExecutableSchemaMockSchema.Unlock() + return mock.SchemaFunc() +} + +// SchemaCalls gets all the calls that were made to Schema. +// Check the length with: +// len(mockedExecutableSchema.SchemaCalls()) +func (mock *ExecutableSchemaMock) SchemaCalls() []struct { +} { + var calls []struct { + } + lockExecutableSchemaMockSchema.RLock() + calls = mock.calls.Schema + lockExecutableSchemaMockSchema.RUnlock() + return calls +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/executor/executor.go b/vendor/github.com/99designs/gqlgen/graphql/executor/executor.go new file mode 100644 index 000000000..b3163a4bd --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/executor/executor.go @@ -0,0 +1,191 @@ +package executor + +import ( + "context" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vektah/gqlparser/v2/parser" + "github.com/vektah/gqlparser/v2/validator" +) + +// Executor executes graphql queries against a schema. +type Executor struct { + es graphql.ExecutableSchema + extensions []graphql.HandlerExtension + ext extensions + + errorPresenter graphql.ErrorPresenterFunc + recoverFunc graphql.RecoverFunc + queryCache graphql.Cache +} + +var _ graphql.GraphExecutor = &Executor{} + +// New creates a new Executor with the given schema, and a default error and +// recovery callbacks, and no query cache or extensions. +func New(es graphql.ExecutableSchema) *Executor { + e := &Executor{ + es: es, + errorPresenter: graphql.DefaultErrorPresenter, + recoverFunc: graphql.DefaultRecover, + queryCache: graphql.NoCache{}, + ext: processExtensions(nil), + } + return e +} + +func (e *Executor) CreateOperationContext(ctx context.Context, params *graphql.RawParams) (*graphql.OperationContext, gqlerror.List) { + rc := &graphql.OperationContext{ + DisableIntrospection: true, + Recover: e.recoverFunc, + ResolverMiddleware: e.ext.fieldMiddleware, + Stats: graphql.Stats{ + Read: params.ReadTime, + OperationStart: graphql.GetStartTime(ctx), + }, + } + ctx = graphql.WithOperationContext(ctx, rc) + + for _, p := range e.ext.operationParameterMutators { + if err := p.MutateOperationParameters(ctx, params); err != nil { + return rc, gqlerror.List{err} + } + } + + rc.RawQuery = params.Query + rc.OperationName = params.OperationName + + var listErr gqlerror.List + rc.Doc, listErr = e.parseQuery(ctx, &rc.Stats, params.Query) + if len(listErr) != 0 { + return rc, listErr + } + + rc.Operation = rc.Doc.Operations.ForName(params.OperationName) + if rc.Operation == nil { + return rc, gqlerror.List{gqlerror.Errorf("operation %s not found", params.OperationName)} + } + + var err *gqlerror.Error + rc.Variables, err = validator.VariableValues(e.es.Schema(), rc.Operation, params.Variables) + if err != nil { + errcode.Set(err, errcode.ValidationFailed) + return rc, gqlerror.List{err} + } + rc.Stats.Validation.End = graphql.Now() + + for _, p := range e.ext.operationContextMutators { + if err := p.MutateOperationContext(ctx, rc); err != nil { + return rc, gqlerror.List{err} + } + } + + return rc, nil +} + +func (e *Executor) DispatchOperation(ctx context.Context, rc *graphql.OperationContext) (graphql.ResponseHandler, context.Context) { + ctx = graphql.WithOperationContext(ctx, rc) + + var innerCtx context.Context + res := e.ext.operationMiddleware(ctx, func(ctx context.Context) graphql.ResponseHandler { + innerCtx = ctx + + tmpResponseContext := graphql.WithResponseContext(ctx, e.errorPresenter, e.recoverFunc) + responses := e.es.Exec(tmpResponseContext) + if errs := graphql.GetErrors(tmpResponseContext); errs != nil { + return graphql.OneShot(&graphql.Response{Errors: errs}) + } + + return func(ctx context.Context) *graphql.Response { + ctx = graphql.WithResponseContext(ctx, e.errorPresenter, e.recoverFunc) + resp := e.ext.responseMiddleware(ctx, func(ctx context.Context) *graphql.Response { + resp := responses(ctx) + if resp == nil { + return nil + } + resp.Errors = append(resp.Errors, graphql.GetErrors(ctx)...) + resp.Extensions = graphql.GetExtensions(ctx) + return resp + }) + if resp == nil { + return nil + } + + return resp + } + }) + + return res, innerCtx +} + +func (e *Executor) DispatchError(ctx context.Context, list gqlerror.List) *graphql.Response { + ctx = graphql.WithResponseContext(ctx, e.errorPresenter, e.recoverFunc) + for _, gErr := range list { + graphql.AddError(ctx, gErr) + } + + resp := e.ext.responseMiddleware(ctx, func(ctx context.Context) *graphql.Response { + resp := &graphql.Response{ + Errors: list, + } + resp.Extensions = graphql.GetExtensions(ctx) + return resp + }) + + return resp +} + +func (e *Executor) PresentRecoveredError(ctx context.Context, err interface{}) *gqlerror.Error { + return e.errorPresenter(ctx, e.recoverFunc(ctx, err)) +} + +func (e *Executor) SetQueryCache(cache graphql.Cache) { + e.queryCache = cache +} + +func (e *Executor) SetErrorPresenter(f graphql.ErrorPresenterFunc) { + e.errorPresenter = f +} + +func (e *Executor) SetRecoverFunc(f graphql.RecoverFunc) { + e.recoverFunc = f +} + +// parseQuery decodes the incoming query and validates it, pulling from cache if present. +// +// NOTE: This should NOT look at variables, they will change per request. It should only parse and validate +// the raw query string. +func (e *Executor) parseQuery(ctx context.Context, stats *graphql.Stats, query string) (*ast.QueryDocument, gqlerror.List) { + stats.Parsing.Start = graphql.Now() + + if doc, ok := e.queryCache.Get(ctx, query); ok { + now := graphql.Now() + + stats.Parsing.End = now + stats.Validation.Start = now + return doc.(*ast.QueryDocument), nil + } + + doc, err := parser.ParseQuery(&ast.Source{Input: query}) + if err != nil { + errcode.Set(err, errcode.ParseFailed) + return nil, gqlerror.List{err} + } + stats.Parsing.End = graphql.Now() + + stats.Validation.Start = graphql.Now() + listErr := validator.Validate(e.es.Schema(), doc) + if len(listErr) != 0 { + for _, e := range listErr { + errcode.Set(e, errcode.ValidationFailed) + } + return nil, listErr + } + + e.queryCache.Add(ctx, query, doc) + + return doc, nil +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/executor/extensions.go b/vendor/github.com/99designs/gqlgen/graphql/executor/extensions.go new file mode 100644 index 000000000..30a48ce80 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/executor/extensions.go @@ -0,0 +1,159 @@ +package executor + +import ( + "context" + "fmt" + + "github.com/99designs/gqlgen/graphql" +) + +// Use adds the given extension to this Executor. +func (e *Executor) Use(extension graphql.HandlerExtension) { + if err := extension.Validate(e.es); err != nil { + panic(err) + } + + switch extension.(type) { + case graphql.OperationParameterMutator, + graphql.OperationContextMutator, + graphql.OperationInterceptor, + graphql.FieldInterceptor, + graphql.ResponseInterceptor: + e.extensions = append(e.extensions, extension) + e.ext = processExtensions(e.extensions) + + default: + panic(fmt.Errorf("cannot Use %T as a gqlgen handler extension because it does not implement any extension hooks", extension)) + } +} + +// AroundFields is a convenience method for creating an extension that only implements field middleware +func (e *Executor) AroundFields(f graphql.FieldMiddleware) { + e.Use(aroundFieldFunc(f)) +} + +// AroundOperations is a convenience method for creating an extension that only implements operation middleware +func (e *Executor) AroundOperations(f graphql.OperationMiddleware) { + e.Use(aroundOpFunc(f)) +} + +// AroundResponses is a convenience method for creating an extension that only implements response middleware +func (e *Executor) AroundResponses(f graphql.ResponseMiddleware) { + e.Use(aroundRespFunc(f)) +} + +type extensions struct { + operationMiddleware graphql.OperationMiddleware + responseMiddleware graphql.ResponseMiddleware + fieldMiddleware graphql.FieldMiddleware + operationParameterMutators []graphql.OperationParameterMutator + operationContextMutators []graphql.OperationContextMutator +} + +func processExtensions(exts []graphql.HandlerExtension) extensions { + e := extensions{ + operationMiddleware: func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + return next(ctx) + }, + responseMiddleware: func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + return next(ctx) + }, + fieldMiddleware: func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + return next(ctx) + }, + } + + // this loop goes backwards so the first extension is the outer most middleware and runs first. + for i := len(exts) - 1; i >= 0; i-- { + p := exts[i] + if p, ok := p.(graphql.OperationInterceptor); ok { + previous := e.operationMiddleware + e.operationMiddleware = func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + return p.InterceptOperation(ctx, func(ctx context.Context) graphql.ResponseHandler { + return previous(ctx, next) + }) + } + } + + if p, ok := p.(graphql.ResponseInterceptor); ok { + previous := e.responseMiddleware + e.responseMiddleware = func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + return p.InterceptResponse(ctx, func(ctx context.Context) *graphql.Response { + return previous(ctx, next) + }) + } + } + + if p, ok := p.(graphql.FieldInterceptor); ok { + previous := e.fieldMiddleware + e.fieldMiddleware = func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + return p.InterceptField(ctx, func(ctx context.Context) (res interface{}, err error) { + return previous(ctx, next) + }) + } + } + } + + for _, p := range exts { + if p, ok := p.(graphql.OperationParameterMutator); ok { + e.operationParameterMutators = append(e.operationParameterMutators, p) + } + + if p, ok := p.(graphql.OperationContextMutator); ok { + e.operationContextMutators = append(e.operationContextMutators, p) + } + } + + return e +} + +type aroundOpFunc func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler + +func (r aroundOpFunc) ExtensionName() string { + return "InlineOperationFunc" +} + +func (r aroundOpFunc) Validate(schema graphql.ExecutableSchema) error { + if r == nil { + return fmt.Errorf("OperationFunc can not be nil") + } + return nil +} + +func (r aroundOpFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + return r(ctx, next) +} + +type aroundRespFunc func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response + +func (r aroundRespFunc) ExtensionName() string { + return "InlineResponseFunc" +} + +func (r aroundRespFunc) Validate(schema graphql.ExecutableSchema) error { + if r == nil { + return fmt.Errorf("ResponseFunc can not be nil") + } + return nil +} + +func (r aroundRespFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + return r(ctx, next) +} + +type aroundFieldFunc func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) + +func (f aroundFieldFunc) ExtensionName() string { + return "InlineFieldFunc" +} + +func (f aroundFieldFunc) Validate(schema graphql.ExecutableSchema) error { + if f == nil { + return fmt.Errorf("FieldFunc can not be nil") + } + return nil +} + +func (f aroundFieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + return f(ctx, next) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler.go b/vendor/github.com/99designs/gqlgen/graphql/handler.go new file mode 100644 index 000000000..e74af2f03 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler.go @@ -0,0 +1,123 @@ +package graphql + +import ( + "context" + "net/http" + "strconv" + "strings" + + "github.com/vektah/gqlparser/v2/gqlerror" +) + +type ( + OperationMiddleware func(ctx context.Context, next OperationHandler) ResponseHandler + OperationHandler func(ctx context.Context) ResponseHandler + + ResponseHandler func(ctx context.Context) *Response + ResponseMiddleware func(ctx context.Context, next ResponseHandler) *Response + + Resolver func(ctx context.Context) (res interface{}, err error) + FieldMiddleware func(ctx context.Context, next Resolver) (res interface{}, err error) + + RawParams struct { + Query string `json:"query"` + OperationName string `json:"operationName"` + Variables map[string]interface{} `json:"variables"` + Extensions map[string]interface{} `json:"extensions"` + + ReadTime TraceTiming `json:"-"` + } + + GraphExecutor interface { + CreateOperationContext(ctx context.Context, params *RawParams) (*OperationContext, gqlerror.List) + DispatchOperation(ctx context.Context, rc *OperationContext) (ResponseHandler, context.Context) + DispatchError(ctx context.Context, list gqlerror.List) *Response + } + + // HandlerExtension adds functionality to the http handler. See the list of possible hook points below + // Its important to understand the lifecycle of a graphql request and the terminology we use in gqlgen + // before working with these + // + // +--- REQUEST POST /graphql --------------------------------------------+ + // | +- OPERATION query OpName { viewer { name } } -----------------------+ | + // | | RESPONSE { "data": { "viewer": { "name": "bob" } } } | | + // | +- OPERATION subscription OpName2 { chat { message } } --------------+ | + // | | RESPONSE { "data": { "chat": { "message": "hello" } } } | | + // | | RESPONSE { "data": { "chat": { "message": "byee" } } } | | + // | +--------------------------------------------------------------------+ | + // +------------------------------------------------------------------------+ + HandlerExtension interface { + // ExtensionName should be a CamelCase string version of the extension which may be shown in stats and logging. + ExtensionName() string + // Validate is called when adding an extension to the server, it allows validation against the servers schema. + Validate(schema ExecutableSchema) error + } + + // OperationParameterMutator is called before creating a request context. allows manipulating the raw query + // on the way in. + OperationParameterMutator interface { + MutateOperationParameters(ctx context.Context, request *RawParams) *gqlerror.Error + } + + // OperationContextMutator is called after creating the request context, but before executing the root resolver. + OperationContextMutator interface { + MutateOperationContext(ctx context.Context, rc *OperationContext) *gqlerror.Error + } + + // OperationInterceptor is called for each incoming query, for basic requests the writer will be invoked once, + // for subscriptions it will be invoked multiple times. + OperationInterceptor interface { + InterceptOperation(ctx context.Context, next OperationHandler) ResponseHandler + } + + // ResponseInterceptor is called around each graphql operation response. This can be called many times for a single + // operation the case of subscriptions. + ResponseInterceptor interface { + InterceptResponse(ctx context.Context, next ResponseHandler) *Response + } + + // FieldInterceptor called around each field + FieldInterceptor interface { + InterceptField(ctx context.Context, next Resolver) (res interface{}, err error) + } + + // Transport provides support for different wire level encodings of graphql requests, eg Form, Get, Post, Websocket + Transport interface { + Supports(r *http.Request) bool + Do(w http.ResponseWriter, r *http.Request, exec GraphExecutor) + } +) + +type Status int + +func (p *RawParams) AddUpload(upload Upload, key, path string) *gqlerror.Error { + if !strings.HasPrefix(path, "variables.") { + return gqlerror.Errorf("invalid operations paths for key %s", key) + } + + var ptr interface{} = p.Variables + parts := strings.Split(path, ".") + + // skip the first part (variables) because we started there + for i, p := range parts[1:] { + last := i == len(parts)-2 + if ptr == nil { + return gqlerror.Errorf("path is missing \"variables.\" prefix, key: %s, path: %s", key, path) + } + if index, parseNbrErr := strconv.Atoi(p); parseNbrErr == nil { + if last { + ptr.([]interface{})[index] = upload + } else { + ptr = ptr.([]interface{})[index] + } + } else { + if last { + ptr.(map[string]interface{})[p] = upload + } else { + ptr = ptr.(map[string]interface{})[p] + } + } + } + + return nil +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/extension/apq.go b/vendor/github.com/99designs/gqlgen/graphql/handler/extension/apq.go new file mode 100644 index 000000000..83f4c1bfc --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/extension/apq.go @@ -0,0 +1,112 @@ +package extension + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "fmt" + + "github.com/99designs/gqlgen/graphql/errcode" + + "github.com/vektah/gqlparser/v2/gqlerror" + + "github.com/99designs/gqlgen/graphql" + "github.com/mitchellh/mapstructure" +) + +const errPersistedQueryNotFound = "PersistedQueryNotFound" +const errPersistedQueryNotFoundCode = "PERSISTED_QUERY_NOT_FOUND" + +// AutomaticPersistedQuery saves client upload by optimistically sending only the hashes of queries, if the server +// does not yet know what the query is for the hash it will respond telling the client to send the query along with the +// hash in the next request. +// see https://github.com/apollographql/apollo-link-persisted-queries +type AutomaticPersistedQuery struct { + Cache graphql.Cache +} + +type ApqStats struct { + // The hash of the incoming query + Hash string + + // SentQuery is true if the incoming request sent the full query + SentQuery bool +} + +const apqExtension = "APQ" + +var _ interface { + graphql.OperationParameterMutator + graphql.HandlerExtension +} = AutomaticPersistedQuery{} + +func (a AutomaticPersistedQuery) ExtensionName() string { + return "AutomaticPersistedQuery" +} + +func (a AutomaticPersistedQuery) Validate(schema graphql.ExecutableSchema) error { + if a.Cache == nil { + return fmt.Errorf("AutomaticPersistedQuery.Cache can not be nil") + } + return nil +} + +func (a AutomaticPersistedQuery) MutateOperationParameters(ctx context.Context, rawParams *graphql.RawParams) *gqlerror.Error { + if rawParams.Extensions["persistedQuery"] == nil { + return nil + } + + var extension struct { + Sha256 string `mapstructure:"sha256Hash"` + Version int64 `mapstructure:"version"` + } + + if err := mapstructure.Decode(rawParams.Extensions["persistedQuery"], &extension); err != nil { + return gqlerror.Errorf("invalid APQ extension data") + } + + if extension.Version != 1 { + return gqlerror.Errorf("unsupported APQ version") + } + + fullQuery := false + if rawParams.Query == "" { + // client sent optimistic query hash without query string, get it from the cache + query, ok := a.Cache.Get(ctx, extension.Sha256) + if !ok { + err := gqlerror.Errorf(errPersistedQueryNotFound) + errcode.Set(err, errPersistedQueryNotFoundCode) + return err + } + rawParams.Query = query.(string) + } else { + // client sent optimistic query hash with query string, verify and store it + if computeQueryHash(rawParams.Query) != extension.Sha256 { + return gqlerror.Errorf("provided APQ hash does not match query") + } + a.Cache.Add(ctx, extension.Sha256, rawParams.Query) + fullQuery = true + } + + graphql.GetOperationContext(ctx).Stats.SetExtension(apqExtension, &ApqStats{ + Hash: extension.Sha256, + SentQuery: fullQuery, + }) + + return nil +} + +func GetApqStats(ctx context.Context) *ApqStats { + rc := graphql.GetOperationContext(ctx) + if rc == nil { + return nil + } + + s, _ := rc.Stats.GetExtension(apqExtension).(*ApqStats) + return s +} + +func computeQueryHash(query string) string { + b := sha256.Sum256([]byte(query)) + return hex.EncodeToString(b[:]) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/extension/complexity.go b/vendor/github.com/99designs/gqlgen/graphql/handler/extension/complexity.go new file mode 100644 index 000000000..2d853802b --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/extension/complexity.go @@ -0,0 +1,88 @@ +package extension + +import ( + "context" + "fmt" + + "github.com/99designs/gqlgen/complexity" + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +const errComplexityLimit = "COMPLEXITY_LIMIT_EXCEEDED" + +// ComplexityLimit allows you to define a limit on query complexity +// +// If a query is submitted that exceeds the limit, a 422 status code will be returned. +type ComplexityLimit struct { + Func func(ctx context.Context, rc *graphql.OperationContext) int + + es graphql.ExecutableSchema +} + +var _ interface { + graphql.OperationContextMutator + graphql.HandlerExtension +} = &ComplexityLimit{} + +const complexityExtension = "ComplexityLimit" + +type ComplexityStats struct { + // The calculated complexity for this request + Complexity int + + // The complexity limit for this request returned by the extension func + ComplexityLimit int +} + +// FixedComplexityLimit sets a complexity limit that does not change +func FixedComplexityLimit(limit int) *ComplexityLimit { + return &ComplexityLimit{ + Func: func(ctx context.Context, rc *graphql.OperationContext) int { + return limit + }, + } +} + +func (c ComplexityLimit) ExtensionName() string { + return complexityExtension +} + +func (c *ComplexityLimit) Validate(schema graphql.ExecutableSchema) error { + if c.Func == nil { + return fmt.Errorf("ComplexityLimit func can not be nil") + } + c.es = schema + return nil +} + +func (c ComplexityLimit) MutateOperationContext(ctx context.Context, rc *graphql.OperationContext) *gqlerror.Error { + op := rc.Doc.Operations.ForName(rc.OperationName) + complexity := complexity.Calculate(c.es, op, rc.Variables) + + limit := c.Func(ctx, rc) + + rc.Stats.SetExtension(complexityExtension, &ComplexityStats{ + Complexity: complexity, + ComplexityLimit: limit, + }) + + if complexity > limit { + err := gqlerror.Errorf("operation has complexity %d, which exceeds the limit of %d", complexity, limit) + errcode.Set(err, errComplexityLimit) + return err + } + + return nil +} + +func GetComplexityStats(ctx context.Context) *ComplexityStats { + rc := graphql.GetOperationContext(ctx) + if rc == nil { + return nil + } + + s, _ := rc.Stats.GetExtension(complexityExtension).(*ComplexityStats) + return s +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/extension/introspection.go b/vendor/github.com/99designs/gqlgen/graphql/handler/extension/introspection.go new file mode 100644 index 000000000..acc5db2fb --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/extension/introspection.go @@ -0,0 +1,29 @@ +package extension + +import ( + "context" + + "github.com/99designs/gqlgen/graphql" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +// EnableIntrospection enables clients to reflect all of the types available on the graph. +type Introspection struct{} + +var _ interface { + graphql.OperationContextMutator + graphql.HandlerExtension +} = Introspection{} + +func (c Introspection) ExtensionName() string { + return "Introspection" +} + +func (c Introspection) Validate(schema graphql.ExecutableSchema) error { + return nil +} + +func (c Introspection) MutateOperationContext(ctx context.Context, rc *graphql.OperationContext) *gqlerror.Error { + rc.DisableIntrospection = false + return nil +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/lru/lru.go b/vendor/github.com/99designs/gqlgen/graphql/handler/lru/lru.go new file mode 100644 index 000000000..e2b1561ac --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/lru/lru.go @@ -0,0 +1,32 @@ +package lru + +import ( + "context" + + "github.com/99designs/gqlgen/graphql" + lru "github.com/hashicorp/golang-lru" +) + +type LRU struct { + lru *lru.Cache +} + +var _ graphql.Cache = &LRU{} + +func New(size int) *LRU { + cache, err := lru.New(size) + if err != nil { + // An error is only returned for non-positive cache size + // and we already checked for that. + panic("unexpected error creating cache: " + err.Error()) + } + return &LRU{cache} +} + +func (l LRU) Get(ctx context.Context, key string) (value interface{}, ok bool) { + return l.lru.Get(key) +} + +func (l LRU) Add(ctx context.Context, key string, value interface{}) { + l.lru.Add(key, value) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/server.go b/vendor/github.com/99designs/gqlgen/graphql/handler/server.go new file mode 100644 index 000000000..640b2781c --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/server.go @@ -0,0 +1,180 @@ +package handler + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/executor" + "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/lru" + "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +type ( + Server struct { + transports []graphql.Transport + exec *executor.Executor + } +) + +func New(es graphql.ExecutableSchema) *Server { + return &Server{ + exec: executor.New(es), + } +} + +func NewDefaultServer(es graphql.ExecutableSchema) *Server { + srv := New(es) + + srv.AddTransport(transport.Websocket{ + KeepAlivePingInterval: 10 * time.Second, + }) + srv.AddTransport(transport.Options{}) + srv.AddTransport(transport.GET{}) + srv.AddTransport(transport.POST{}) + srv.AddTransport(transport.MultipartForm{}) + + srv.SetQueryCache(lru.New(1000)) + + srv.Use(extension.Introspection{}) + srv.Use(extension.AutomaticPersistedQuery{ + Cache: lru.New(100), + }) + + return srv +} + +func (s *Server) AddTransport(transport graphql.Transport) { + s.transports = append(s.transports, transport) +} + +func (s *Server) SetErrorPresenter(f graphql.ErrorPresenterFunc) { + s.exec.SetErrorPresenter(f) +} + +func (s *Server) SetRecoverFunc(f graphql.RecoverFunc) { + s.exec.SetRecoverFunc(f) +} + +func (s *Server) SetQueryCache(cache graphql.Cache) { + s.exec.SetQueryCache(cache) +} + +func (s *Server) Use(extension graphql.HandlerExtension) { + s.exec.Use(extension) +} + +// AroundFields is a convenience method for creating an extension that only implements field middleware +func (s *Server) AroundFields(f graphql.FieldMiddleware) { + s.exec.AroundFields(f) +} + +// AroundOperations is a convenience method for creating an extension that only implements operation middleware +func (s *Server) AroundOperations(f graphql.OperationMiddleware) { + s.exec.AroundOperations(f) +} + +// AroundResponses is a convenience method for creating an extension that only implements response middleware +func (s *Server) AroundResponses(f graphql.ResponseMiddleware) { + s.exec.AroundResponses(f) +} + +func (s *Server) getTransport(r *http.Request) graphql.Transport { + for _, t := range s.transports { + if t.Supports(r) { + return t + } + } + return nil +} + +func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + if err := recover(); err != nil { + err := s.exec.PresentRecoveredError(r.Context(), err) + resp := &graphql.Response{Errors: []*gqlerror.Error{err}} + b, _ := json.Marshal(resp) + w.WriteHeader(http.StatusUnprocessableEntity) + w.Write(b) + } + }() + + r = r.WithContext(graphql.StartOperationTrace(r.Context())) + + transport := s.getTransport(r) + if transport == nil { + sendErrorf(w, http.StatusBadRequest, "transport not supported") + return + } + + transport.Do(w, r, s.exec) +} + +func sendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) { + w.WriteHeader(code) + b, err := json.Marshal(&graphql.Response{Errors: errors}) + if err != nil { + panic(err) + } + w.Write(b) +} + +func sendErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) { + sendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)}) +} + +type OperationFunc func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler + +func (r OperationFunc) ExtensionName() string { + return "InlineOperationFunc" +} + +func (r OperationFunc) Validate(schema graphql.ExecutableSchema) error { + if r == nil { + return fmt.Errorf("OperationFunc can not be nil") + } + return nil +} + +func (r OperationFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { + return r(ctx, next) +} + +type ResponseFunc func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response + +func (r ResponseFunc) ExtensionName() string { + return "InlineResponseFunc" +} + +func (r ResponseFunc) Validate(schema graphql.ExecutableSchema) error { + if r == nil { + return fmt.Errorf("ResponseFunc can not be nil") + } + return nil +} + +func (r ResponseFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + return r(ctx, next) +} + +type FieldFunc func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) + +func (f FieldFunc) ExtensionName() string { + return "InlineFieldFunc" +} + +func (f FieldFunc) Validate(schema graphql.ExecutableSchema) error { + if f == nil { + return fmt.Errorf("FieldFunc can not be nil") + } + return nil +} + +func (f FieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { + return f(ctx, next) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/error.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/error.go new file mode 100644 index 000000000..b1aeaf144 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/error.go @@ -0,0 +1,26 @@ +package transport + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/99designs/gqlgen/graphql" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +// SendError sends a best effort error to a raw response writer. It assumes the client can understand the standard +// json error response +func SendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) { + w.WriteHeader(code) + b, err := json.Marshal(&graphql.Response{Errors: errors}) + if err != nil { + panic(err) + } + w.Write(b) +} + +// SendErrorf wraps SendError to add formatted messages +func SendErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) { + SendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)}) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_form.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_form.go new file mode 100644 index 000000000..4afc154bd --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_form.go @@ -0,0 +1,208 @@ +package transport + +import ( + "encoding/json" + "io" + "io/ioutil" + "mime" + "net/http" + "os" + "strings" + + "github.com/99designs/gqlgen/graphql" +) + +// MultipartForm the Multipart request spec https://github.com/jaydenseric/graphql-multipart-request-spec +type MultipartForm struct { + // MaxUploadSize sets the maximum number of bytes used to parse a request body + // as multipart/form-data. + MaxUploadSize int64 + + // MaxMemory defines the maximum number of bytes used to parse a request body + // as multipart/form-data in memory, with the remainder stored on disk in + // temporary files. + MaxMemory int64 +} + +var _ graphql.Transport = MultipartForm{} + +func (f MultipartForm) Supports(r *http.Request) bool { + if r.Header.Get("Upgrade") != "" { + return false + } + + mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err != nil { + return false + } + + return r.Method == "POST" && mediaType == "multipart/form-data" +} + +func (f MultipartForm) maxUploadSize() int64 { + if f.MaxUploadSize == 0 { + return 32 << 20 + } + return f.MaxUploadSize +} + +func (f MultipartForm) maxMemory() int64 { + if f.MaxMemory == 0 { + return 32 << 20 + } + return f.MaxMemory +} + +func (f MultipartForm) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { + w.Header().Set("Content-Type", "application/json") + + start := graphql.Now() + + var err error + if r.ContentLength > f.maxUploadSize() { + writeJsonError(w, "failed to parse multipart form, request body too large") + return + } + r.Body = http.MaxBytesReader(w, r.Body, f.maxUploadSize()) + if err = r.ParseMultipartForm(f.maxMemory()); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + if strings.Contains(err.Error(), "request body too large") { + writeJsonError(w, "failed to parse multipart form, request body too large") + return + } + writeJsonError(w, "failed to parse multipart form") + return + } + defer r.Body.Close() + + var params graphql.RawParams + + if err = jsonDecode(strings.NewReader(r.Form.Get("operations")), ¶ms); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonError(w, "operations form field could not be decoded") + return + } + + var uploadsMap = map[string][]string{} + if err = json.Unmarshal([]byte(r.Form.Get("map")), &uploadsMap); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonError(w, "map form field could not be decoded") + return + } + + var upload graphql.Upload + for key, paths := range uploadsMap { + if len(paths) == 0 { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonErrorf(w, "invalid empty operations paths list for key %s", key) + return + } + file, header, err := r.FormFile(key) + if err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonErrorf(w, "failed to get key %s from form", key) + return + } + defer file.Close() + + if len(paths) == 1 { + upload = graphql.Upload{ + File: file, + Size: header.Size, + Filename: header.Filename, + ContentType: header.Header.Get("Content-Type"), + } + + if err := params.AddUpload(upload, key, paths[0]); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonGraphqlError(w, err) + return + } + } else { + if r.ContentLength < f.maxMemory() { + fileBytes, err := ioutil.ReadAll(file) + if err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonErrorf(w, "failed to read file for key %s", key) + return + } + for _, path := range paths { + upload = graphql.Upload{ + File: &bytesReader{s: &fileBytes, i: 0, prevRune: -1}, + Size: header.Size, + Filename: header.Filename, + ContentType: header.Header.Get("Content-Type"), + } + + if err := params.AddUpload(upload, key, path); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonGraphqlError(w, err) + return + } + } + } else { + tmpFile, err := ioutil.TempFile(os.TempDir(), "gqlgen-") + if err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonErrorf(w, "failed to create temp file for key %s", key) + return + } + tmpName := tmpFile.Name() + defer func() { + _ = os.Remove(tmpName) + }() + _, err = io.Copy(tmpFile, file) + if err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + if err := tmpFile.Close(); err != nil { + writeJsonErrorf(w, "failed to copy to temp file and close temp file for key %s", key) + return + } + writeJsonErrorf(w, "failed to copy to temp file for key %s", key) + return + } + if err := tmpFile.Close(); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonErrorf(w, "failed to close temp file for key %s", key) + return + } + for _, path := range paths { + pathTmpFile, err := os.Open(tmpName) + if err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonErrorf(w, "failed to open temp file for key %s", key) + return + } + defer pathTmpFile.Close() + upload = graphql.Upload{ + File: pathTmpFile, + Size: header.Size, + Filename: header.Filename, + ContentType: header.Header.Get("Content-Type"), + } + + if err := params.AddUpload(upload, key, path); err != nil { + w.WriteHeader(http.StatusUnprocessableEntity) + writeJsonGraphqlError(w, err) + return + } + } + } + } + } + + params.ReadTime = graphql.TraceTiming{ + Start: start, + End: graphql.Now(), + } + + rc, gerr := exec.CreateOperationContext(r.Context(), ¶ms) + if gerr != nil { + resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), gerr) + w.WriteHeader(statusFor(gerr)) + writeJson(w, resp) + return + } + responses, ctx := exec.DispatchOperation(r.Context(), rc) + writeJson(w, responses(ctx)) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_get.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_get.go new file mode 100644 index 000000000..d97c89c63 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_get.go @@ -0,0 +1,87 @@ +package transport + +import ( + "encoding/json" + "io" + "net/http" + "strings" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +// GET implements the GET side of the default HTTP transport +// defined in https://github.com/APIs-guru/graphql-over-http#get +type GET struct{} + +var _ graphql.Transport = GET{} + +func (h GET) Supports(r *http.Request) bool { + if r.Header.Get("Upgrade") != "" { + return false + } + + return r.Method == "GET" +} + +func (h GET) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { + w.Header().Set("Content-Type", "application/json") + + raw := &graphql.RawParams{ + Query: r.URL.Query().Get("query"), + OperationName: r.URL.Query().Get("operationName"), + } + raw.ReadTime.Start = graphql.Now() + + if variables := r.URL.Query().Get("variables"); variables != "" { + if err := jsonDecode(strings.NewReader(variables), &raw.Variables); err != nil { + w.WriteHeader(http.StatusBadRequest) + writeJsonError(w, "variables could not be decoded") + return + } + } + + if extensions := r.URL.Query().Get("extensions"); extensions != "" { + if err := jsonDecode(strings.NewReader(extensions), &raw.Extensions); err != nil { + w.WriteHeader(http.StatusBadRequest) + writeJsonError(w, "extensions could not be decoded") + return + } + } + + raw.ReadTime.End = graphql.Now() + + rc, err := exec.CreateOperationContext(r.Context(), raw) + if err != nil { + w.WriteHeader(statusFor(err)) + resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), err) + writeJson(w, resp) + return + } + op := rc.Doc.Operations.ForName(rc.OperationName) + if op.Operation != ast.Query { + w.WriteHeader(http.StatusNotAcceptable) + writeJsonError(w, "GET requests only allow query operations") + return + } + + responses, ctx := exec.DispatchOperation(r.Context(), rc) + writeJson(w, responses(ctx)) +} + +func jsonDecode(r io.Reader, val interface{}) error { + dec := json.NewDecoder(r) + dec.UseNumber() + return dec.Decode(val) +} + +func statusFor(errs gqlerror.List) int { + switch errcode.GetErrorKind(errs) { + case errcode.KindProtocol: + return http.StatusUnprocessableEntity + default: + return http.StatusOK + } +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go new file mode 100644 index 000000000..70d971ac8 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go @@ -0,0 +1,54 @@ +package transport + +import ( + "mime" + "net/http" + + "github.com/99designs/gqlgen/graphql" +) + +// POST implements the POST side of the default HTTP transport +// defined in https://github.com/APIs-guru/graphql-over-http#post +type POST struct{} + +var _ graphql.Transport = POST{} + +func (h POST) Supports(r *http.Request) bool { + if r.Header.Get("Upgrade") != "" { + return false + } + + mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err != nil { + return false + } + + return r.Method == "POST" && mediaType == "application/json" +} + +func (h POST) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { + w.Header().Set("Content-Type", "application/json") + + var params *graphql.RawParams + start := graphql.Now() + if err := jsonDecode(r.Body, ¶ms); err != nil { + w.WriteHeader(http.StatusBadRequest) + writeJsonErrorf(w, "json body could not be decoded: "+err.Error()) + return + } + params.ReadTime = graphql.TraceTiming{ + Start: start, + End: graphql.Now(), + } + + rc, err := exec.CreateOperationContext(r.Context(), params) + if err != nil { + w.WriteHeader(statusFor(err)) + resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), err) + writeJson(w, resp) + return + } + ctx := graphql.WithOperationContext(r.Context(), rc) + responses, ctx := exec.DispatchOperation(ctx, rc) + writeJson(w, responses(ctx)) +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/options.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/options.go new file mode 100644 index 000000000..674a00c7f --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/options.go @@ -0,0 +1,26 @@ +package transport + +import ( + "net/http" + + "github.com/99designs/gqlgen/graphql" +) + +// Options responds to http OPTIONS and HEAD requests +type Options struct{} + +var _ graphql.Transport = Options{} + +func (o Options) Supports(r *http.Request) bool { + return r.Method == "HEAD" || r.Method == "OPTIONS" +} + +func (o Options) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { + switch r.Method { + case http.MethodOptions: + w.WriteHeader(http.StatusOK) + w.Header().Set("Allow", "OPTIONS, GET, POST") + case http.MethodHead: + w.WriteHeader(http.StatusMethodNotAllowed) + } +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/reader.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/reader.go new file mode 100644 index 000000000..d3261e283 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/reader.go @@ -0,0 +1,25 @@ +package transport + +import ( + "errors" + "io" +) + +type bytesReader struct { + s *[]byte + i int64 // current reading index + prevRune int // index of previous rune; or < 0 +} + +func (r *bytesReader) Read(b []byte) (n int, err error) { + if r.s == nil { + return 0, errors.New("byte slice pointer is nil") + } + if r.i >= int64(len(*r.s)) { + return 0, io.EOF + } + r.prevRune = -1 + n = copy(b, (*r.s)[r.i:]) + r.i += int64(n) + return +} diff --git a/vendor/github.com/99designs/gqlgen/graphql/handler/transport/util.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/util.go new file mode 100644 index 000000000..ce845c196 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/util.go @@ -0,0 +1,30 @@ +package transport + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/99designs/gqlgen/graphql" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +func writeJson(w io.Writer, response *graphql.Response) { + b, err := json.Marshal(response) + if err != nil { + panic(err) + } + w.Write(b) +} + +func writeJsonError(w io.Writer, msg string) { + writeJson(w, &graphql.Response{Errors: gqlerror.List{{Message: msg}}}) +} + +func writeJsonErrorf(w io.Writer, format string, args ...interface{}) { + writeJson(w, &graphql.Response{Errors: gqlerror.List{{Message: fmt.Sprintf(format, args...)}}}) +} + +func writeJsonGraphqlError(w io.Writer, err ...*gqlerror.Error) { + writeJson(w, &graphql.Response{Errors: err}) +} diff --git a/vendor/github.com/99designs/gqlgen/handler/websocket.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket.go similarity index 56% rename from vendor/github.com/99designs/gqlgen/handler/websocket.go rename to vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket.go index 58f38e5d4..3089a8779 100644 --- a/vendor/github.com/99designs/gqlgen/handler/websocket.go +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket.go @@ -1,4 +1,4 @@ -package handler +package transport import ( "bytes" @@ -11,12 +11,9 @@ import ( "time" "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" "github.com/gorilla/websocket" - "github.com/hashicorp/golang-lru" - "github.com/vektah/gqlparser" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/gqlerror" ) const ( @@ -32,42 +29,53 @@ const ( connectionKeepAliveMsg = "ka" // Server -> Client ) -type operationMessage struct { - Payload json.RawMessage `json:"payload,omitempty"` - ID string `json:"id,omitempty"` - Type string `json:"type"` +type ( + Websocket struct { + Upgrader websocket.Upgrader + InitFunc WebsocketInitFunc + KeepAlivePingInterval time.Duration + } + wsConnection struct { + Websocket + ctx context.Context + conn *websocket.Conn + active map[string]context.CancelFunc + mu sync.Mutex + keepAliveTicker *time.Ticker + exec graphql.GraphExecutor + + initPayload InitPayload + } + operationMessage struct { + Payload json.RawMessage `json:"payload,omitempty"` + ID string `json:"id,omitempty"` + Type string `json:"type"` + } + WebsocketInitFunc func(ctx context.Context, initPayload InitPayload) (context.Context, error) +) + +var _ graphql.Transport = Websocket{} + +func (t Websocket) Supports(r *http.Request) bool { + return r.Header.Get("Upgrade") != "" } -type wsConnection struct { - ctx context.Context - conn *websocket.Conn - exec graphql.ExecutableSchema - active map[string]context.CancelFunc - mu sync.Mutex - cfg *Config - cache *lru.Cache - keepAliveTicker *time.Ticker - - initPayload InitPayload -} - -func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Request, cfg *Config, cache *lru.Cache) { - ws, err := cfg.upgrader.Upgrade(w, r, http.Header{ +func (t Websocket) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) { + ws, err := t.Upgrader.Upgrade(w, r, http.Header{ "Sec-Websocket-Protocol": []string{"graphql-ws"}, }) if err != nil { log.Printf("unable to upgrade %T to websocket %s: ", w, err.Error()) - sendErrorf(w, http.StatusBadRequest, "unable to upgrade") + SendErrorf(w, http.StatusBadRequest, "unable to upgrade") return } conn := wsConnection{ - active: map[string]context.CancelFunc{}, - exec: exec, - conn: ws, - ctx: r.Context(), - cfg: cfg, - cache: cache, + active: map[string]context.CancelFunc{}, + conn: ws, + ctx: r.Context(), + exec: exec, + Websocket: t, } if !conn.init() { @@ -94,7 +102,18 @@ func (c *wsConnection) init() bool { } } + if c.InitFunc != nil { + ctx, err := c.InitFunc(c.ctx, c.initPayload) + if err != nil { + c.sendConnectionError(err.Error()) + c.close(websocket.CloseNormalClosure, "terminated") + return false + } + c.ctx = ctx + } + c.write(&operationMessage{Type: connectionAckMsg}) + c.write(&operationMessage{Type: connectionKeepAliveMsg}) case connectionTerminateMsg: c.close(websocket.CloseNormalClosure, "terminated") return false @@ -117,18 +136,22 @@ func (c *wsConnection) run() { // We create a cancellation that will shutdown the keep-alive when we leave // this function. ctx, cancel := context.WithCancel(c.ctx) - defer cancel() + defer func() { + cancel() + c.close(websocket.CloseAbnormalClosure, "unexpected closure") + }() // Create a timer that will fire every interval to keep the connection alive. - if c.cfg.connectionKeepAlivePingInterval != 0 { + if c.KeepAlivePingInterval != 0 { c.mu.Lock() - c.keepAliveTicker = time.NewTicker(c.cfg.connectionKeepAlivePingInterval) + c.keepAliveTicker = time.NewTicker(c.KeepAlivePingInterval) c.mu.Unlock() go c.keepAlive(ctx) } for { + start := graphql.Now() message := c.readOp() if message == nil { return @@ -136,19 +159,14 @@ func (c *wsConnection) run() { switch message.Type { case startMsg: - if !c.subscribe(message) { - return - } + c.subscribe(start, message) case stopMsg: c.mu.Lock() closer := c.active[message.ID] c.mu.Unlock() - if closer == nil { - c.sendError(message.ID, gqlerror.Errorf("%s is not running, cannot stop", message.ID)) - continue + if closer != nil { + closer() } - - closer() case connectionTerminateMsg: c.close(websocket.CloseNormalClosure, "terminated") return @@ -172,108 +190,90 @@ func (c *wsConnection) keepAlive(ctx context.Context) { } } -func (c *wsConnection) subscribe(message *operationMessage) bool { - var reqParams params - if err := jsonDecode(bytes.NewReader(message.Payload), &reqParams); err != nil { - c.sendConnectionError("invalid json") - return false +func (c *wsConnection) subscribe(start time.Time, message *operationMessage) { + ctx := graphql.StartOperationTrace(c.ctx) + var params *graphql.RawParams + if err := jsonDecode(bytes.NewReader(message.Payload), ¶ms); err != nil { + c.sendError(message.ID, &gqlerror.Error{Message: "invalid json"}) + c.complete(message.ID) + return } - var ( - doc *ast.QueryDocument - cacheHit bool - ) - if c.cache != nil { - val, ok := c.cache.Get(reqParams.Query) - if ok { - doc = val.(*ast.QueryDocument) - cacheHit = true - } - } - if !cacheHit { - var qErr gqlerror.List - doc, qErr = gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query) - if qErr != nil { - c.sendError(message.ID, qErr...) - return true - } - if c.cache != nil { - c.cache.Add(reqParams.Query, doc) - } + params.ReadTime = graphql.TraceTiming{ + Start: start, + End: graphql.Now(), } - op := doc.Operations.ForName(reqParams.OperationName) - if op == nil { - c.sendError(message.ID, gqlerror.Errorf("operation %s not found", reqParams.OperationName)) - return true - } - - vars, err := validator.VariableValues(c.exec.Schema(), op, reqParams.Variables) + rc, err := c.exec.CreateOperationContext(ctx, params) if err != nil { - c.sendError(message.ID, err) - return true + resp := c.exec.DispatchError(graphql.WithOperationContext(ctx, rc), err) + switch errcode.GetErrorKind(err) { + case errcode.KindProtocol: + c.sendError(message.ID, resp.Errors...) + default: + c.sendResponse(message.ID, &graphql.Response{Errors: err}) + } + + c.complete(message.ID) + return } - reqCtx := c.cfg.newRequestContext(c.exec, doc, op, reqParams.Query, vars) - ctx := graphql.WithRequestContext(c.ctx, reqCtx) + + ctx = graphql.WithOperationContext(ctx, rc) if c.initPayload != nil { ctx = withInitPayload(ctx, c.initPayload) } - if op.Operation != ast.Subscription { - var result *graphql.Response - if op.Operation == ast.Query { - result = c.exec.Query(ctx, op) - } else { - result = c.exec.Mutation(ctx, op) - } - - c.sendData(message.ID, result) - c.write(&operationMessage{ID: message.ID, Type: completeMsg}) - return true - } - ctx, cancel := context.WithCancel(ctx) c.mu.Lock() c.active[message.ID] = cancel c.mu.Unlock() + go func() { defer func() { if r := recover(); r != nil { - userErr := reqCtx.Recover(ctx, r) + userErr := rc.Recover(ctx, r) c.sendError(message.ID, &gqlerror.Error{Message: userErr.Error()}) } }() - next := c.exec.Subscription(ctx, op) - for result := next(); result != nil; result = next() { - c.sendData(message.ID, result) - } + responses, ctx := c.exec.DispatchOperation(ctx, rc) + for { + response := responses(ctx) + if response == nil { + break + } - c.write(&operationMessage{ID: message.ID, Type: completeMsg}) + c.sendResponse(message.ID, response) + } + c.complete(message.ID) c.mu.Lock() delete(c.active, message.ID) c.mu.Unlock() cancel() }() - - return true } -func (c *wsConnection) sendData(id string, response *graphql.Response) { +func (c *wsConnection) sendResponse(id string, response *graphql.Response) { b, err := json.Marshal(response) if err != nil { - c.sendError(id, gqlerror.Errorf("unable to encode json response: %s", err.Error())) - return + panic(err) } + c.write(&operationMessage{ + Payload: b, + ID: id, + Type: dataMsg, + }) +} - c.write(&operationMessage{Type: dataMsg, ID: id, Payload: b}) +func (c *wsConnection) complete(id string) { + c.write(&operationMessage{ID: id, Type: completeMsg}) } func (c *wsConnection) sendError(id string, errors ...*gqlerror.Error) { - var errs []error - for _, err := range errors { - errs = append(errs, err) + errs := make([]error, len(errors)) + for i, err := range errors { + errs[i] = err } b, err := json.Marshal(errs) if err != nil { @@ -293,8 +293,10 @@ func (c *wsConnection) sendConnectionError(format string, args ...interface{}) { func (c *wsConnection) readOp() *operationMessage { _, r, err := c.conn.NextReader() - if err != nil { - c.sendConnectionError("invalid json") + if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseNoStatusReceived) { + return nil + } else if err != nil { + c.sendConnectionError("invalid json: %T %s", err, err.Error()) return nil } message := operationMessage{} diff --git a/vendor/github.com/99designs/gqlgen/handler/context.go b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket_init.go similarity index 78% rename from vendor/github.com/99designs/gqlgen/handler/context.go rename to vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket_init.go index 2992aa3d4..a5f84ba2d 100644 --- a/vendor/github.com/99designs/gqlgen/handler/context.go +++ b/vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket_init.go @@ -1,4 +1,4 @@ -package handler +package transport import "context" @@ -14,12 +14,12 @@ type InitPayload map[string]interface{} // GetString safely gets a string value from the payload. It returns an empty string if the // payload is nil or the value isn't set. -func (payload InitPayload) GetString(key string) string { - if payload == nil { +func (p InitPayload) GetString(key string) string { + if p == nil { return "" } - if value, ok := payload[key]; ok { + if value, ok := p[key]; ok { res, _ := value.(string) return res } @@ -29,12 +29,12 @@ func (payload InitPayload) GetString(key string) string { // Authorization is a short hand for getting the Authorization header from the // payload. -func (payload InitPayload) Authorization() string { - if value := payload.GetString("Authorization"); value != "" { +func (p InitPayload) Authorization() string { + if value := p.GetString("Authorization"); value != "" { return value } - if value := payload.GetString("authorization"); value != "" { + if value := p.GetString("authorization"); value != "" { return value } diff --git a/vendor/github.com/99designs/gqlgen/graphql/id.go b/vendor/github.com/99designs/gqlgen/graphql/id.go index 4f532037d..2e78a5ec4 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/id.go +++ b/vendor/github.com/99designs/gqlgen/graphql/id.go @@ -20,6 +20,8 @@ func UnmarshalID(v interface{}) (string, error) { return string(v), nil case int: return strconv.Itoa(v), nil + case int64: + return strconv.FormatInt(v, 10), nil case float64: return fmt.Sprintf("%f", v), nil case bool: diff --git a/vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go b/vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go index ca0b065f8..5239c9283 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go +++ b/vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go @@ -1,7 +1,7 @@ // introspection implements the spec defined in https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection package introspection -import "github.com/vektah/gqlparser/ast" +import "github.com/vektah/gqlparser/v2/ast" type ( Directive struct { diff --git a/vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go b/vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go index b5d2c4822..044e91d6e 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go +++ b/vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go @@ -3,7 +3,7 @@ package introspection import ( "strings" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type Schema struct { @@ -11,7 +11,7 @@ type Schema struct { } func (s *Schema) Types() []Type { - var types []Type + types := make([]Type, 0, len(s.schema.Types)) for _, typ := range s.schema.Types { if strings.HasPrefix(typ.Name, "__") { continue @@ -34,7 +34,7 @@ func (s *Schema) SubscriptionType() *Type { } func (s *Schema) Directives() []Directive { - var res []Directive + res := make([]Directive, 0, len(s.schema.Directives)) for _, d := range s.schema.Directives { res = append(res, s.directiveFromDef(d)) @@ -44,19 +44,19 @@ func (s *Schema) Directives() []Directive { } func (s *Schema) directiveFromDef(d *ast.DirectiveDefinition) Directive { - var locs []string - for _, loc := range d.Locations { - locs = append(locs, string(loc)) + locs := make([]string, len(d.Locations)) + for i, loc := range d.Locations { + locs[i] = string(loc) } - var args []InputValue - for _, arg := range d.Arguments { - args = append(args, InputValue{ + args := make([]InputValue, len(d.Arguments)) + for i, arg := range d.Arguments { + args[i] = InputValue{ Name: arg.Name, Description: arg.Description, DefaultValue: defaultValue(arg.DefaultValue), Type: WrapTypeFromType(s.schema, arg.Type), - }) + } } return Directive{ diff --git a/vendor/github.com/99designs/gqlgen/graphql/introspection/type.go b/vendor/github.com/99designs/gqlgen/graphql/introspection/type.go index 9aceebdc9..f842fa645 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/introspection/type.go +++ b/vendor/github.com/99designs/gqlgen/graphql/introspection/type.go @@ -3,7 +3,7 @@ package introspection import ( "strings" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type Type struct { @@ -152,6 +152,10 @@ func (t *Type) EnumValues(includeDeprecated bool) []EnumValue { res := []EnumValue{} for _, val := range t.def.EnumValues { + if !includeDeprecated && val.Directives.ForName("deprecated") != nil { + continue + } + res = append(res, EnumValue{ Name: val.Name, Description: val.Description, diff --git a/vendor/github.com/99designs/gqlgen/graphql/oneshot.go b/vendor/github.com/99designs/gqlgen/graphql/oneshot.go index dd31f5baa..01fa15f89 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/oneshot.go +++ b/vendor/github.com/99designs/gqlgen/graphql/oneshot.go @@ -1,9 +1,11 @@ package graphql -func OneShot(resp *Response) func() *Response { +import "context" + +func OneShot(resp *Response) ResponseHandler { var oneshot bool - return func() *Response { + return func(context context.Context) *Response { if oneshot { return nil } diff --git a/vendor/github.com/99designs/gqlgen/handler/playground.go b/vendor/github.com/99designs/gqlgen/graphql/playground/playground.go similarity index 92% rename from vendor/github.com/99designs/gqlgen/handler/playground.go rename to vendor/github.com/99designs/gqlgen/graphql/playground/playground.go index 0e1ca7686..45bbbd4f1 100644 --- a/vendor/github.com/99designs/gqlgen/handler/playground.go +++ b/vendor/github.com/99designs/gqlgen/graphql/playground/playground.go @@ -1,4 +1,4 @@ -package handler +package playground import ( "html/template" @@ -11,7 +11,7 @@ var page = template.Must(template.New("graphiql").Parse(` - @@ -33,6 +33,7 @@ var page = template.Must(template.New("graphiql").Parse(` GraphQLPlayground.init(root, { endpoint: location.protocol + '//' + location.host + '{{.endpoint}}', subscriptionsEndpoint: wsProto + '//' + location.host + '{{.endpoint }}', + shareEnabled: true, settings: { 'request.credentials': 'same-origin' } @@ -43,7 +44,7 @@ var page = template.Must(template.New("graphiql").Parse(` `)) -func Playground(title string, endpoint string) http.HandlerFunc { +func Handler(title string, endpoint string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "text/html") err := page.Execute(w, map[string]string{ diff --git a/vendor/github.com/99designs/gqlgen/graphql/response.go b/vendor/github.com/99designs/gqlgen/graphql/response.go index 6fe55d56d..0d36049a3 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/response.go +++ b/vendor/github.com/99designs/gqlgen/graphql/response.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" ) // Errors are intentionally serialized first based on the advice in diff --git a/vendor/github.com/99designs/gqlgen/graphql/stats.go b/vendor/github.com/99designs/gqlgen/graphql/stats.go new file mode 100644 index 000000000..a52e143eb --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/graphql/stats.go @@ -0,0 +1,60 @@ +package graphql + +import ( + "context" + "fmt" + "time" +) + +type Stats struct { + OperationStart time.Time + Read TraceTiming + Parsing TraceTiming + Validation TraceTiming + + // Stats collected by handler extensions. Dont use directly, the extension should provide a type safe way to + // access this. + extension map[string]interface{} +} + +type TraceTiming struct { + Start time.Time + End time.Time +} + +var ctxTraceStart key = "trace_start" + +// StartOperationTrace captures the current time and stores it in context. This will eventually be added to request +// context but we want to grab it as soon as possible. For transports that can only handle a single graphql query +// per http requests you dont need to call this at all, the server will do it for you. For transports that handle +// multiple (eg batching, subscriptions) this should be called before decoding each request. +func StartOperationTrace(ctx context.Context) context.Context { + return context.WithValue(ctx, ctxTraceStart, Now()) +} + +// GetStartTime should only be called by the handler package, it will be set into request context +// as Stats.Start +func GetStartTime(ctx context.Context) time.Time { + t, ok := ctx.Value(ctxTraceStart).(time.Time) + if !ok { + panic(fmt.Sprintf("missing start time: %T", ctx.Value(ctxTraceStart))) + } + return t +} + +func (c *Stats) SetExtension(name string, data interface{}) { + if c.extension == nil { + c.extension = map[string]interface{}{} + } + c.extension[name] = data +} + +func (c *Stats) GetExtension(name string) interface{} { + if c.extension == nil { + return nil + } + return c.extension[name] +} + +// Now is time.Now, except in tests. Then it can be whatever you want it to be. +var Now = time.Now diff --git a/vendor/github.com/99designs/gqlgen/graphql/tracer.go b/vendor/github.com/99designs/gqlgen/graphql/tracer.go deleted file mode 100644 index 0597ce8cc..000000000 --- a/vendor/github.com/99designs/gqlgen/graphql/tracer.go +++ /dev/null @@ -1,58 +0,0 @@ -package graphql - -import ( - "context" -) - -var _ Tracer = (*NopTracer)(nil) - -type Tracer interface { - StartOperationParsing(ctx context.Context) context.Context - EndOperationParsing(ctx context.Context) - StartOperationValidation(ctx context.Context) context.Context - EndOperationValidation(ctx context.Context) - StartOperationExecution(ctx context.Context) context.Context - StartFieldExecution(ctx context.Context, field CollectedField) context.Context - StartFieldResolverExecution(ctx context.Context, rc *ResolverContext) context.Context - StartFieldChildExecution(ctx context.Context) context.Context - EndFieldExecution(ctx context.Context) - EndOperationExecution(ctx context.Context) -} - -type NopTracer struct{} - -func (NopTracer) StartOperationParsing(ctx context.Context) context.Context { - return ctx -} - -func (NopTracer) EndOperationParsing(ctx context.Context) { -} - -func (NopTracer) StartOperationValidation(ctx context.Context) context.Context { - return ctx -} - -func (NopTracer) EndOperationValidation(ctx context.Context) { -} - -func (NopTracer) StartOperationExecution(ctx context.Context) context.Context { - return ctx -} - -func (NopTracer) StartFieldExecution(ctx context.Context, field CollectedField) context.Context { - return ctx -} - -func (NopTracer) StartFieldResolverExecution(ctx context.Context, rc *ResolverContext) context.Context { - return ctx -} - -func (NopTracer) StartFieldChildExecution(ctx context.Context) context.Context { - return ctx -} - -func (NopTracer) EndFieldExecution(ctx context.Context) { -} - -func (NopTracer) EndOperationExecution(ctx context.Context) { -} diff --git a/vendor/github.com/99designs/gqlgen/graphql/upload.go b/vendor/github.com/99designs/gqlgen/graphql/upload.go index 22d610314..62f71c0dc 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/upload.go +++ b/vendor/github.com/99designs/gqlgen/graphql/upload.go @@ -6,9 +6,10 @@ import ( ) type Upload struct { - File io.Reader - Filename string - Size int64 + File io.Reader + Filename string + Size int64 + ContentType string } func MarshalUpload(f Upload) Marshaler { diff --git a/vendor/github.com/99designs/gqlgen/graphql/version.go b/vendor/github.com/99designs/gqlgen/graphql/version.go index 11dc6b019..49954bbb6 100644 --- a/vendor/github.com/99designs/gqlgen/graphql/version.go +++ b/vendor/github.com/99designs/gqlgen/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.9.0" +const Version = "v0.12.2" diff --git a/vendor/github.com/99designs/gqlgen/handler/graphql.go b/vendor/github.com/99designs/gqlgen/handler/graphql.go deleted file mode 100644 index a22542225..000000000 --- a/vendor/github.com/99designs/gqlgen/handler/graphql.go +++ /dev/null @@ -1,709 +0,0 @@ -package handler - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "mime" - "net/http" - "os" - "strconv" - "strings" - "time" - - "github.com/99designs/gqlgen/complexity" - "github.com/99designs/gqlgen/graphql" - "github.com/gorilla/websocket" - lru "github.com/hashicorp/golang-lru" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/parser" - "github.com/vektah/gqlparser/validator" -) - -type params struct { - Query string `json:"query"` - OperationName string `json:"operationName"` - Variables map[string]interface{} `json:"variables"` -} - -type Config struct { - cacheSize int - upgrader websocket.Upgrader - recover graphql.RecoverFunc - errorPresenter graphql.ErrorPresenterFunc - resolverHook graphql.FieldMiddleware - requestHook graphql.RequestMiddleware - tracer graphql.Tracer - complexityLimit int - complexityLimitFunc graphql.ComplexityLimitFunc - disableIntrospection bool - connectionKeepAlivePingInterval time.Duration - uploadMaxMemory int64 - uploadMaxSize int64 -} - -func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDocument, op *ast.OperationDefinition, query string, variables map[string]interface{}) *graphql.RequestContext { - reqCtx := graphql.NewRequestContext(doc, query, variables) - reqCtx.DisableIntrospection = c.disableIntrospection - - if hook := c.recover; hook != nil { - reqCtx.Recover = hook - } - - if hook := c.errorPresenter; hook != nil { - reqCtx.ErrorPresenter = hook - } - - if hook := c.resolverHook; hook != nil { - reqCtx.ResolverMiddleware = hook - } - - if hook := c.requestHook; hook != nil { - reqCtx.RequestMiddleware = hook - } - - if hook := c.tracer; hook != nil { - reqCtx.Tracer = hook - } - - if c.complexityLimit > 0 || c.complexityLimitFunc != nil { - reqCtx.ComplexityLimit = c.complexityLimit - operationComplexity := complexity.Calculate(es, op, variables) - reqCtx.OperationComplexity = operationComplexity - } - - return reqCtx -} - -type Option func(cfg *Config) - -func WebsocketUpgrader(upgrader websocket.Upgrader) Option { - return func(cfg *Config) { - cfg.upgrader = upgrader - } -} - -func RecoverFunc(recover graphql.RecoverFunc) Option { - return func(cfg *Config) { - cfg.recover = recover - } -} - -// ErrorPresenter transforms errors found while resolving into errors that will be returned to the user. It provides -// a good place to add any extra fields, like error.type, that might be desired by your frontend. Check the default -// implementation in graphql.DefaultErrorPresenter for an example. -func ErrorPresenter(f graphql.ErrorPresenterFunc) Option { - return func(cfg *Config) { - cfg.errorPresenter = f - } -} - -// IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be useful in prod when you dont -// want clients introspecting the full schema. -func IntrospectionEnabled(enabled bool) Option { - return func(cfg *Config) { - cfg.disableIntrospection = !enabled - } -} - -// ComplexityLimit sets a maximum query complexity that is allowed to be executed. -// If a query is submitted that exceeds the limit, a 422 status code will be returned. -func ComplexityLimit(limit int) Option { - return func(cfg *Config) { - cfg.complexityLimit = limit - } -} - -// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed -// to be executed. -// If a query is submitted that exceeds the limit, a 422 status code will be returned. -func ComplexityLimitFunc(complexityLimitFunc graphql.ComplexityLimitFunc) Option { - return func(cfg *Config) { - cfg.complexityLimitFunc = complexityLimitFunc - } -} - -// ResolverMiddleware allows you to define a function that will be called around every resolver, -// useful for logging. -func ResolverMiddleware(middleware graphql.FieldMiddleware) Option { - return func(cfg *Config) { - if cfg.resolverHook == nil { - cfg.resolverHook = middleware - return - } - - lastResolve := cfg.resolverHook - cfg.resolverHook = func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { - return lastResolve(ctx, func(ctx context.Context) (res interface{}, err error) { - return middleware(ctx, next) - }) - } - } -} - -// RequestMiddleware allows you to define a function that will be called around the root request, -// after the query has been parsed. This is useful for logging -func RequestMiddleware(middleware graphql.RequestMiddleware) Option { - return func(cfg *Config) { - if cfg.requestHook == nil { - cfg.requestHook = middleware - return - } - - lastResolve := cfg.requestHook - cfg.requestHook = func(ctx context.Context, next func(ctx context.Context) []byte) []byte { - return lastResolve(ctx, func(ctx context.Context) []byte { - return middleware(ctx, next) - }) - } - } -} - -// Tracer allows you to add a request/resolver tracer that will be called around the root request, -// calling resolver. This is useful for tracing -func Tracer(tracer graphql.Tracer) Option { - return func(cfg *Config) { - if cfg.tracer == nil { - cfg.tracer = tracer - - } else { - lastResolve := cfg.tracer - cfg.tracer = &tracerWrapper{ - tracer1: lastResolve, - tracer2: tracer, - } - } - - opt := RequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte { - ctx = tracer.StartOperationExecution(ctx) - resp := next(ctx) - tracer.EndOperationExecution(ctx) - - return resp - }) - opt(cfg) - } -} - -type tracerWrapper struct { - tracer1 graphql.Tracer - tracer2 graphql.Tracer -} - -func (tw *tracerWrapper) StartOperationParsing(ctx context.Context) context.Context { - ctx = tw.tracer1.StartOperationParsing(ctx) - ctx = tw.tracer2.StartOperationParsing(ctx) - return ctx -} - -func (tw *tracerWrapper) EndOperationParsing(ctx context.Context) { - tw.tracer2.EndOperationParsing(ctx) - tw.tracer1.EndOperationParsing(ctx) -} - -func (tw *tracerWrapper) StartOperationValidation(ctx context.Context) context.Context { - ctx = tw.tracer1.StartOperationValidation(ctx) - ctx = tw.tracer2.StartOperationValidation(ctx) - return ctx -} - -func (tw *tracerWrapper) EndOperationValidation(ctx context.Context) { - tw.tracer2.EndOperationValidation(ctx) - tw.tracer1.EndOperationValidation(ctx) -} - -func (tw *tracerWrapper) StartOperationExecution(ctx context.Context) context.Context { - ctx = tw.tracer1.StartOperationExecution(ctx) - ctx = tw.tracer2.StartOperationExecution(ctx) - return ctx -} - -func (tw *tracerWrapper) StartFieldExecution(ctx context.Context, field graphql.CollectedField) context.Context { - ctx = tw.tracer1.StartFieldExecution(ctx, field) - ctx = tw.tracer2.StartFieldExecution(ctx, field) - return ctx -} - -func (tw *tracerWrapper) StartFieldResolverExecution(ctx context.Context, rc *graphql.ResolverContext) context.Context { - ctx = tw.tracer1.StartFieldResolverExecution(ctx, rc) - ctx = tw.tracer2.StartFieldResolverExecution(ctx, rc) - return ctx -} - -func (tw *tracerWrapper) StartFieldChildExecution(ctx context.Context) context.Context { - ctx = tw.tracer1.StartFieldChildExecution(ctx) - ctx = tw.tracer2.StartFieldChildExecution(ctx) - return ctx -} - -func (tw *tracerWrapper) EndFieldExecution(ctx context.Context) { - tw.tracer2.EndFieldExecution(ctx) - tw.tracer1.EndFieldExecution(ctx) -} - -func (tw *tracerWrapper) EndOperationExecution(ctx context.Context) { - tw.tracer2.EndOperationExecution(ctx) - tw.tracer1.EndOperationExecution(ctx) -} - -// CacheSize sets the maximum size of the query cache. -// If size is less than or equal to 0, the cache is disabled. -func CacheSize(size int) Option { - return func(cfg *Config) { - cfg.cacheSize = size - } -} - -// UploadMaxSize sets the maximum number of bytes used to parse a request body -// as multipart/form-data. -func UploadMaxSize(size int64) Option { - return func(cfg *Config) { - cfg.uploadMaxSize = size - } -} - -// UploadMaxMemory sets the maximum number of bytes used to parse a request body -// as multipart/form-data in memory, with the remainder stored on disk in -// temporary files. -func UploadMaxMemory(size int64) Option { - return func(cfg *Config) { - cfg.uploadMaxMemory = size - } -} - -// WebsocketKeepAliveDuration allows you to reconfigure the keepalive behavior. -// By default, keepalive is enabled with a DefaultConnectionKeepAlivePingInterval -// duration. Set handler.connectionKeepAlivePingInterval = 0 to disable keepalive -// altogether. -func WebsocketKeepAliveDuration(duration time.Duration) Option { - return func(cfg *Config) { - cfg.connectionKeepAlivePingInterval = duration - } -} - -const DefaultCacheSize = 1000 -const DefaultConnectionKeepAlivePingInterval = 25 * time.Second - -// DefaultUploadMaxMemory is the maximum number of bytes used to parse a request body -// as multipart/form-data in memory, with the remainder stored on disk in -// temporary files. -const DefaultUploadMaxMemory = 32 << 20 - -// DefaultUploadMaxSize is maximum number of bytes used to parse a request body -// as multipart/form-data. -const DefaultUploadMaxSize = 32 << 20 - -func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc { - cfg := &Config{ - cacheSize: DefaultCacheSize, - uploadMaxMemory: DefaultUploadMaxMemory, - uploadMaxSize: DefaultUploadMaxSize, - connectionKeepAlivePingInterval: DefaultConnectionKeepAlivePingInterval, - upgrader: websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - }, - } - - for _, option := range options { - option(cfg) - } - - var cache *lru.Cache - if cfg.cacheSize > 0 { - var err error - cache, err = lru.New(cfg.cacheSize) - if err != nil { - // An error is only returned for non-positive cache size - // and we already checked for that. - panic("unexpected error creating cache: " + err.Error()) - } - } - if cfg.tracer == nil { - cfg.tracer = &graphql.NopTracer{} - } - - handler := &graphqlHandler{ - cfg: cfg, - cache: cache, - exec: exec, - } - - return handler.ServeHTTP -} - -var _ http.Handler = (*graphqlHandler)(nil) - -type graphqlHandler struct { - cfg *Config - cache *lru.Cache - exec graphql.ExecutableSchema -} - -func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodOptions { - w.Header().Set("Allow", "OPTIONS, GET, POST") - w.WriteHeader(http.StatusOK) - return - } - - if strings.Contains(r.Header.Get("Upgrade"), "websocket") { - connectWs(gh.exec, w, r, gh.cfg, gh.cache) - return - } - - w.Header().Set("Content-Type", "application/json") - var reqParams params - switch r.Method { - case http.MethodGet: - reqParams.Query = r.URL.Query().Get("query") - reqParams.OperationName = r.URL.Query().Get("operationName") - - if variables := r.URL.Query().Get("variables"); variables != "" { - if err := jsonDecode(strings.NewReader(variables), &reqParams.Variables); err != nil { - sendErrorf(w, http.StatusBadRequest, "variables could not be decoded") - return - } - } - case http.MethodPost: - mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) - if err != nil { - sendErrorf(w, http.StatusBadRequest, "error parsing request Content-Type") - return - } - - switch mediaType { - case "application/json": - if err := jsonDecode(r.Body, &reqParams); err != nil { - sendErrorf(w, http.StatusBadRequest, "json body could not be decoded: "+err.Error()) - return - } - - case "multipart/form-data": - var closers []io.Closer - var tmpFiles []string - defer func() { - for i := len(closers) - 1; 0 <= i; i-- { - _ = closers[i].Close() - } - for _, tmpFile := range tmpFiles { - _ = os.Remove(tmpFile) - } - }() - if err := processMultipart(w, r, &reqParams, &closers, &tmpFiles, gh.cfg.uploadMaxSize, gh.cfg.uploadMaxMemory); err != nil { - sendErrorf(w, http.StatusBadRequest, "multipart body could not be decoded: "+err.Error()) - return - } - default: - sendErrorf(w, http.StatusBadRequest, "unsupported Content-Type: "+mediaType) - return - } - default: - w.WriteHeader(http.StatusMethodNotAllowed) - return - } - - ctx := r.Context() - - var doc *ast.QueryDocument - var cacheHit bool - if gh.cache != nil { - val, ok := gh.cache.Get(reqParams.Query) - if ok { - doc = val.(*ast.QueryDocument) - cacheHit = true - } - } - - ctx, doc, gqlErr := gh.parseOperation(ctx, &parseOperationArgs{ - Query: reqParams.Query, - CachedDoc: doc, - }) - if gqlErr != nil { - sendError(w, http.StatusUnprocessableEntity, gqlErr) - return - } - - ctx, op, vars, listErr := gh.validateOperation(ctx, &validateOperationArgs{ - Doc: doc, - OperationName: reqParams.OperationName, - CacheHit: cacheHit, - R: r, - Variables: reqParams.Variables, - }) - if len(listErr) != 0 { - sendError(w, http.StatusUnprocessableEntity, listErr...) - return - } - - if gh.cache != nil && !cacheHit { - gh.cache.Add(reqParams.Query, doc) - } - - reqCtx := gh.cfg.newRequestContext(gh.exec, doc, op, reqParams.Query, vars) - ctx = graphql.WithRequestContext(ctx, reqCtx) - - defer func() { - if err := recover(); err != nil { - userErr := reqCtx.Recover(ctx, err) - sendErrorf(w, http.StatusUnprocessableEntity, userErr.Error()) - } - }() - - if gh.cfg.complexityLimitFunc != nil { - reqCtx.ComplexityLimit = gh.cfg.complexityLimitFunc(ctx) - } - - if reqCtx.ComplexityLimit > 0 && reqCtx.OperationComplexity > reqCtx.ComplexityLimit { - sendErrorf(w, http.StatusUnprocessableEntity, "operation has complexity %d, which exceeds the limit of %d", reqCtx.OperationComplexity, reqCtx.ComplexityLimit) - return - } - - switch op.Operation { - case ast.Query: - b, err := json.Marshal(gh.exec.Query(ctx, op)) - if err != nil { - panic(err) - } - w.Write(b) - case ast.Mutation: - b, err := json.Marshal(gh.exec.Mutation(ctx, op)) - if err != nil { - panic(err) - } - w.Write(b) - default: - sendErrorf(w, http.StatusBadRequest, "unsupported operation type") - } -} - -type parseOperationArgs struct { - Query string - CachedDoc *ast.QueryDocument -} - -func (gh *graphqlHandler) parseOperation(ctx context.Context, args *parseOperationArgs) (context.Context, *ast.QueryDocument, *gqlerror.Error) { - ctx = gh.cfg.tracer.StartOperationParsing(ctx) - defer func() { gh.cfg.tracer.EndOperationParsing(ctx) }() - - if args.CachedDoc != nil { - return ctx, args.CachedDoc, nil - } - - doc, gqlErr := parser.ParseQuery(&ast.Source{Input: args.Query}) - if gqlErr != nil { - return ctx, nil, gqlErr - } - - return ctx, doc, nil -} - -type validateOperationArgs struct { - Doc *ast.QueryDocument - OperationName string - CacheHit bool - R *http.Request - Variables map[string]interface{} -} - -func (gh *graphqlHandler) validateOperation(ctx context.Context, args *validateOperationArgs) (context.Context, *ast.OperationDefinition, map[string]interface{}, gqlerror.List) { - ctx = gh.cfg.tracer.StartOperationValidation(ctx) - defer func() { gh.cfg.tracer.EndOperationValidation(ctx) }() - - if !args.CacheHit { - listErr := validator.Validate(gh.exec.Schema(), args.Doc) - if len(listErr) != 0 { - return ctx, nil, nil, listErr - } - } - - op := args.Doc.Operations.ForName(args.OperationName) - if op == nil { - return ctx, nil, nil, gqlerror.List{gqlerror.Errorf("operation %s not found", args.OperationName)} - } - - if op.Operation != ast.Query && args.R.Method == http.MethodGet { - return ctx, nil, nil, gqlerror.List{gqlerror.Errorf("GET requests only allow query operations")} - } - - vars, err := validator.VariableValues(gh.exec.Schema(), op, args.Variables) - if err != nil { - return ctx, nil, nil, gqlerror.List{err} - } - - return ctx, op, vars, nil -} - -func jsonDecode(r io.Reader, val interface{}) error { - dec := json.NewDecoder(r) - dec.UseNumber() - return dec.Decode(val) -} - -func sendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) { - w.WriteHeader(code) - b, err := json.Marshal(&graphql.Response{Errors: errors}) - if err != nil { - panic(err) - } - w.Write(b) -} - -func sendErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) { - sendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)}) -} - -type bytesReader struct { - s *[]byte - i int64 // current reading index - prevRune int // index of previous rune; or < 0 -} - -func (r *bytesReader) Read(b []byte) (n int, err error) { - if r.s == nil { - return 0, errors.New("byte slice pointer is nil") - } - if r.i >= int64(len(*r.s)) { - return 0, io.EOF - } - r.prevRune = -1 - n = copy(b, (*r.s)[r.i:]) - r.i += int64(n) - return -} - -func processMultipart(w http.ResponseWriter, r *http.Request, request *params, closers *[]io.Closer, tmpFiles *[]string, uploadMaxSize, uploadMaxMemory int64) error { - var err error - if r.ContentLength > uploadMaxSize { - return errors.New("failed to parse multipart form, request body too large") - } - r.Body = http.MaxBytesReader(w, r.Body, uploadMaxSize) - if err = r.ParseMultipartForm(uploadMaxMemory); err != nil { - if strings.Contains(err.Error(), "request body too large") { - return errors.New("failed to parse multipart form, request body too large") - } - return errors.New("failed to parse multipart form") - } - *closers = append(*closers, r.Body) - - if err = jsonDecode(strings.NewReader(r.Form.Get("operations")), &request); err != nil { - return errors.New("operations form field could not be decoded") - } - - var uploadsMap = map[string][]string{} - if err = json.Unmarshal([]byte(r.Form.Get("map")), &uploadsMap); err != nil { - return errors.New("map form field could not be decoded") - } - - var upload graphql.Upload - for key, paths := range uploadsMap { - if len(paths) == 0 { - return fmt.Errorf("invalid empty operations paths list for key %s", key) - } - file, header, err := r.FormFile(key) - if err != nil { - return fmt.Errorf("failed to get key %s from form", key) - } - *closers = append(*closers, file) - - if len(paths) == 1 { - upload = graphql.Upload{ - File: file, - Size: header.Size, - Filename: header.Filename, - } - err = addUploadToOperations(request, upload, key, paths[0]) - if err != nil { - return err - } - } else { - if r.ContentLength < uploadMaxMemory { - fileBytes, err := ioutil.ReadAll(file) - if err != nil { - return fmt.Errorf("failed to read file for key %s", key) - } - for _, path := range paths { - upload = graphql.Upload{ - File: &bytesReader{s: &fileBytes, i: 0, prevRune: -1}, - Size: header.Size, - Filename: header.Filename, - } - err = addUploadToOperations(request, upload, key, path) - if err != nil { - return err - } - } - } else { - tmpFile, err := ioutil.TempFile(os.TempDir(), "gqlgen-") - if err != nil { - return fmt.Errorf("failed to create temp file for key %s", key) - } - tmpName := tmpFile.Name() - *tmpFiles = append(*tmpFiles, tmpName) - _, err = io.Copy(tmpFile, file) - if err != nil { - if err := tmpFile.Close(); err != nil { - return fmt.Errorf("failed to copy to temp file and close temp file for key %s", key) - } - return fmt.Errorf("failed to copy to temp file for key %s", key) - } - if err := tmpFile.Close(); err != nil { - return fmt.Errorf("failed to close temp file for key %s", key) - } - for _, path := range paths { - pathTmpFile, err := os.Open(tmpName) - if err != nil { - return fmt.Errorf("failed to open temp file for key %s", key) - } - *closers = append(*closers, pathTmpFile) - upload = graphql.Upload{ - File: pathTmpFile, - Size: header.Size, - Filename: header.Filename, - } - err = addUploadToOperations(request, upload, key, path) - if err != nil { - return err - } - } - } - } - } - return nil -} - -func addUploadToOperations(request *params, upload graphql.Upload, key, path string) error { - if !strings.HasPrefix(path, "variables.") { - return fmt.Errorf("invalid operations paths for key %s", key) - } - - var ptr interface{} = request.Variables - parts := strings.Split(path, ".") - - // skip the first part (variables) because we started there - for i, p := range parts[1:] { - last := i == len(parts)-2 - if ptr == nil { - return fmt.Errorf("path is missing \"variables.\" prefix, key: %s, path: %s", key, path) - } - if index, parseNbrErr := strconv.Atoi(p); parseNbrErr == nil { - if last { - ptr.([]interface{})[index] = upload - } else { - ptr = ptr.([]interface{})[index] - } - } else { - if last { - ptr.(map[string]interface{})[p] = upload - } else { - ptr = ptr.(map[string]interface{})[p] - } - } - } - - return nil -} diff --git a/vendor/github.com/99designs/gqlgen/handler/handler.go b/vendor/github.com/99designs/gqlgen/handler/handler.go new file mode 100644 index 000000000..892df5398 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/handler/handler.go @@ -0,0 +1,247 @@ +package handler + +import ( + "context" + "net/http" + "time" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/lru" + "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/99designs/gqlgen/graphql/playground" + "github.com/gorilla/websocket" +) + +// Deprecated: switch to graphql/handler.New +func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc { + var cfg Config + cfg.cacheSize = 1000 + + for _, option := range options { + option(&cfg) + } + + srv := handler.New(exec) + + srv.AddTransport(transport.Websocket{ + Upgrader: cfg.upgrader, + InitFunc: cfg.websocketInitFunc, + KeepAlivePingInterval: cfg.connectionKeepAlivePingInterval, + }) + srv.AddTransport(transport.Options{}) + srv.AddTransport(transport.GET{}) + srv.AddTransport(transport.POST{}) + srv.AddTransport(transport.MultipartForm{ + MaxUploadSize: cfg.uploadMaxSize, + MaxMemory: cfg.uploadMaxMemory, + }) + + if cfg.cacheSize != 0 { + srv.SetQueryCache(lru.New(cfg.cacheSize)) + } + if cfg.recover != nil { + srv.SetRecoverFunc(cfg.recover) + } + if cfg.errorPresenter != nil { + srv.SetErrorPresenter(cfg.errorPresenter) + } + for _, hook := range cfg.fieldHooks { + srv.AroundFields(hook) + } + for _, hook := range cfg.requestHooks { + srv.AroundResponses(hook) + } + if cfg.complexityLimit != 0 { + srv.Use(extension.FixedComplexityLimit(cfg.complexityLimit)) + } else if cfg.complexityLimitFunc != nil { + srv.Use(&extension.ComplexityLimit{ + Func: func(ctx context.Context, rc *graphql.OperationContext) int { + return cfg.complexityLimitFunc(graphql.WithOperationContext(ctx, rc)) + }, + }) + } + if !cfg.disableIntrospection { + srv.Use(extension.Introspection{}) + } + if cfg.apqCache != nil { + srv.Use(extension.AutomaticPersistedQuery{Cache: apqAdapter{cfg.apqCache}}) + } + return srv.ServeHTTP +} + +// Deprecated: switch to graphql/handler.New +type Config struct { + cacheSize int + upgrader websocket.Upgrader + websocketInitFunc transport.WebsocketInitFunc + connectionKeepAlivePingInterval time.Duration + recover graphql.RecoverFunc + errorPresenter graphql.ErrorPresenterFunc + fieldHooks []graphql.FieldMiddleware + requestHooks []graphql.ResponseMiddleware + complexityLimit int + complexityLimitFunc func(ctx context.Context) int + disableIntrospection bool + uploadMaxMemory int64 + uploadMaxSize int64 + apqCache PersistedQueryCache +} + +// Deprecated: switch to graphql/handler.New +type Option func(cfg *Config) + +// Deprecated: switch to graphql/handler.New +func WebsocketUpgrader(upgrader websocket.Upgrader) Option { + return func(cfg *Config) { + cfg.upgrader = upgrader + } +} + +// Deprecated: switch to graphql/handler.New +func RecoverFunc(recover graphql.RecoverFunc) Option { + return func(cfg *Config) { + cfg.recover = recover + } +} + +// ErrorPresenter transforms errors found while resolving into errors that will be returned to the user. It provides +// a good place to add any extra fields, like error.type, that might be desired by your frontend. Check the default +// implementation in graphql.DefaultErrorPresenter for an example. +// Deprecated: switch to graphql/handler.New +func ErrorPresenter(f graphql.ErrorPresenterFunc) Option { + return func(cfg *Config) { + cfg.errorPresenter = f + } +} + +// IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be useful in prod when you dont +// want clients introspecting the full schema. +// Deprecated: switch to graphql/handler.New +func IntrospectionEnabled(enabled bool) Option { + return func(cfg *Config) { + cfg.disableIntrospection = !enabled + } +} + +// ComplexityLimit sets a maximum query complexity that is allowed to be executed. +// If a query is submitted that exceeds the limit, a 422 status code will be returned. +// Deprecated: switch to graphql/handler.New +func ComplexityLimit(limit int) Option { + return func(cfg *Config) { + cfg.complexityLimit = limit + } +} + +// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed +// to be executed. +// If a query is submitted that exceeds the limit, a 422 status code will be returned. +// Deprecated: switch to graphql/handler.New +func ComplexityLimitFunc(complexityLimitFunc func(ctx context.Context) int) Option { + return func(cfg *Config) { + cfg.complexityLimitFunc = complexityLimitFunc + } +} + +// ResolverMiddleware allows you to define a function that will be called around every resolver, +// useful for logging. +// Deprecated: switch to graphql/handler.New +func ResolverMiddleware(middleware graphql.FieldMiddleware) Option { + return func(cfg *Config) { + cfg.fieldHooks = append(cfg.fieldHooks, middleware) + } +} + +// RequestMiddleware allows you to define a function that will be called around the root request, +// after the query has been parsed. This is useful for logging +// Deprecated: switch to graphql/handler.New +func RequestMiddleware(middleware graphql.ResponseMiddleware) Option { + return func(cfg *Config) { + cfg.requestHooks = append(cfg.requestHooks, middleware) + } +} + +// WebsocketInitFunc is called when the server receives connection init message from the client. +// This can be used to check initial payload to see whether to accept the websocket connection. +// Deprecated: switch to graphql/handler.New +func WebsocketInitFunc(websocketInitFunc transport.WebsocketInitFunc) Option { + return func(cfg *Config) { + cfg.websocketInitFunc = websocketInitFunc + } +} + +// CacheSize sets the maximum size of the query cache. +// If size is less than or equal to 0, the cache is disabled. +// Deprecated: switch to graphql/handler.New +func CacheSize(size int) Option { + return func(cfg *Config) { + cfg.cacheSize = size + } +} + +// UploadMaxSize sets the maximum number of bytes used to parse a request body +// as multipart/form-data. +// Deprecated: switch to graphql/handler.New +func UploadMaxSize(size int64) Option { + return func(cfg *Config) { + cfg.uploadMaxSize = size + } +} + +// UploadMaxMemory sets the maximum number of bytes used to parse a request body +// as multipart/form-data in memory, with the remainder stored on disk in +// temporary files. +// Deprecated: switch to graphql/handler.New +func UploadMaxMemory(size int64) Option { + return func(cfg *Config) { + cfg.uploadMaxMemory = size + } +} + +// WebsocketKeepAliveDuration allows you to reconfigure the keepalive behavior. +// By default, keepalive is enabled with a DefaultConnectionKeepAlivePingInterval +// duration. Set handler.connectionKeepAlivePingInterval = 0 to disable keepalive +// altogether. +// Deprecated: switch to graphql/handler.New +func WebsocketKeepAliveDuration(duration time.Duration) Option { + return func(cfg *Config) { + cfg.connectionKeepAlivePingInterval = duration + } +} + +// Add cache that will hold queries for automatic persisted queries (APQ) +// Deprecated: switch to graphql/handler.New +func EnablePersistedQueryCache(cache PersistedQueryCache) Option { + return func(cfg *Config) { + cfg.apqCache = cache + } +} + +func GetInitPayload(ctx context.Context) transport.InitPayload { + return transport.GetInitPayload(ctx) +} + +type apqAdapter struct { + PersistedQueryCache +} + +func (a apqAdapter) Get(ctx context.Context, key string) (value interface{}, ok bool) { + return a.PersistedQueryCache.Get(ctx, key) +} +func (a apqAdapter) Add(ctx context.Context, key string, value interface{}) { + a.PersistedQueryCache.Add(ctx, key, value.(string)) +} + +type PersistedQueryCache interface { + Add(ctx context.Context, hash string, query string) + Get(ctx context.Context, hash string) (string, bool) +} + +// Deprecated: use playground.Handler instead +func Playground(title string, endpoint string) http.HandlerFunc { + return playground.Handler(title, endpoint) +} + +// Deprecated: use transport.InitPayload instead +type InitPayload = transport.InitPayload diff --git a/vendor/github.com/99designs/gqlgen/handler/mock.go b/vendor/github.com/99designs/gqlgen/handler/mock.go deleted file mode 100644 index 3e70cf036..000000000 --- a/vendor/github.com/99designs/gqlgen/handler/mock.go +++ /dev/null @@ -1,57 +0,0 @@ -package handler - -import ( - "context" - - "github.com/99designs/gqlgen/graphql" - "github.com/vektah/gqlparser" - "github.com/vektah/gqlparser/ast" -) - -type executableSchemaMock struct { - MutationFunc func(ctx context.Context, op *ast.OperationDefinition) *graphql.Response -} - -var _ graphql.ExecutableSchema = &executableSchemaMock{} - -func (e *executableSchemaMock) Schema() *ast.Schema { - return gqlparser.MustLoadSchema(&ast.Source{Input: ` - schema { query: Query, mutation: Mutation } - type Query { - empty: String! - } - scalar Upload - type File { - id: Int! - } - input UploadFile { - id: Int! - file: Upload! - } - type Mutation { - singleUpload(file: Upload!): File! - singleUploadWithPayload(req: UploadFile!): File! - multipleUpload(files: [Upload!]!): [File!]! - multipleUploadWithPayload(req: [UploadFile!]!): [File!]! - } - `}) -} - -func (e *executableSchemaMock) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool) { - return 0, false -} - -func (e *executableSchemaMock) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - return graphql.ErrorResponse(ctx, "queries are not supported") -} - -func (e *executableSchemaMock) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - return e.MutationFunc(ctx, op) -} - -func (e *executableSchemaMock) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { - return func() *graphql.Response { - <-ctx.Done() - return nil - } -} diff --git a/vendor/github.com/99designs/gqlgen/handler/stub.go b/vendor/github.com/99designs/gqlgen/handler/stub.go deleted file mode 100644 index d237e1889..000000000 --- a/vendor/github.com/99designs/gqlgen/handler/stub.go +++ /dev/null @@ -1,51 +0,0 @@ -package handler - -import ( - "context" - - "github.com/99designs/gqlgen/graphql" - "github.com/vektah/gqlparser" - "github.com/vektah/gqlparser/ast" -) - -type executableSchemaStub struct { - NextResp chan struct{} -} - -var _ graphql.ExecutableSchema = &executableSchemaStub{} - -func (e *executableSchemaStub) Schema() *ast.Schema { - return gqlparser.MustLoadSchema(&ast.Source{Input: ` - schema { query: Query } - type Query { - me: User! - user(id: Int): User! - } - type User { name: String! } - `}) -} - -func (e *executableSchemaStub) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool) { - return 0, false -} - -func (e *executableSchemaStub) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - return &graphql.Response{Data: []byte(`{"name":"test"}`)} -} - -func (e *executableSchemaStub) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - return graphql.ErrorResponse(ctx, "mutations are not supported") -} - -func (e *executableSchemaStub) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { - return func() *graphql.Response { - select { - case <-ctx.Done(): - return nil - case <-e.NextResp: - return &graphql.Response{ - Data: []byte(`{"name":"test"}`), - } - } - } -} diff --git a/vendor/github.com/99designs/gqlgen/internal/code/imports.go b/vendor/github.com/99designs/gqlgen/internal/code/imports.go index 75c30fe1e..b56d80fc5 100644 --- a/vendor/github.com/99designs/gqlgen/internal/code/imports.go +++ b/vendor/github.com/99designs/gqlgen/internal/code/imports.go @@ -1,7 +1,6 @@ package code import ( - "errors" "go/build" "go/parser" "go/token" @@ -9,13 +8,8 @@ import ( "path/filepath" "regexp" "strings" - "sync" - - "golang.org/x/tools/go/packages" ) -var nameForPackageCache = sync.Map{} - var gopaths []string func init() { @@ -51,33 +45,50 @@ func NameForDir(dir string) string { return SanitizePackageName(filepath.Base(dir)) } -// ImportPathForDir takes a path and returns a golang import path for the package -func ImportPathForDir(dir string) (res string) { +// goModuleRoot returns the root of the current go module if there is a go.mod file in the directory tree +// If not, it returns false +func goModuleRoot(dir string) (string, bool) { 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")) + f, err := ioutil.ReadFile(filepath.Join(modDir, "go.mod")) if err == nil { // found it, stop searching - return string(modregex.FindSubmatch(f)[1]) + assumedPart + return string(modregex.FindSubmatch(f)[1]) + assumedPart, true } assumedPart = "/" + filepath.Base(modDir) + assumedPart - modDir, err = filepath.Abs(filepath.Join(modDir, "..")) + parentDir, err := filepath.Abs(filepath.Join(modDir, "..")) if err != nil { panic(err) } - // Walked all the way to the root and didnt find anything :'( - if modDir == "/" { + if parentDir == modDir { + // Walked all the way to the root and didnt find anything :'( break } + modDir = parentDir + } + return "", false +} + +// 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, ok := goModuleRoot(dir) + if ok { + return modDir } for _, gopath := range gopaths { @@ -89,26 +100,4 @@ func ImportPathForDir(dir string) (res string) { 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 -} +var modregex = regexp.MustCompile(`module ([^\s]*)`) diff --git a/vendor/github.com/99designs/gqlgen/internal/code/packages.go b/vendor/github.com/99designs/gqlgen/internal/code/packages.go new file mode 100644 index 000000000..b14c45ad2 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/internal/code/packages.go @@ -0,0 +1,173 @@ +package code + +import ( + "bytes" + "path/filepath" + + "github.com/pkg/errors" + "golang.org/x/tools/go/packages" +) + +var mode = packages.NeedName | + packages.NeedFiles | + packages.NeedImports | + packages.NeedTypes | + packages.NeedSyntax | + packages.NeedTypesInfo + +// Packages is a wrapper around x/tools/go/packages that maintains a (hopefully prewarmed) cache of packages +// that can be invalidated as writes are made and packages are known to change. +type Packages struct { + packages map[string]*packages.Package + importToName map[string]string + loadErrors []error + + numLoadCalls int // stupid test steam. ignore. + numNameCalls int // stupid test steam. ignore. +} + +// LoadAll will call packages.Load and return the package data for the given packages, +// but if the package already have been loaded it will return cached values instead. +func (p *Packages) LoadAll(importPaths ...string) []*packages.Package { + if p.packages == nil { + p.packages = map[string]*packages.Package{} + } + + missing := make([]string, 0, len(importPaths)) + for _, path := range importPaths { + if _, ok := p.packages[path]; ok { + continue + } + missing = append(missing, path) + } + + if len(missing) > 0 { + p.numLoadCalls++ + pkgs, err := packages.Load(&packages.Config{Mode: mode}, missing...) + if err != nil { + p.loadErrors = append(p.loadErrors, err) + } + + for _, pkg := range pkgs { + p.addToCache(pkg) + } + } + + res := make([]*packages.Package, 0, len(importPaths)) + for _, path := range importPaths { + res = append(res, p.packages[NormalizeVendor(path)]) + } + return res +} + +func (p *Packages) addToCache(pkg *packages.Package) { + imp := NormalizeVendor(pkg.PkgPath) + p.packages[imp] = pkg + for _, imp := range pkg.Imports { + if _, found := p.packages[NormalizeVendor(imp.PkgPath)]; !found { + p.addToCache(imp) + } + } +} + +// Load works the same as LoadAll, except a single package at a time. +func (p *Packages) Load(importPath string) *packages.Package { + pkgs := p.LoadAll(importPath) + if len(pkgs) == 0 { + return nil + } + return pkgs[0] +} + +// LoadWithTypes tries a standard load, which may not have enough type info (TypesInfo== nil) available if the imported package is a +// second order dependency. Fortunately this doesnt happen very often, so we can just issue a load when we detect it. +func (p *Packages) LoadWithTypes(importPath string) *packages.Package { + pkg := p.Load(importPath) + if pkg == nil || pkg.TypesInfo == nil { + p.numLoadCalls++ + pkgs, err := packages.Load(&packages.Config{Mode: mode}, importPath) + if err != nil { + p.loadErrors = append(p.loadErrors, err) + return nil + } + p.addToCache(pkgs[0]) + pkg = pkgs[0] + } + return pkg +} + +// NameForPackage looks up the package name from the package stanza in the go files at the given import path. +func (p *Packages) NameForPackage(importPath string) string { + if importPath == "" { + panic(errors.New("import path can not be empty")) + } + if p.importToName == nil { + p.importToName = map[string]string{} + } + + importPath = NormalizeVendor(importPath) + + // if its in the name cache use it + if name := p.importToName[importPath]; name != "" { + return name + } + + // otherwise we might have already loaded the full package data for it cached + pkg := p.packages[importPath] + + if pkg == nil { + // otherwise do a name only lookup for it but dont put it in the package cache. + p.numNameCalls++ + pkgs, err := packages.Load(&packages.Config{Mode: packages.NeedName}, importPath) + if err != nil { + p.loadErrors = append(p.loadErrors, err) + } else { + pkg = pkgs[0] + } + } + + if pkg == nil || pkg.Name == "" { + return SanitizePackageName(filepath.Base(importPath)) + } + + p.importToName[importPath] = pkg.Name + + return pkg.Name +} + +// Evict removes a given package import path from the cache, along with any packages that depend on it. Further calls +// to Load will fetch it from disk. +func (p *Packages) Evict(importPath string) { + delete(p.packages, importPath) + + for _, pkg := range p.packages { + for _, imported := range pkg.Imports { + if imported.PkgPath == importPath { + p.Evict(pkg.PkgPath) + } + } + } +} + +// Errors returns any errors that were returned by Load, either from the call itself or any of the loaded packages. +func (p *Packages) Errors() PkgErrors { + var res []error //nolint:prealloc + res = append(res, p.loadErrors...) + for _, pkg := range p.packages { + for _, err := range pkg.Errors { + res = append(res, err) + } + } + return res +} + +type PkgErrors []error + +func (p PkgErrors) Error() string { + var b bytes.Buffer + b.WriteString("packages.Load: ") + for _, e := range p { + b.WriteString(e.Error() + "\n") + } + return b.String() +} diff --git a/vendor/github.com/99designs/gqlgen/internal/code/util.go b/vendor/github.com/99designs/gqlgen/internal/code/util.go index 2be83a23c..cbe40858e 100644 --- a/vendor/github.com/99designs/gqlgen/internal/code/util.go +++ b/vendor/github.com/99designs/gqlgen/internal/code/util.go @@ -41,6 +41,11 @@ func NormalizeVendor(pkg string) string { func QualifyPackagePath(importPath string) string { wd, _ := os.Getwd() + // in go module mode, the import path doesn't need fixing + if _, ok := goModuleRoot(wd); ok { + return importPath + } + pkg, err := build.Import(importPath, wd, 0) if err != nil { return importPath diff --git a/vendor/github.com/99designs/gqlgen/internal/imports/prune.go b/vendor/github.com/99designs/gqlgen/internal/imports/prune.go index d678870ef..d42a41579 100644 --- a/vendor/github.com/99designs/gqlgen/internal/imports/prune.go +++ b/vendor/github.com/99designs/gqlgen/internal/imports/prune.go @@ -24,7 +24,7 @@ func (fn visitFn) Visit(node ast.Node) ast.Visitor { } // Prune removes any unused imports -func Prune(filename string, src []byte) ([]byte, error) { +func Prune(filename string, src []byte, packages *code.Packages) ([]byte, error) { fset := token.NewFileSet() file, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.AllErrors) @@ -32,10 +32,7 @@ func Prune(filename string, src []byte) ([]byte, error) { return nil, err } - unused, err := getUnusedImports(file, filename) - if err != nil { - return nil, err - } + unused := getUnusedImports(file, packages) for ipath, name := range unused { astutil.DeleteNamedImport(fset, file, name, ipath) } @@ -49,7 +46,7 @@ func Prune(filename string, src []byte) ([]byte, error) { 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) { +func getUnusedImports(file ast.Node, packages *code.Packages) map[string]string { imported := map[string]*ast.ImportSpec{} used := map[string]bool{} @@ -68,7 +65,7 @@ func getUnusedImports(file ast.Node, filename string) (map[string]string, error) break } - local := code.NameForPackage(ipath) + local := packages.NameForPackage(ipath) imported[local] = v case *ast.SelectorExpr: @@ -99,5 +96,5 @@ func getUnusedImports(file ast.Node, filename string) (map[string]string, error) } } - return unusedImport, nil + return unusedImport } diff --git a/vendor/github.com/99designs/gqlgen/internal/rewrite/rewriter.go b/vendor/github.com/99designs/gqlgen/internal/rewrite/rewriter.go new file mode 100644 index 000000000..1b9adb171 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/internal/rewrite/rewriter.go @@ -0,0 +1,195 @@ +package rewrite + +import ( + "bytes" + "fmt" + "go/ast" + "go/token" + "io/ioutil" + "path/filepath" + "strconv" + "strings" + + "github.com/99designs/gqlgen/internal/code" + "golang.org/x/tools/go/packages" +) + +type Rewriter struct { + pkg *packages.Package + files map[string]string + copied map[ast.Decl]bool +} + +func New(dir string) (*Rewriter, error) { + importPath := code.ImportPathForDir(dir) + if importPath == "" { + return nil, fmt.Errorf("import path not found for directory: %q", dir) + } + pkgs, err := packages.Load(&packages.Config{ + Mode: packages.NeedSyntax | packages.NeedTypes, + }, importPath) + if err != nil { + return nil, err + } + if len(pkgs) == 0 { + return nil, fmt.Errorf("package not found for importPath: %s", importPath) + } + + return &Rewriter{ + pkg: pkgs[0], + files: map[string]string{}, + copied: map[ast.Decl]bool{}, + }, nil +} + +func (r *Rewriter) getSource(start, end token.Pos) string { + startPos := r.pkg.Fset.Position(start) + endPos := r.pkg.Fset.Position(end) + + if startPos.Filename != endPos.Filename { + panic("cant get source spanning multiple files") + } + + file := r.getFile(startPos.Filename) + return file[startPos.Offset:endPos.Offset] +} + +func (r *Rewriter) getFile(filename string) string { + if _, ok := r.files[filename]; !ok { + b, err := ioutil.ReadFile(filename) + if err != nil { + panic(fmt.Errorf("unable to load file, already exists: %s", err.Error())) + } + + r.files[filename] = string(b) + + } + + return r.files[filename] +} + +func (r *Rewriter) GetMethodBody(structname string, methodname string) string { + for _, f := range r.pkg.Syntax { + for _, d := range f.Decls { + d, isFunc := d.(*ast.FuncDecl) + if !isFunc { + continue + } + if d.Name.Name != methodname { + continue + } + if d.Recv == nil || len(d.Recv.List) == 0 { + continue + } + recv := d.Recv.List[0].Type + if star, isStar := recv.(*ast.StarExpr); isStar { + recv = star.X + } + ident, ok := recv.(*ast.Ident) + if !ok { + continue + } + + if ident.Name != structname { + continue + } + + r.copied[d] = true + + return r.getSource(d.Body.Pos()+1, d.Body.End()-1) + } + } + + return "" +} + +func (r *Rewriter) MarkStructCopied(name string) { + for _, f := range r.pkg.Syntax { + for _, d := range f.Decls { + d, isGen := d.(*ast.GenDecl) + if !isGen { + continue + } + if d.Tok != token.TYPE || len(d.Specs) == 0 { + continue + } + + spec, isTypeSpec := d.Specs[0].(*ast.TypeSpec) + if !isTypeSpec { + continue + } + + if spec.Name.Name != name { + continue + } + + r.copied[d] = true + } + } +} + +func (r *Rewriter) ExistingImports(filename string) []Import { + filename, err := filepath.Abs(filename) + if err != nil { + panic(err) + } + for _, f := range r.pkg.Syntax { + pos := r.pkg.Fset.Position(f.Pos()) + + if filename != pos.Filename { + continue + } + + var imps []Import + for _, i := range f.Imports { + name := "" + if i.Name != nil { + name = i.Name.Name + } + path, err := strconv.Unquote(i.Path.Value) + if err != nil { + panic(err) + } + imps = append(imps, Import{name, path}) + } + return imps + } + return nil +} + +func (r *Rewriter) RemainingSource(filename string) string { + filename, err := filepath.Abs(filename) + if err != nil { + panic(err) + } + for _, f := range r.pkg.Syntax { + pos := r.pkg.Fset.Position(f.Pos()) + + if filename != pos.Filename { + continue + } + + var buf bytes.Buffer + + for _, d := range f.Decls { + if r.copied[d] { + continue + } + + if d, isGen := d.(*ast.GenDecl); isGen && d.Tok == token.IMPORT { + continue + } + + buf.WriteString(r.getSource(d.Pos(), d.End())) + buf.WriteString("\n") + } + + return strings.TrimSpace(buf.String()) + } + return "" +} + +type Import struct { + Alias string + ImportPath string +} diff --git a/vendor/github.com/99designs/gqlgen/plugin/federation/federation.go b/vendor/github.com/99designs/gqlgen/plugin/federation/federation.go new file mode 100644 index 000000000..7d9abc977 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/plugin/federation/federation.go @@ -0,0 +1,311 @@ +package federation + +import ( + "fmt" + "sort" + "strings" + + "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/codegen" + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/codegen/templates" + "github.com/99designs/gqlgen/plugin" +) + +type federation struct { + Entities []*Entity +} + +// New returns a federation plugin that injects +// federated directives and types into the schema +func New() plugin.Plugin { + return &federation{} +} + +// Name returns the plugin name +func (f *federation) Name() string { + return "federation" +} + +// MutateConfig mutates the configuration +func (f *federation) MutateConfig(cfg *config.Config) error { + builtins := config.TypeMap{ + "_Service": { + Model: config.StringList{ + "github.com/99designs/gqlgen/plugin/federation/fedruntime.Service", + }, + }, + "_Entity": { + Model: config.StringList{ + "github.com/99designs/gqlgen/plugin/federation/fedruntime.Entity", + }, + }, + "Entity": { + Model: config.StringList{ + "github.com/99designs/gqlgen/plugin/federation/fedruntime.Entity", + }, + }, + "_Any": { + Model: config.StringList{"github.com/99designs/gqlgen/graphql.Map"}, + }, + } + for typeName, entry := range builtins { + if cfg.Models.Exists(typeName) { + return fmt.Errorf("%v already exists which must be reserved when Federation is enabled", typeName) + } + cfg.Models[typeName] = entry + } + cfg.Directives["external"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["requires"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["provides"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["key"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["extends"] = config.DirectiveConfig{SkipRuntime: true} + + return nil +} + +func (f *federation) InjectSourceEarly() *ast.Source { + return &ast.Source{ + Name: "federation/directives.graphql", + Input: ` +scalar _Any +scalar _FieldSet + +directive @external on FIELD_DEFINITION +directive @requires(fields: _FieldSet!) on FIELD_DEFINITION +directive @provides(fields: _FieldSet!) on FIELD_DEFINITION +directive @key(fields: _FieldSet!) on OBJECT | INTERFACE +directive @extends on OBJECT +`, + BuiltIn: true, + } +} + +// InjectSources creates a GraphQL Entity type with all +// the fields that had the @key directive +func (f *federation) InjectSourceLate(schema *ast.Schema) *ast.Source { + f.setEntities(schema) + + entities := "" + resolvers := "" + for i, e := range f.Entities { + if i != 0 { + entities += " | " + } + entities += e.Name + + if e.ResolverName != "" { + resolverArgs := "" + for _, field := range e.KeyFields { + resolverArgs += fmt.Sprintf("%s: %s,", field.Field.Name, field.Field.Type.String()) + } + resolvers += fmt.Sprintf("\t%s(%s): %s!\n", e.ResolverName, resolverArgs, e.Def.Name) + } + + } + + if len(f.Entities) == 0 { + // It's unusual for a service not to have any entities, but + // possible if it only exports top-level queries and mutations. + return nil + } + + // resolvers can be empty if a service defines only "empty + // extend" types. This should be rare. + if resolvers != "" { + resolvers = ` +# fake type to build resolver interfaces for users to implement +type Entity { + ` + resolvers + ` +} +` + } + + return &ast.Source{ + Name: "federation/entity.graphql", + BuiltIn: true, + Input: ` +# a union of all types that use the @key directive +union _Entity = ` + entities + ` +` + resolvers + ` +type _Service { + sdl: String +} + +extend type Query { + _entities(representations: [_Any!]!): [_Entity]! + _service: _Service! +} +`, + } +} + +// Entity represents a federated type +// that was declared in the GQL schema. +type Entity struct { + Name string // The same name as the type declaration + KeyFields []*KeyField // The fields declared in @key. + ResolverName string // The resolver name, such as FindUserByID + Def *ast.Definition + Requires []*Requires +} + +type KeyField struct { + Field *ast.FieldDefinition + TypeReference *config.TypeReference // The Go representation of that field type +} + +// Requires represents an @requires clause +type Requires struct { + Name string // the name of the field + Fields []*RequireField // the name of the sibling fields +} + +// RequireField is similar to an entity but it is a field not +// an object +type RequireField struct { + Name string // The same name as the type declaration + NameGo string // The Go struct field name + TypeReference *config.TypeReference // The Go representation of that field type +} + +func (e *Entity) allFieldsAreExternal() bool { + for _, field := range e.Def.Fields { + if field.Directives.ForName("external") == nil { + return false + } + } + return true +} + +func (f *federation) GenerateCode(data *codegen.Data) error { + if len(f.Entities) > 0 { + if data.Objects.ByName("Entity") != nil { + data.Objects.ByName("Entity").Root = true + } + for _, e := range f.Entities { + obj := data.Objects.ByName(e.Def.Name) + for _, field := range obj.Fields { + // Storing key fields in a slice rather than a map + // to preserve insertion order at the tradeoff of higher + // lookup complexity. + keyField := f.getKeyField(e.KeyFields, field.Name) + if keyField != nil { + keyField.TypeReference = field.TypeReference + } + for _, r := range e.Requires { + for _, rf := range r.Fields { + if rf.Name == field.Name { + rf.TypeReference = field.TypeReference + rf.NameGo = field.GoFieldName + } + } + } + } + } + } + + return templates.Render(templates.Options{ + PackageName: data.Config.Federation.Package, + Filename: data.Config.Federation.Filename, + Data: f, + GeneratedHeader: true, + Packages: data.Config.Packages, + }) +} + +func (f *federation) getKeyField(keyFields []*KeyField, fieldName string) *KeyField { + for _, field := range keyFields { + if field.Field.Name == fieldName { + return field + } + } + return nil +} + +func (f *federation) setEntities(schema *ast.Schema) { + for _, schemaType := range schema.Types { + if schemaType.Kind == ast.Object { + dir := schemaType.Directives.ForName("key") // TODO: interfaces + if dir != nil { + if len(dir.Arguments) > 1 { + panic("Multiple arguments are not currently supported in @key declaration.") + } + fieldName := dir.Arguments[0].Value.Raw // TODO: multiple arguments + if strings.Contains(fieldName, "{") { + panic("Nested fields are not currently supported in @key declaration.") + } + + requires := []*Requires{} + for _, f := range schemaType.Fields { + dir := f.Directives.ForName("requires") + if dir == nil { + continue + } + fields := strings.Split(dir.Arguments[0].Value.Raw, " ") + requireFields := []*RequireField{} + for _, f := range fields { + requireFields = append(requireFields, &RequireField{ + Name: f, + }) + } + requires = append(requires, &Requires{ + Name: f.Name, + Fields: requireFields, + }) + } + + fieldNames := strings.Split(fieldName, " ") + keyFields := make([]*KeyField, len(fieldNames)) + resolverName := fmt.Sprintf("find%sBy", schemaType.Name) + for i, f := range fieldNames { + field := schemaType.Fields.ForName(f) + + keyFields[i] = &KeyField{Field: field} + if i > 0 { + resolverName += "And" + } + resolverName += templates.ToGo(f) + + } + + e := &Entity{ + Name: schemaType.Name, + KeyFields: keyFields, + Def: schemaType, + ResolverName: resolverName, + Requires: requires, + } + // If our schema has a field with a type defined in + // another service, then we need to define an "empty + // extend" of that type in this service, so this service + // knows what the type is like. But the graphql-server + // will never ask us to actually resolve this "empty + // extend", so we don't require a resolver function for + // it. (Well, it will never ask in practice; it's + // unclear whether the spec guarantees this. See + // https://github.com/apollographql/apollo-server/issues/3852 + // ). Example: + // type MyType { + // myvar: TypeDefinedInOtherService + // } + // // Federation needs this type, but + // // it doesn't need a resolver for it! + // extend TypeDefinedInOtherService @key(fields: "id") { + // id: ID @external + // } + if e.allFieldsAreExternal() { + e.ResolverName = "" + } + + f.Entities = append(f.Entities, e) + } + } + } + + // make sure order remains stable across multiple builds + sort.Slice(f.Entities, func(i, j int) bool { + return f.Entities[i].Name < f.Entities[j].Name + }) +} diff --git a/vendor/github.com/99designs/gqlgen/plugin/federation/federation.gotpl b/vendor/github.com/99designs/gqlgen/plugin/federation/federation.gotpl new file mode 100644 index 000000000..96c25e857 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/plugin/federation/federation.gotpl @@ -0,0 +1,69 @@ +{{ reserveImport "context" }} +{{ reserveImport "errors" }} +{{ reserveImport "fmt" }} +{{ reserveImport "strings" }} + +{{ reserveImport "github.com/99designs/gqlgen/plugin/federation/fedruntime" }} + +func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) { + if ec.DisableIntrospection { + return fedruntime.Service{}, errors.New("federated introspection disabled") + } + + var sdl []string + + for _, src := range sources { + if src.BuiltIn { + continue + } + sdl = append(sdl, src.Input) + } + + return fedruntime.Service{ + SDL: strings.Join(sdl, "\n"), + }, nil +} + +{{if .Entities}} +func (ec *executionContext) __resolve_entities(ctx context.Context, representations []map[string]interface{}) ([]fedruntime.Entity, error) { + list := []fedruntime.Entity{} + for _, rep := range representations { + typeName, ok := rep["__typename"].(string) + if !ok { + return nil, errors.New("__typename must be an existing string") + } + switch typeName { + {{ range .Entities }} + {{ if .ResolverName }} + case "{{.Def.Name}}": + {{ range $i, $keyField := .KeyFields -}} + id{{$i}}, err := ec.{{.TypeReference.UnmarshalFunc}}(ctx, rep["{{$keyField.Field.Name}}"]) + if err != nil { + return nil, errors.New(fmt.Sprintf("Field %s undefined in schema.", "{{$keyField.Field.Name}}")) + } + {{end}} + + entity, err := ec.resolvers.Entity().{{.ResolverName | go}}(ctx, + {{ range $i, $_ := .KeyFields -}} id{{$i}}, {{end}}) + if err != nil { + return nil, err + } + + {{ range .Requires }} + {{ range .Fields}} + entity.{{.NameGo}}, err = ec.{{.TypeReference.UnmarshalFunc}}(ctx, rep["{{.Name}}"]) + if err != nil { + return nil, err + } + {{ end }} + {{ end }} + list = append(list, entity) + {{ end }} + {{ end }} + default: + return nil, errors.New("unknown type: "+typeName) + } + } + return list, nil +} +{{end}} diff --git a/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go b/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go index bb400f1b7..e0ca18663 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go +++ b/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go @@ -7,11 +7,16 @@ import ( "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" + "github.com/vektah/gqlparser/v2/ast" ) +type BuildMutateHook = func(b *ModelBuild) *ModelBuild + +func defaultBuildMutateHook(b *ModelBuild) *ModelBuild { + return b +} + type ModelBuild struct { PackageName string Interfaces []*Interface @@ -51,10 +56,14 @@ type EnumValue struct { } func New() plugin.Plugin { - return &Plugin{} + return &Plugin{ + MutateHook: defaultBuildMutateHook, + } } -type Plugin struct{} +type Plugin struct { + MutateHook BuildMutateHook +} var _ plugin.ConfigMutator = &Plugin{} @@ -63,31 +72,16 @@ func (m *Plugin) Name() string { } 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 - } + binder := cfg.NewBinder() b := &ModelBuild{ PackageName: cfg.Model.Package, } - for _, schemaType := range schema.Types { + for _, schemaType := range cfg.Schema.Types { if cfg.Models.UserDefined(schemaType.Name) { continue } - switch schemaType.Kind { case ast.Interface, ast.Union: it := &Interface{ @@ -97,25 +91,24 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { b.Interfaces = append(b.Interfaces, it) case ast.Object, ast.InputObject: - if schemaType == schema.Query || schemaType == schema.Mutation || schemaType == schema.Subscription { + if schemaType == cfg.Schema.Query || schemaType == cfg.Schema.Mutation || schemaType == cfg.Schema.Subscription { continue } it := &Object{ Description: schemaType.Description, Name: schemaType.Name, } - - for _, implementor := range schema.GetImplements(schemaType) { + for _, implementor := range cfg.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()] + fieldDef := cfg.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) + var err error + typ, err = binder.FindTypeFromName(cfg.Models[field.Type.Name()].Model[0]) if err != nil { return err } @@ -196,7 +189,6 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { 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 }) @@ -214,15 +206,20 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { cfg.Models.Add(it, "github.com/99designs/gqlgen/graphql.String") } - if len(b.Models) == 0 && len(b.Enums) == 0 { + if len(b.Models) == 0 && len(b.Enums) == 0 && len(b.Interfaces) == 0 && len(b.Scalars) == 0 { return nil } + if m.MutateHook != nil { + b = m.MutateHook(b) + } + return templates.Render(templates.Options{ PackageName: cfg.Model.Package, Filename: cfg.Model.Filename, Data: b, GeneratedHeader: true, + Packages: cfg.Packages, }) } diff --git a/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl b/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl index 6df200ee0..e58d5b21a 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl +++ b/vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl @@ -7,8 +7,8 @@ {{ reserveImport "errors" }} {{ reserveImport "bytes" }} -{{ reserveImport "github.com/vektah/gqlparser" }} -{{ reserveImport "github.com/vektah/gqlparser/ast" }} +{{ reserveImport "github.com/vektah/gqlparser/v2" }} +{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }} {{ reserveImport "github.com/99designs/gqlgen/graphql" }} {{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }} @@ -36,7 +36,7 @@ {{- end}} {{ range $enum := .Enums }} - {{ with .Description|go }} {{.|prefixLines "// "}} {{end}} + {{ with .Description }} {{.|prefixLines "// "}} {{end}} type {{.Name|go }} string const ( {{- range $value := .Values}} diff --git a/vendor/github.com/99designs/gqlgen/plugin/plugin.go b/vendor/github.com/99designs/gqlgen/plugin/plugin.go index a84bfd327..7de36bd8c 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/plugin.go +++ b/vendor/github.com/99designs/gqlgen/plugin/plugin.go @@ -5,6 +5,7 @@ package plugin import ( "github.com/99designs/gqlgen/codegen" "github.com/99designs/gqlgen/codegen/config" + "github.com/vektah/gqlparser/v2/ast" ) type Plugin interface { @@ -18,3 +19,13 @@ type ConfigMutator interface { type CodeGenerator interface { GenerateCode(cfg *codegen.Data) error } + +// EarlySourceInjector is used to inject things that are required for user schema files to compile. +type EarlySourceInjector interface { + InjectSourceEarly() *ast.Source +} + +// LateSourceInjector is used to inject more sources, after we have loaded the users schema. +type LateSourceInjector interface { + InjectSourceLate(schema *ast.Schema) *ast.Source +} diff --git a/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go b/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go index 00a6d5c9d..204801efb 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go +++ b/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go @@ -1,11 +1,14 @@ package resolvergen import ( - "log" "os" + "path/filepath" + "strings" "github.com/99designs/gqlgen/codegen" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" + "github.com/99designs/gqlgen/internal/rewrite" "github.com/99designs/gqlgen/plugin" "github.com/pkg/errors" ) @@ -19,35 +22,186 @@ type Plugin struct{} var _ plugin.CodeGenerator = &Plugin{} func (m *Plugin) Name() string { - return "resovlergen" + return "resolvergen" } + func (m *Plugin) GenerateCode(data *codegen.Data) error { if !data.Config.Resolver.IsDefined() { return nil } + switch data.Config.Resolver.Layout { + case config.LayoutSingleFile: + return m.generateSingleFile(data) + case config.LayoutFollowSchema: + return m.generatePerSchema(data) + } + + return nil +} + +func (m *Plugin) generateSingleFile(data *codegen.Data) error { + file := File{} + + if _, err := os.Stat(data.Config.Resolver.Filename); err == nil { + // file already exists and we dont support updating resolvers with layout = single so just return + return nil + } + + for _, o := range data.Objects { + if o.HasResolvers() { + file.Objects = append(file.Objects, o) + } + for _, f := range o.Fields { + if !f.IsResolver { + continue + } + + resolver := Resolver{o, f, `panic("not implemented")`} + file.Resolvers = append(file.Resolvers, &resolver) + } + } + resolverBuild := &ResolverBuild{ - Data: data, + File: &file, PackageName: data.Config.Resolver.Package, ResolverType: data.Config.Resolver.Type, + HasRoot: true, } - filename := data.Config.Resolver.Filename - if _, err := os.Stat(filename); os.IsNotExist(errors.Cause(err)) { - return templates.Render(templates.Options{ + return templates.Render(templates.Options{ + PackageName: data.Config.Resolver.Package, + FileNotice: `// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.`, + Filename: data.Config.Resolver.Filename, + Data: resolverBuild, + Packages: data.Config.Packages, + }) +} + +func (m *Plugin) generatePerSchema(data *codegen.Data) error { + rewriter, err := rewrite.New(data.Config.Resolver.Dir()) + if err != nil { + return err + } + + files := map[string]*File{} + + for _, o := range data.Objects { + if o.HasResolvers() { + fn := gqlToResolverName(data.Config.Resolver.Dir(), o.Position.Src.Name, data.Config.Resolver.FilenameTemplate) + if files[fn] == nil { + files[fn] = &File{} + } + + rewriter.MarkStructCopied(templates.LcFirst(o.Name) + templates.UcFirst(data.Config.Resolver.Type)) + rewriter.GetMethodBody(data.Config.Resolver.Type, o.Name) + files[fn].Objects = append(files[fn].Objects, o) + } + for _, f := range o.Fields { + if !f.IsResolver { + continue + } + + structName := templates.LcFirst(o.Name) + templates.UcFirst(data.Config.Resolver.Type) + implementation := strings.TrimSpace(rewriter.GetMethodBody(structName, f.GoFieldName)) + if implementation == "" { + implementation = `panic(fmt.Errorf("not implemented"))` + } + + resolver := Resolver{o, f, implementation} + fn := gqlToResolverName(data.Config.Resolver.Dir(), f.Position.Src.Name, data.Config.Resolver.FilenameTemplate) + if files[fn] == nil { + files[fn] = &File{} + } + + files[fn].Resolvers = append(files[fn].Resolvers, &resolver) + } + } + + for filename, file := range files { + file.imports = rewriter.ExistingImports(filename) + file.RemainingSource = rewriter.RemainingSource(filename) + } + + for filename, file := range files { + resolverBuild := &ResolverBuild{ + File: file, + PackageName: data.Config.Resolver.Package, + ResolverType: data.Config.Resolver.Type, + } + + err := templates.Render(templates.Options{ PackageName: data.Config.Resolver.Package, - Filename: data.Config.Resolver.Filename, - Data: resolverBuild, + FileNotice: ` + // This file will be automatically regenerated based on the schema, any resolver implementations + // will be copied through when generating and any unknown code will be moved to the end.`, + Filename: filename, + Data: resolverBuild, + Packages: data.Config.Packages, }) + if err != nil { + return err + } } - log.Printf("Skipped resolver: %s already exists\n", filename) + if _, err := os.Stat(data.Config.Resolver.Filename); os.IsNotExist(errors.Cause(err)) { + err := templates.Render(templates.Options{ + PackageName: data.Config.Resolver.Package, + FileNotice: ` + // This file will not be regenerated automatically. + // + // It serves as dependency injection for your app, add any dependencies you require here.`, + Template: `type {{.}} struct {}`, + Filename: data.Config.Resolver.Filename, + Data: data.Config.Resolver.Type, + Packages: data.Config.Packages, + }) + if err != nil { + return err + } + } return nil } type ResolverBuild struct { - *codegen.Data - + *File + HasRoot bool PackageName string ResolverType string } + +type File struct { + // These are separated because the type definition of the resolver object may live in a different file from the + //resolver method implementations, for example when extending a type in a different graphql schema file + Objects []*codegen.Object + Resolvers []*Resolver + imports []rewrite.Import + RemainingSource string +} + +func (f *File) Imports() string { + for _, imp := range f.imports { + if imp.Alias == "" { + _, _ = templates.CurrentImports.Reserve(imp.ImportPath) + } else { + _, _ = templates.CurrentImports.Reserve(imp.ImportPath, imp.Alias) + } + } + return "" +} + +type Resolver struct { + Object *codegen.Object + Field *codegen.Field + Implementation string +} + +func gqlToResolverName(base string, gqlname, filenameTmpl string) string { + gqlname = filepath.Base(gqlname) + ext := filepath.Ext(gqlname) + if filenameTmpl == "" { + filenameTmpl = "{name}.resolvers.go" + } + filename := strings.ReplaceAll(filenameTmpl, "{name}", strings.TrimSuffix(gqlname, ext)) + return filepath.Join(base, filename) +} diff --git a/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl b/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl index 7d95e6903..543bf136e 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl +++ b/vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl @@ -1,5 +1,3 @@ -// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES. - {{ reserveImport "context" }} {{ reserveImport "fmt" }} {{ reserveImport "io" }} @@ -9,32 +7,39 @@ {{ reserveImport "errors" }} {{ reserveImport "bytes" }} -{{ reserveImport "github.com/99designs/gqlgen/handler" }} -{{ reserveImport "github.com/vektah/gqlparser" }} -{{ reserveImport "github.com/vektah/gqlparser/ast" }} +{{ reserveImport "github.com/vektah/gqlparser/v2" }} +{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }} {{ reserveImport "github.com/99designs/gqlgen/graphql" }} {{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }} -type {{.ResolverType}} struct {} +{{ .Imports }} + +{{ if .HasRoot }} + type {{.ResolverType}} struct {} +{{ end }} + +{{ range $resolver := .Resolvers -}} + func (r *{{lcFirst $resolver.Object.Name}}{{ucFirst $.ResolverType}}) {{$resolver.Field.GoFieldName}}{{ $resolver.Field.ShortResolverDeclaration }} { + {{ $resolver.Implementation }} + } -{{ 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 -}} + // {{$object.Name}} returns {{ $object.ResolverInterface | ref }} implementation. + func (r *{{$.ResolverType}}) {{$object.Name}}() {{ $object.ResolverInterface | ref }} { return &{{lcFirst $object.Name}}{{ucFirst $.ResolverType}}{r} } +{{ end }} + +{{ range $object := .Objects -}} + type {{lcFirst $object.Name}}{{ucFirst $.ResolverType}} struct { *{{$.ResolverType}} } +{{ end }} + +{{ if (ne .RemainingSource "") }} + // !!! WARNING !!! + // The code below was going to be deleted when updating resolvers. It has been copied here so you have + // one last chance to move it out of harms way if you want. There are two reasons this happens: + // - When renaming or deleting a resolver the old code will be put in here. You can safely delete + // it when you're done. + // - You have helper methods in this file. Move them out to keep these resolver files clean. + {{ .RemainingSource }} {{ end }} diff --git a/vendor/github.com/99designs/gqlgen/plugin/servergen/server.go b/vendor/github.com/99designs/gqlgen/plugin/servergen/server.go index 22289c025..029c9ae39 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/servergen/server.go +++ b/vendor/github.com/99designs/gqlgen/plugin/servergen/server.go @@ -34,6 +34,7 @@ func (m *Plugin) GenerateCode(data *codegen.Data) error { PackageName: "main", Filename: m.filename, Data: serverBuild, + Packages: data.Config.Packages, }) } diff --git a/vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl b/vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl index fca71c53c..a3ae2a877 100644 --- a/vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl +++ b/vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl @@ -2,7 +2,8 @@ {{ reserveImport "log" }} {{ reserveImport "net/http" }} {{ reserveImport "os" }} -{{ reserveImport "github.com/99designs/gqlgen/handler" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql/playground" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql/handler" }} const defaultPort = "8080" @@ -12,8 +13,10 @@ func main() { port = defaultPort } - http.Handle("/", handler.Playground("GraphQL playground", "/query")) - http.Handle("/query", handler.GraphQL({{ lookupImport .ExecPackageName }}.NewExecutableSchema({{ lookupImport .ExecPackageName}}.Config{Resolvers: &{{ lookupImport .ResolverPackageName}}.Resolver{}}))) + srv := handler.NewDefaultServer({{ lookupImport .ExecPackageName }}.NewExecutableSchema({{ lookupImport .ExecPackageName}}.Config{Resolvers: &{{ lookupImport .ResolverPackageName}}.Resolver{}})) + + http.Handle("/", playground.Handler("GraphQL playground", "/query")) + http.Handle("/query", srv) log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) log.Fatal(http.ListenAndServe(":" + port, nil)) diff --git a/vendor/github.com/99designs/gqlgen/tools.go b/vendor/github.com/99designs/gqlgen/tools.go index 912fc0d63..e63a71a80 100644 --- a/vendor/github.com/99designs/gqlgen/tools.go +++ b/vendor/github.com/99designs/gqlgen/tools.go @@ -2,4 +2,7 @@ package main -import _ "github.com/vektah/dataloaden" +import ( + _ "github.com/matryer/moq" + _ "github.com/vektah/dataloaden" +) diff --git a/vendor/github.com/Yamashou/gqlgenc/.gitignore b/vendor/github.com/Yamashou/gqlgenc/.gitignore new file mode 100644 index 000000000..15b3e741f --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/.gitignore @@ -0,0 +1,7 @@ +/.gqlgenc.yml +/models_gen.go +/**/.graphqlconfig +/schema.graphql +/client.go +/query/ +/.idea/ diff --git a/vendor/github.com/Yamashou/gqlgenc/.golangci.yml b/vendor/github.com/Yamashou/gqlgenc/.golangci.yml new file mode 100644 index 000000000..941fe3034 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/.golangci.yml @@ -0,0 +1,65 @@ +# See https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml +run: +linters-settings: + govet: + enable-all: true + disable: + - shadow + unused: + check-exported: true + unparam: + check-exported: true + varcheck: + exported-fields: true + structcheck: + exported-fields: true + nakedret: + max-func-lines: 1 + +linters: + enable-all: true + disable: + - testpackage + - nestif + - godot + - wsl + - lll + - dupl + - funlen + - gochecknoinits + - gochecknoglobals + - godox + - maligned + - gocognit + - gocyclo + - interfacer + - gomnd + - goerr113 + fast: false + +issues: + exclude-rules: + # Test + - path: _test\.go + text: "Using the variable on range scope `tt` in function literal" + linters: + - scopelint + - path: _test\.go + linters: + - unused + - structcheck + - path: introspection/type.go + linters: + - structcheck # These types fits IntrospectionQuery + - path: config/config.go + text: "`Query` is unused" # used in main.go + linters: + - structcheck + - path: graphqljson/graphql.go + text: "`Extensions` is unused" # used in line 48 + linters: + - structcheck + - path: introspection/query.go + text: "`Introspection` is unused" # used in config/config.go + linters: + - varcheck diff --git a/vendor/github.com/Yamashou/gqlgenc/LICENSE b/vendor/github.com/Yamashou/gqlgenc/LICENSE new file mode 100644 index 000000000..e16053d8f --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Yamashou + +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. diff --git a/vendor/github.com/Yamashou/gqlgenc/Makefile b/vendor/github.com/Yamashou/gqlgenc/Makefile new file mode 100644 index 000000000..453c30b40 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/Makefile @@ -0,0 +1,10 @@ +MAKEFLAGS=--no-builtin-rules --no-builtin-variables --always-make + +fmt: + gofumports -local github.com/Yamashou/gqlgenc -w . + +lint: + golangci-lint run + +test: + go test -v ./... diff --git a/vendor/github.com/Yamashou/gqlgenc/README.md b/vendor/github.com/Yamashou/gqlgenc/README.md new file mode 100644 index 000000000..598017976 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/README.md @@ -0,0 +1,118 @@ +# gqlgenc + +## What is gqlgenc ? + +This is Go library for building GraphQL client with [gqlgen](https://github.com/99designs/gqlgen) + +## Motivation + +Now, if you build GraphQL api client for Go, have choice: + + - [github.com/shurcooL/graphql](https://github.com/shurcooL/graphql) + - [github.com/machinebox/graphql](https://github.com/machinebox/graphql) + +These libraries are very simple and easy to handle. +However, as I work with [gqlgen](https://github.com/99designs/gqlgen) and [graphql-code-generator](https://graphql-code-generator.com/) every day, I find out the beauty of automatic generation. +So I want to automatically generate types. + +## Installation + +```shell script +go get -u github.com/Yamashou/gqlgenc +``` + +## How to use + +### Client Codes Only + +gqlgenc base is gqlgen with [plugins](https://gqlgen.com/reference/plugins/). So the setting is yaml in each format. +gqlgenc can be configured using a .gqlgenc.yml file, + +```yaml + +model: + package: generated + filename: ./models_gen.go # https://github.com/99designs/gqlgen/tree/master/plugin/modelgen +client: + package: generated + filename: ./client.go # Where should any generated client go? +models: + Int: + model: github.com/99designs/gqlgen/graphql.Int64 + Date: + model: github.com/99designs/gqlgen/graphql.Time +endpoint: + url: https://api.annict.com/graphql # Where do you want to send your request? + headers: # If you need header for getting introspection query, set it + Authorization: "Bearer ${ANNICT_KEY}" # support environment variables +query: + - "./query/*.graphql" # Where are all the query files located? +``` + +Execute the following command on same directory for .gqlgenc.yaml + +```shell script +gqlgenc +``` + +### With gqlgen + +Do this when creating a server and client for Go. +You create your own entrypoint for gqlgen. +This use case is very useful for testing your server. + + +```go +package main + +import ( + "fmt" + "os" + + "github.com/Yamashou/gqlgenc/clientgen" + + "github.com/99designs/gqlgen/api" + "github.com/99designs/gqlgen/codegen/config" +) + +func main() { + cfg, err := config.LoadConfigFromDefaultLocations() + if err != nil { + fmt.Fprintln(os.Stderr, "failed to load config", err.Error()) + os.Exit(2) + } + queries := []string{"client.query", "fragemt.query"} + clientPackage := config.PackageConfig{ + Filename: "./client.go", + Package: "gen", + } + + clientPlugin := clientgen.New(queries, clientPackage) + err = api.Generate(cfg, + api.AddPlugin(clientPlugin), + ) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(3) + } +} +``` + +## Documents + +- [How to configure gqlgen using gqlgen.yml](https://gqlgen.com/config/) +- [How to write plugins for gqlgen](https://gqlgen.com/reference/plugins/) + + +## Comments + +### Japanese Comments +These codes have Japanese comments. Replace with English. + +### Subscription + +This client does not support subscription. If you need a subscription, please create an issue or pull request. + +### Pre-conditions + +[clientgen](https://github.com/Yamashou/gqlgenc/tree/master/clientgen) is created based on [modelgen](https://github.com/99designs/gqlgen/tree/master/plugin/modelgen). So if you don't have a modelgen, it may be a mysterious move. diff --git a/vendor/github.com/Yamashou/gqlgenc/client/client.go b/vendor/github.com/Yamashou/gqlgenc/client/client.go new file mode 100644 index 000000000..94cea8971 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/client/client.go @@ -0,0 +1,88 @@ +package client + +import ( + "bytes" + "context" + "encoding/json" + "net/http" + + "github.com/Yamashou/gqlgenc/graphqljson" + "golang.org/x/xerrors" +) + +type HTTPRequestOption func(req *http.Request) + +type Client struct { + Client *http.Client + BaseURL string + HTTPRequestOptions []HTTPRequestOption +} + +// Request represents an outgoing GraphQL request +type Request struct { + Query string `json:"query"` + Variables map[string]interface{} `json:"variables,omitempty"` + OperationName string `json:"operationName,omitempty"` +} + +func NewClient(client *http.Client, baseURL string, options ...HTTPRequestOption) *Client { + return &Client{ + Client: client, + BaseURL: baseURL, + HTTPRequestOptions: options, + } +} + +func (c *Client) newRequest(ctx context.Context, query string, vars map[string]interface{}, httpRequestOptions []HTTPRequestOption) (*http.Request, error) { + r := &Request{ + Query: query, + Variables: vars, + OperationName: "", + } + + requestBody, err := json.Marshal(r) + if err != nil { + return nil, xerrors.Errorf("encode: %w", err) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.BaseURL, bytes.NewBuffer(requestBody)) + if err != nil { + return nil, xerrors.Errorf("create request struct failed: %w", err) + } + + for _, httpRequestOption := range c.HTTPRequestOptions { + httpRequestOption(req) + } + for _, httpRequestOption := range httpRequestOptions { + httpRequestOption(req) + } + + return req, nil +} + +// Post sends a http POST request to the graphql endpoint with the given query then unpacks +// the response into the given object. +func (c *Client) Post(ctx context.Context, query string, respData interface{}, vars map[string]interface{}, httpRequestOptions ...HTTPRequestOption) error { + req, err := c.newRequest(ctx, query, vars, httpRequestOptions) + if err != nil { + return xerrors.Errorf("don't create request: %w", err) + } + req.Header.Set("Content-Type", "application/json; charset=utf-8") + req.Header.Set("Accept", "application/json; charset=utf-8") + + resp, err := c.Client.Do(req) + if err != nil { + return xerrors.Errorf("request failed: %w", err) + } + defer resp.Body.Close() + + if err := graphqljson.Unmarshal(resp.Body, respData); err != nil { + return err + } + + if resp.StatusCode < 200 || 299 < resp.StatusCode { + return xerrors.Errorf("http status code: %v", resp.StatusCode) + } + + return nil +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/client.go b/vendor/github.com/Yamashou/gqlgenc/clientgen/client.go new file mode 100644 index 000000000..d037ccb55 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/client.go @@ -0,0 +1,76 @@ +package clientgen + +import ( + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/plugin" + "golang.org/x/xerrors" +) + +var _ plugin.ConfigMutator = &Plugin{} + +type Plugin struct { + queryFilePaths []string + Client config.PackageConfig +} + +func New(queryFilePaths []string, client config.PackageConfig) *Plugin { + return &Plugin{ + queryFilePaths: queryFilePaths, + Client: client, + } +} + +func (p *Plugin) Name() string { + return "clientgen" +} + +func (p *Plugin) MutateConfig(cfg *config.Config) error { + querySources, err := LoadQuerySources(p.queryFilePaths) + if err != nil { + return xerrors.Errorf("load query sources failed: %w", err) + } + + // 1. 全体のqueryDocumentを1度にparse + // 1. Parse document from source of query + queryDocument, err := ParseQueryDocuments(cfg.Schema, querySources) + if err != nil { + return xerrors.Errorf(": %w", err) + } + + // 2. OperationごとのqueryDocumentを作成 + // 2. Separate documents for each operation + queryDocuments, err := QueryDocumentsByOperations(cfg.Schema, queryDocument.Operations) + if err != nil { + return xerrors.Errorf("parse query document failed: %w", err) + } + + // 3. テンプレートと情報ソースを元にコード生成 + // 3. Generate code from template and document source + sourceGenerator := NewSourceGenerator(cfg, p.Client) + source := NewSource(cfg.Schema, queryDocument, sourceGenerator) + query, err := source.Query() + if err != nil { + return xerrors.Errorf("generating query object: %w", err) + } + + mutation, err := source.Mutation() + if err != nil { + return xerrors.Errorf("generating mutation object: %w", err) + } + + fragments, err := source.Fragments() + if err != nil { + return xerrors.Errorf("generating fragment failed: %w", err) + } + + operationResponses, err := source.OperationResponses() + if err != nil { + return xerrors.Errorf("generating operation response failed: %w", err) + } + + if err := RenderTemplate(cfg, query, mutation, fragments, source.Operations(queryDocuments), operationResponses, p.Client); err != nil { + return xerrors.Errorf("template failed: %w", err) + } + + return nil +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/query.go b/vendor/github.com/Yamashou/gqlgenc/clientgen/query.go new file mode 100644 index 000000000..ea99bc5c6 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/query.go @@ -0,0 +1,93 @@ +package clientgen + +import ( + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/parser" + "github.com/vektah/gqlparser/v2/validator" + "golang.org/x/xerrors" +) + +func ParseQueryDocuments(schema *ast.Schema, querySources []*ast.Source) (*ast.QueryDocument, error) { + var queryDocument ast.QueryDocument + for _, querySource := range querySources { + query, gqlerr := parser.ParseQuery(querySource) + if gqlerr != nil { + return nil, xerrors.Errorf(": %w", gqlerr) + } + + mergeQueryDocument(&queryDocument, query) + } + + if errs := validator.Validate(schema, &queryDocument); errs != nil { + return nil, xerrors.Errorf(": %w", errs) + } + + return &queryDocument, nil +} + +func mergeQueryDocument(q, other *ast.QueryDocument) { + q.Operations = append(q.Operations, other.Operations...) + q.Fragments = append(q.Fragments, other.Fragments...) +} + +func QueryDocumentsByOperations(schema *ast.Schema, operations ast.OperationList) ([]*ast.QueryDocument, error) { + queryDocuments := make([]*ast.QueryDocument, 0, len(operations)) + for _, operation := range operations { + fragments := fragmentsInOperationDefinition(operation) + + queryDocument := &ast.QueryDocument{ + Operations: ast.OperationList{operation}, + Fragments: fragments, + Position: nil, + } + + if errs := validator.Validate(schema, queryDocument); errs != nil { + return nil, xerrors.Errorf(": %w", errs) + } + + queryDocuments = append(queryDocuments, queryDocument) + } + + return queryDocuments, nil +} + +func fragmentsInOperationDefinition(operation *ast.OperationDefinition) ast.FragmentDefinitionList { + fragments := fragmentsInOperationWalker(operation.SelectionSet) + uniqueFragments := fragmentsUnique(fragments) + + return uniqueFragments +} + +func fragmentsUnique(fragments ast.FragmentDefinitionList) ast.FragmentDefinitionList { + uniqueMap := make(map[string]*ast.FragmentDefinition) + for _, fragment := range fragments { + uniqueMap[fragment.Name] = fragment + } + + uniqueFragments := make(ast.FragmentDefinitionList, 0, len(uniqueMap)) + for _, fragment := range uniqueMap { + uniqueFragments = append(uniqueFragments, fragment) + } + + return uniqueFragments +} + +func fragmentsInOperationWalker(selectionSet ast.SelectionSet) ast.FragmentDefinitionList { + var fragments ast.FragmentDefinitionList + for _, selection := range selectionSet { + var selectionSet ast.SelectionSet + switch selection := selection.(type) { + case *ast.Field: + selectionSet = selection.SelectionSet + case *ast.InlineFragment: + selectionSet = selection.SelectionSet + case *ast.FragmentSpread: + fragments = append(fragments, selection.Definition) + selectionSet = selection.Definition.SelectionSet + } + + fragments = append(fragments, fragmentsInOperationWalker(selectionSet)...) + } + + return fragments +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go b/vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go new file mode 100644 index 000000000..946b744c0 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go @@ -0,0 +1,106 @@ +/* +Copyright (c) 2020 gqlgen authors + +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. +*/ + +package clientgen + +import ( + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/99designs/gqlgen/codegen/config" + "github.com/vektah/gqlparser/v2/ast" + "golang.org/x/xerrors" +) + +var path2regex = strings.NewReplacer( + `.`, `\.`, + `*`, `.+`, + `\`, `[\\/]`, + `/`, `[\\/]`, +) + +// LoadQuerySourceなどは、gqlgenがLoadConfigでSchemaを読み込む時の実装をコピーして一部修正している +// **/test/*.graphqlなどに対応している +func LoadQuerySources(queryFileNames []string) ([]*ast.Source, error) { + var noGlobQueryFileNames config.StringList + + var err error + preGlobbing := queryFileNames + for _, f := range preGlobbing { + var matches []string + + // for ** we want to override default globbing patterns and walk all + // subdirectories to match schema files. + if strings.Contains(f, "**") { + pathParts := strings.SplitN(f, "**", 2) + rest := strings.TrimPrefix(strings.TrimPrefix(pathParts[1], `\`), `/`) + // turn the rest of the glob into a regex, anchored only at the end because ** allows + // for any number of dirs in between and walk will let us match against the full path name + globRe := regexp.MustCompile(path2regex.Replace(rest) + `$`) + + if err := filepath.Walk(pathParts[0], func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if globRe.MatchString(strings.TrimPrefix(path, pathParts[0])) { + matches = append(matches, path) + } + + return nil + }); err != nil { + return nil, xerrors.Errorf("failed to walk schema at root: %w", pathParts[0]) + } + } else { + matches, err = filepath.Glob(f) + if err != nil { + return nil, xerrors.Errorf("failed to glob schema filename %v: %w", f, err) + } + } + + for _, m := range matches { + if noGlobQueryFileNames.Has(m) { + continue + } + + noGlobQueryFileNames = append(noGlobQueryFileNames, m) + } + } + + querySources := make([]*ast.Source, 0, len(noGlobQueryFileNames)) + for _, filename := range noGlobQueryFileNames { + filename = filepath.ToSlash(filename) + var err error + var schemaRaw []byte + schemaRaw, err = ioutil.ReadFile(filename) + if err != nil { + return nil, xerrors.Errorf("unable to open schema: %w", err) + } + + querySources = append(querySources, &ast.Source{Name: filename, Input: string(schemaRaw)}) + } + + return querySources, nil +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/source.go b/vendor/github.com/Yamashou/gqlgenc/clientgen/source.go new file mode 100644 index 000000000..534d94416 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/source.go @@ -0,0 +1,193 @@ +package clientgen + +import ( + "bytes" + "fmt" + "go/types" + + "github.com/99designs/gqlgen/codegen/templates" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/formatter" + "golang.org/x/xerrors" +) + +type Source struct { + schema *ast.Schema + queryDocument *ast.QueryDocument + sourceGenerator *SourceGenerator +} + +func NewSource(schema *ast.Schema, queryDocument *ast.QueryDocument, sourceGenerator *SourceGenerator) *Source { + return &Source{ + schema: schema, + queryDocument: queryDocument, + sourceGenerator: sourceGenerator, + } +} + +type Fragment struct { + Name string + Type types.Type +} + +func (s *Source) Fragments() ([]*Fragment, error) { + fragments := make([]*Fragment, 0, len(s.queryDocument.Fragments)) + for _, fragment := range s.queryDocument.Fragments { + responseFields := s.sourceGenerator.NewResponseFields(fragment.SelectionSet) + if s.sourceGenerator.cfg.Models.Exists(fragment.Name) { + return nil, xerrors.New(fmt.Sprintf("%s is duplicated", fragment.Name)) + } + + fragment := &Fragment{ + Name: fragment.Name, + Type: responseFields.StructType(), + } + + fragments = append(fragments, fragment) + } + + for _, fragment := range fragments { + name := fragment.Name + s.sourceGenerator.cfg.Models.Add( + name, + fmt.Sprintf("%s.%s", s.sourceGenerator.client.Pkg(), templates.ToGo(name)), + ) + } + + return fragments, nil +} + +type Operation struct { + Name string + ResponseStructName string + Operation string + Args []*Argument + VariableDefinitions ast.VariableDefinitionList +} + +func NewOperation(operation *ast.OperationDefinition, queryDocument *ast.QueryDocument, args []*Argument) *Operation { + return &Operation{ + Name: operation.Name, + ResponseStructName: getResponseStructName(operation), + Operation: queryString(queryDocument), + Args: args, + VariableDefinitions: operation.VariableDefinitions, + } +} + +func (s *Source) Operations(queryDocuments []*ast.QueryDocument) []*Operation { + operations := make([]*Operation, 0, len(s.queryDocument.Operations)) + + queryDocumentsMap := queryDocumentMapByOperationName(queryDocuments) + operationArgsMap := s.operationArgsMapByOperationName() + for _, operation := range s.queryDocument.Operations { + queryDocument := queryDocumentsMap[operation.Name] + args := operationArgsMap[operation.Name] + operations = append(operations, NewOperation( + operation, + queryDocument, + args, + )) + } + + return operations +} + +func (s *Source) operationArgsMapByOperationName() map[string][]*Argument { + operationArgsMap := make(map[string][]*Argument) + for _, operation := range s.queryDocument.Operations { + operationArgsMap[operation.Name] = s.sourceGenerator.OperationArguments(operation.VariableDefinitions) + } + + return operationArgsMap +} + +func queryDocumentMapByOperationName(queryDocuments []*ast.QueryDocument) map[string]*ast.QueryDocument { + queryDocumentMap := make(map[string]*ast.QueryDocument) + for _, queryDocument := range queryDocuments { + operation := queryDocument.Operations[0] + queryDocumentMap[operation.Name] = queryDocument + } + + return queryDocumentMap +} + +func queryString(queryDocument *ast.QueryDocument) string { + var buf bytes.Buffer + astFormatter := formatter.NewFormatter(&buf) + astFormatter.FormatQueryDocument(queryDocument) + + return buf.String() +} + +type OperationResponse struct { + Name string + Type types.Type +} + +func (s *Source) OperationResponses() ([]*OperationResponse, error) { + operationResponse := make([]*OperationResponse, 0, len(s.queryDocument.Operations)) + for _, operation := range s.queryDocument.Operations { + responseFields := s.sourceGenerator.NewResponseFields(operation.SelectionSet) + name := getResponseStructName(operation) + if s.sourceGenerator.cfg.Models.Exists(name) { + return nil, xerrors.New(fmt.Sprintf("%s is duplicated", name)) + } + operationResponse = append(operationResponse, &OperationResponse{ + Name: name, + Type: responseFields.StructType(), + }) + } + + for _, operationResponse := range operationResponse { + name := operationResponse.Name + s.sourceGenerator.cfg.Models.Add( + name, + fmt.Sprintf("%s.%s", s.sourceGenerator.client.Pkg(), templates.ToGo(name)), + ) + } + + return operationResponse, nil +} + +type Query struct { + Name string + Type types.Type +} + +func (s *Source) Query() (*Query, error) { + fields, err := s.sourceGenerator.NewResponseFieldsByDefinition(s.schema.Query) + if err != nil { + return nil, xerrors.Errorf("generate failed for query struct type : %w", err) + } + + return &Query{ + Name: s.schema.Query.Name, + Type: fields.StructType(), + }, nil +} + +type Mutation struct { + Name string + Type types.Type +} + +func (s *Source) Mutation() (*Mutation, error) { + fields, err := s.sourceGenerator.NewResponseFieldsByDefinition(s.schema.Mutation) + if err != nil { + return nil, xerrors.Errorf("generate failed for mutation struct type : %w", err) + } + + return &Mutation{ + Name: s.schema.Mutation.Name, + Type: fields.StructType(), + }, nil +} + +func getResponseStructName(operation *ast.OperationDefinition) string { + if operation.Operation == ast.Mutation { + return fmt.Sprintf("%sPayload", operation.Name) + } + + return operation.Name +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/source_generator.go b/vendor/github.com/Yamashou/gqlgenc/clientgen/source_generator.go new file mode 100644 index 000000000..f9be08150 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/source_generator.go @@ -0,0 +1,204 @@ +package clientgen + +import ( + "fmt" + "go/types" + "strings" + + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/codegen/templates" + "github.com/vektah/gqlparser/v2/ast" + "golang.org/x/xerrors" +) + +type Argument struct { + Variable string + Type types.Type +} + +type ResponseField struct { + Name string + IsFragmentSpread bool + IsInlineFragment bool + Type types.Type + Tags []string + ResponseFields ResponseFieldList +} + +type ResponseFieldList []*ResponseField + +func (rs ResponseFieldList) StructType() *types.Struct { + vars := make([]*types.Var, 0) + structTags := make([]string, 0) + for _, filed := range rs { + // クエリーのフィールドの子階層がFragmentの場合、このフィールドにそのFragmentの型を追加する + if filed.IsFragmentSpread { + typ := filed.ResponseFields.StructType().Underlying().(*types.Struct) + for j := 0; j < typ.NumFields(); j++ { + vars = append(vars, typ.Field(j)) + structTags = append(structTags, typ.Tag(j)) + } + } else { + vars = append(vars, types.NewVar(0, nil, templates.ToGo(filed.Name), filed.Type)) + structTags = append(structTags, strings.Join(filed.Tags, " ")) + } + } + + return types.NewStruct(vars, structTags) +} + +func (rs ResponseFieldList) IsFragment() bool { + if len(rs) != 1 { + return false + } + + return rs[0].IsInlineFragment || rs[0].IsFragmentSpread +} + +func (rs ResponseFieldList) IsBasicType() bool { + return len(rs) == 0 +} + +func (rs ResponseFieldList) IsStructType() bool { + return len(rs) > 0 && !rs.IsFragment() +} + +type SourceGenerator struct { + cfg *config.Config + binder *config.Binder + client config.PackageConfig +} + +func NewSourceGenerator(cfg *config.Config, client config.PackageConfig) *SourceGenerator { + return &SourceGenerator{ + cfg: cfg, + binder: cfg.NewBinder(), + client: client, + } +} + +func (r *SourceGenerator) NewResponseFields(selectionSet ast.SelectionSet) ResponseFieldList { + responseFields := make(ResponseFieldList, 0, len(selectionSet)) + for _, selection := range selectionSet { + responseFields = append(responseFields, r.NewResponseField(selection)) + } + + return responseFields +} + +func (r *SourceGenerator) NewResponseFieldsByDefinition(definition *ast.Definition) (ResponseFieldList, error) { + fields := make(ResponseFieldList, 0, len(definition.Fields)) + for _, field := range definition.Fields { + if field.Type.Name() == "__Schema" || field.Type.Name() == "__Type" { + continue + } + typ, err := r.binder.FindTypeFromName(r.cfg.Models[field.Type.Name()].Model[0]) + if err != nil { + return nil, xerrors.Errorf("not found type: %w", err) + } + tags := []string{ + fmt.Sprintf(`json:"%s"`, field.Name), + fmt.Sprintf(`graphql:"%s"`, field.Name), + } + + fields = append(fields, &ResponseField{ + Name: field.Name, + Type: r.binder.CopyModifiersFromAst(field.Type, typ), + Tags: tags, + }) + } + + return fields, nil +} + +func (r *SourceGenerator) NewResponseField(selection ast.Selection) *ResponseField { + switch selection := selection.(type) { + case *ast.Field: + fieldsResponseFields := r.NewResponseFields(selection.SelectionSet) + + var baseType types.Type + switch { + case fieldsResponseFields.IsBasicType(): + baseType = r.Type(selection.Definition.Type.Name()) + case fieldsResponseFields.IsFragment(): + // 子フィールドがFragmentの場合はこのFragmentがフィールドの型になる + // if a child field is fragment, this field type became fragment. + baseType = fieldsResponseFields[0].Type + case fieldsResponseFields.IsStructType(): + baseType = fieldsResponseFields.StructType() + default: + // ここにきたらバグ + // here is bug + panic("not match type") + } + + // GraphQLの定義がオプショナルのはtypeのポインタ型が返り、配列の定義場合はポインタのスライスの型になって返ってきます + // return pointer type then optional type or slice pointer then slice type of definition in GraphQL. + typ := r.binder.CopyModifiersFromAst(selection.Definition.Type, baseType) + + tags := []string{ + fmt.Sprintf(`json:"%s"`, selection.Alias), + fmt.Sprintf(`graphql:"%s"`, selection.Alias), + } + + return &ResponseField{ + Name: selection.Alias, + Type: typ, + Tags: tags, + ResponseFields: fieldsResponseFields, + } + + case *ast.FragmentSpread: + // この構造体はテンプレート側で使われることはなく、ast.FieldでFragment判定するために使用する + fieldsResponseFields := r.NewResponseFields(selection.Definition.SelectionSet) + typ := types.NewNamed( + types.NewTypeName(0, r.client.Pkg(), templates.ToGo(selection.Name), nil), + fieldsResponseFields.StructType(), + nil, + ) + + return &ResponseField{ + Name: selection.Name, + Type: typ, + IsFragmentSpread: true, + ResponseFields: fieldsResponseFields, + } + + case *ast.InlineFragment: + // InlineFragmentは子要素をそのままstructとしてもつので、ここで、構造体の型を作成します + fieldsResponseFields := r.NewResponseFields(selection.SelectionSet) + + return &ResponseField{ + Name: selection.TypeCondition, + Type: fieldsResponseFields.StructType(), + IsInlineFragment: true, + Tags: []string{fmt.Sprintf(`graphql:"... on %s"`, selection.TypeCondition)}, + ResponseFields: fieldsResponseFields, + } + } + + panic("unexpected selection type") +} + +func (r *SourceGenerator) OperationArguments(variableDefinitions ast.VariableDefinitionList) []*Argument { + argumentTypes := make([]*Argument, 0, len(variableDefinitions)) + for _, v := range variableDefinitions { + argumentTypes = append(argumentTypes, &Argument{ + Variable: v.Variable, + Type: r.binder.CopyModifiersFromAst(v.Type, r.Type(v.Type.Name())), + }) + } + + return argumentTypes +} + +// Typeの引数に渡すtypeNameは解析した結果からselectionなどから求めた型の名前を渡さなければいけない +func (r *SourceGenerator) Type(typeName string) types.Type { + goType, err := r.binder.FindTypeFromName(r.cfg.Models[typeName].Model[0]) + if err != nil { + // 実装として正しいtypeNameを渡していれば必ず見つかるはずなのでpanic + panic(fmt.Sprintf("%+v", err)) + } + + return goType +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/template.go b/vendor/github.com/Yamashou/gqlgenc/clientgen/template.go new file mode 100644 index 000000000..3e8fca403 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/template.go @@ -0,0 +1,27 @@ +package clientgen + +import ( + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/codegen/templates" + "golang.org/x/xerrors" +) + +func RenderTemplate(cfg *config.Config, query *Query, mutation *Mutation, fragments []*Fragment, operations []*Operation, operationResponses []*OperationResponse, client config.PackageConfig) error { + if err := templates.Render(templates.Options{ + PackageName: client.Package, + Filename: client.Filename, + Data: map[string]interface{}{ + "Query": query, + "Mutation": mutation, + "Fragment": fragments, + "Operation": operations, + "OperationResponse": operationResponses, + }, + Packages: cfg.Packages, + PackageDoc: "// Code generated by github.com/Yamashou/gqlgenc, DO NOT EDIT.\n", + }); err != nil { + return xerrors.Errorf("%s generating failed: %w", client.Filename, err) + } + + return nil +} diff --git a/vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl b/vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl new file mode 100644 index 000000000..76495ee8a --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl @@ -0,0 +1,54 @@ +{{ reserveImport "bytes" }} +{{ reserveImport "context" }} +{{ reserveImport "encoding/json" }} +{{ reserveImport "fmt" }} +{{ reserveImport "io" }} +{{ reserveImport "io/ioutil" }} +{{ reserveImport "net/http" }} +{{ reserveImport "net/url" }} +{{ reserveImport "path" }} +{{ reserveImport "time" }} + +{{ reserveImport "golang.org/x/xerrors" }} + +{{ reserveImport "github.com/Yamashou/gqlgenc/graphqljson" }} +{{ reserveImport "github.com/Yamashou/gqlgenc/client" }} + +type Client struct { + Client *client.Client +} + +func NewClient(cli *http.Client, baseURL string, options ...client.HTTPRequestOption) *Client { + return &Client{Client: client.NewClient(cli, baseURL, options...)} +} + +type {{ .Query.Name | go }} {{ .Query.Type | ref }} + +type {{ .Mutation.Name | go }} {{ .Mutation.Type | ref }} + +{{- range $name, $element := .Fragment }} + type {{ .Name | go }} {{ .Type | ref }} +{{- end }} + +{{- range $name, $element := .OperationResponse }} + type {{ .Name | go }} {{ .Type | ref }} +{{- end }} + +{{- range $model := .Operation}} +const {{ $model.Name|go }}Query = `{{ $model.Operation }}` + +func (c *Client) {{ $model.Name|go }} (ctx context.Context{{- range $arg := .Args }}, {{ $arg.Variable | goPrivate }} {{ $arg.Type | ref }} {{- end }}, httpRequestOptions ...client.HTTPRequestOption) (*{{ $model.ResponseStructName | go }}, error) { + vars := map[string]interface{}{ + {{- range $args := .VariableDefinitions}} + "{{ $args.Variable }}": {{ $args.Variable | goPrivate }}, + {{- end }} + } + + var res {{ $model.ResponseStructName | go }} + if err := c.Client.Post(ctx, {{ $model.Name|go }}Query, &res, vars, httpRequestOptions...); err != nil { + return nil, err + } + + return &res, nil +} +{{- end}} diff --git a/vendor/github.com/Yamashou/gqlgenc/config/config.go b/vendor/github.com/Yamashou/gqlgenc/config/config.go new file mode 100644 index 000000000..620b11ca3 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/config/config.go @@ -0,0 +1,123 @@ +package config + +import ( + "context" + "io/ioutil" + "net/http" + "os" + "path/filepath" + + "github.com/99designs/gqlgen/codegen/config" + "github.com/Yamashou/gqlgenc/client" + "github.com/Yamashou/gqlgenc/introspection" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/validator" + "golang.org/x/xerrors" + "gopkg.in/yaml.v2" +) + +type Config struct { + Model config.PackageConfig `yaml:"model,omitempty"` + Client config.PackageConfig `yaml:"client,omitempty"` + Models config.TypeMap `yaml:"models,omitempty"` + Endpoint EndPointConfig `yaml:"endpoint"` + Query []string `yaml:"query"` + + // gqlgen config struct + GQLConfig *config.Config `yaml:"-"` +} + +type EndPointConfig struct { + URL string `yaml:"url"` + Headers map[string]string `yaml:"headers,omitempty"` +} + +func findCfg(fileName string) (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", xerrors.Errorf("unable to get working dir to findCfg: %w", err) + } + + cfg := findCfgInDir(dir, fileName) + + if cfg == "" { + return "", os.ErrNotExist + } + + return cfg, nil +} + +func findCfgInDir(dir, fileName string) string { + path := filepath.Join(dir, fileName) + + return path +} + +func LoadConfig(filename string) (*Config, error) { + var cfg Config + file, err := findCfg(filename) + if err != nil { + return nil, xerrors.Errorf("unable to get file path: %w", err) + } + b, err := ioutil.ReadFile(file) + if err != nil { + return nil, xerrors.Errorf("unable to read config: %w", err) + } + + confContent := []byte(os.ExpandEnv(string(b))) + if err := yaml.UnmarshalStrict(confContent, &cfg); err != nil { + return nil, xerrors.Errorf("unable to parse config: %w", err) + } + + cfg.GQLConfig = &config.Config{ + Model: cfg.Model, + Models: cfg.Models, + // TODO: gqlgen must be set exec but client not used + Exec: config.PackageConfig{Filename: "generated.go"}, + Directives: map[string]config.DirectiveConfig{}, + } + + if err := cfg.Client.Check(); err != nil { + return nil, xerrors.Errorf("config.exec: %w", err) + } + + return &cfg, nil +} + +func (c *Config) LoadSchema(ctx context.Context) error { + addHeader := func(req *http.Request) { + for key, value := range c.Endpoint.Headers { + req.Header.Set(key, value) + } + } + gqlclient := client.NewClient(http.DefaultClient, c.Endpoint.URL, addHeader) + schema, err := LoadRemoteSchema(ctx, gqlclient) + if err != nil { + return xerrors.Errorf("load remote schema failed: %w", err) + } + if schema.Query == nil { + schema.Query = &ast.Definition{ + Kind: ast.Object, + Name: "Query", + } + schema.Types["Query"] = schema.Query + } + + c.GQLConfig.Schema = schema + + return nil +} + +func LoadRemoteSchema(ctx context.Context, gqlclient *client.Client) (*ast.Schema, error) { + var res introspection.Query + if err := gqlclient.Post(ctx, introspection.Introspection, &res, nil); err != nil { + return nil, xerrors.Errorf("introspection query failed: %w", err) + } + + schema, err := validator.ValidateSchemaDocument(introspection.ParseIntrospectionQuery(res)) + if err != nil { + return nil, xerrors.Errorf("validation error: %w", err) + } + + return schema, nil +} diff --git a/vendor/github.com/Yamashou/gqlgenc/generator/generater.go b/vendor/github.com/Yamashou/gqlgenc/generator/generater.go new file mode 100644 index 000000000..075b54b12 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/generator/generater.go @@ -0,0 +1,40 @@ +package generator + +import ( + "context" + + "github.com/99designs/gqlgen/api" + "github.com/99designs/gqlgen/plugin" + "github.com/99designs/gqlgen/plugin/modelgen" + "github.com/Yamashou/gqlgenc/config" + "golang.org/x/xerrors" +) + +func Generate(ctx context.Context, cfg *config.Config, option ...api.Option) error { + var plugins []plugin.Plugin + if cfg.Model.IsDefined() { + plugins = append(plugins, modelgen.New()) + } + for _, o := range option { + o(cfg.GQLConfig, &plugins) + } + + if err := cfg.LoadSchema(ctx); err != nil { + return xerrors.Errorf("failed to load schema: %w\n", err) + } + + if err := cfg.GQLConfig.Init(); err != nil { + return xerrors.Errorf("generating core failed: %w\n", err) + } + + for _, p := range plugins { + if mut, ok := p.(plugin.ConfigMutator); ok { + err := mut.MutateConfig(cfg.GQLConfig) + if err != nil { + return xerrors.Errorf("%s failed: %w\n", p.Name(), err) + } + } + } + + return nil +} diff --git a/vendor/github.com/Yamashou/gqlgenc/go.mod b/vendor/github.com/Yamashou/gqlgenc/go.mod new file mode 100644 index 000000000..7b4208f7d --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/go.mod @@ -0,0 +1,14 @@ +module github.com/Yamashou/gqlgenc + +go 1.14 + +require ( + github.com/99designs/gqlgen v0.12.2 + github.com/agnivade/levenshtein v1.1.0 // indirect + github.com/google/go-cmp v0.5.2 + github.com/pkg/errors v0.9.1 // indirect + github.com/vektah/gqlparser/v2 v2.0.1 + golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 + gopkg.in/yaml.v2 v2.3.0 +) diff --git a/vendor/github.com/Yamashou/gqlgenc/go.sum b/vendor/github.com/Yamashou/gqlgenc/go.sum new file mode 100644 index 000000000..966cfd8d7 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/go.sum @@ -0,0 +1,122 @@ +github.com/99designs/gqlgen v0.12.2 h1:aOdpsiCycFtCnAv8CAI1exnKrIDHMqtMzQoXeTziY4o= +github.com/99designs/gqlgen v0.12.2/go.mod h1:7zdGo6ry9u1YBp/qlb2uxSU5Mt2jQKLcBETQiKk+Bxo= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= +github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= +github.com/agnivade/levenshtein v1.1.0 h1:n6qGwyHG61v3ABce1rPVZklEYRT8NFpCMrpZdBUbYGM= +github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +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/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM= +github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +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/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +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/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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.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/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +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/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +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.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU= +github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74= +github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o= +github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3 h1:OjYQxZBKJFs+sJbHkvSGIKNMkZXDJQ9JsMpebGhkafI= +golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= diff --git a/vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go b/vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go new file mode 100644 index 000000000..223176aa7 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go @@ -0,0 +1,416 @@ +/* +MIT License + +Copyright (c) 2017 Dmitri Shuralyov + +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. +*/ + +// Package jsonutil provides a function for decoding JSON +// into a GraphQL query data structure. +package graphqljson + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + "strings" + + "golang.org/x/xerrors" +) + +// Reference: https://blog.gopheracademy.com/advent-2017/custom-json-unmarshaler-for-graphql-client/ + +// RawJSONError is a json formatted error from a GraphQL server. +type RawJSONError struct { + Response +} + +func (r RawJSONError) Error() string { + return fmt.Sprintf("data: %s, error: %s, extensions: %v", r.Data, r.Errors, r.Extensions) +} + +// Response is a GraphQL layer response from a handler. +type Response struct { + Data json.RawMessage + Errors Errors + Extensions map[string]interface{} +} + +func Unmarshal(r io.Reader, data interface{}) error { + resp := Response{} + decoder := json.NewDecoder(r) + if err := decoder.Decode(&resp); err != nil { + var buf bytes.Buffer + if _, e := io.Copy(&buf, decoder.Buffered()); e != nil { + return xerrors.Errorf(": %w", err) + } + + return xerrors.Errorf("%s", buf.String()) + } + + if len(resp.Errors) > 0 { + return xerrors.Errorf("response error: %w", resp.Errors) + } + + if err := UnmarshalData(resp.Data, data); err != nil { + return xerrors.Errorf("response mapping failed: %w", err) + } + + if resp.Errors != nil { + return RawJSONError{resp} + } + + return nil +} + +// UnmarshalGraphQL parses the JSON-encoded GraphQL response data and stores +// the result in the GraphQL query data structure pointed to by v. +// +// The implementation is created on top of the JSON tokenizer available +// in "encoding/json".Decoder. +func UnmarshalData(data json.RawMessage, v interface{}) error { + d := NewDecoder(bytes.NewBuffer(data)) + if err := d.Decode(v); err != nil { + return xerrors.Errorf(": %w", err) + } + + // TODO: この処理が本当に必要かは今後検討 + tok, err := d.jsonDecoder.Token() + switch err { + case io.EOF: + // Expect to get io.EOF. There shouldn't be any more + // tokens left after we've decoded v successfully. + return nil + case nil: + return xerrors.Errorf("invalid token '%v' after top-level value", tok) + } + + return xerrors.Errorf("invalid token '%v' after top-level value", tok) +} + +// decoder is a JSON decoder that performs custom unmarshaling behavior +// for GraphQL query data structures. It's implemented on top of a JSON tokenizer. +type Decoder struct { + jsonDecoder *json.Decoder + + // Stack of what part of input JSON we're in the middle of - objects, arrays. + parseState []json.Delim + + // Stacks of values where to unmarshal. + // The top of each stack is the reflect.Value where to unmarshal next JSON value. + // + // The reason there's more than one stack is because we might be unmarshaling + // a single JSON value into multiple GraphQL fragments or embedded structs, so + // we keep track of them all. + vs [][]reflect.Value +} + +func NewDecoder(r io.Reader) *Decoder { + jsonDecoder := json.NewDecoder(r) + jsonDecoder.UseNumber() + + return &Decoder{ + jsonDecoder: jsonDecoder, + } +} + +// Decode decodes a single JSON value from d.tokenizer into v. +func (d *Decoder) Decode(v interface{}) error { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr { + return xerrors.Errorf("cannot decode into non-pointer %T", v) + } + + d.vs = [][]reflect.Value{{rv.Elem()}} + if err := d.decode(); err != nil { + return xerrors.Errorf(": %w", err) + } + + return nil +} + +// decode decodes a single JSON value from d.tokenizer into d.vs. +func (d *Decoder) decode() error { + // The loop invariant is that the top of each d.vs stack + // is where we try to unmarshal the next JSON value we see. + for len(d.vs) > 0 { + tok, err := d.jsonDecoder.Token() + if err == io.EOF { + return xerrors.New("unexpected end of JSON input") + } else if err != nil { + return xerrors.Errorf(": %w", err) + } + + switch { + // Are we inside an object and seeing next key (rather than end of object)? + case d.state() == '{' && tok != json.Delim('}'): + key, ok := tok.(string) + if !ok { + return xerrors.New("unexpected non-key in JSON input") + } + + someFieldExist := false + for i := range d.vs { + v := d.vs[i][len(d.vs[i])-1] + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + var f reflect.Value + if v.Kind() == reflect.Struct { + f = fieldByGraphQLName(v, key) + if f.IsValid() { + someFieldExist = true + } + } + d.vs[i] = append(d.vs[i], f) + } + if !someFieldExist { + return xerrors.Errorf("struct field for %q doesn't exist in any of %v places to unmarshal", key, len(d.vs)) + } + + // We've just consumed the current token, which was the key. + // Read the next token, which should be the value, and let the rest of code process it. + tok, err = d.jsonDecoder.Token() + if err == io.EOF { + return xerrors.New("unexpected end of JSON input") + } else if err != nil { + return xerrors.Errorf(": %w", err) + } + + // Are we inside an array and seeing next value (rather than end of array)? + case d.state() == '[' && tok != json.Delim(']'): + someSliceExist := false + for i := range d.vs { + v := d.vs[i][len(d.vs[i])-1] + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + var f reflect.Value + if v.Kind() == reflect.Slice { + v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) // v = append(v, T). + f = v.Index(v.Len() - 1) + someSliceExist = true + } + d.vs[i] = append(d.vs[i], f) + } + if !someSliceExist { + return xerrors.Errorf("slice doesn't exist in any of %v places to unmarshal", len(d.vs)) + } + } + + switch tok := tok.(type) { + case string, json.Number, bool, nil: + // Value. + + for i := range d.vs { + v := d.vs[i][len(d.vs[i])-1] + if !v.IsValid() { + continue + } + err := unmarshalValue(tok, v) + if err != nil { + return xerrors.Errorf(": %w", err) + } + } + d.popAllVs() + + case json.Delim: + switch tok { + case '{': + // Start of object. + + d.pushState(tok) + + frontier := make([]reflect.Value, len(d.vs)) // Places to look for GraphQL fragments/embedded structs. + for i := range d.vs { + v := d.vs[i][len(d.vs[i])-1] + frontier[i] = v + // TODO: Do this recursively or not? Add a test case if needed. + if v.Kind() == reflect.Ptr && v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) // v = new(T). + } + } + // Find GraphQL fragments/embedded structs recursively, adding to frontier + // as new ones are discovered and exploring them further. + for len(frontier) > 0 { + v := frontier[0] + frontier = frontier[1:] + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if v.Kind() != reflect.Struct { + continue + } + for i := 0; i < v.NumField(); i++ { + if isGraphQLFragment(v.Type().Field(i)) || v.Type().Field(i).Anonymous { + // Add GraphQL fragment or embedded struct. + d.vs = append(d.vs, []reflect.Value{v.Field(i)}) + frontier = append(frontier, v.Field(i)) + } + } + } + case '[': + // Start of array. + + d.pushState(tok) + + for i := range d.vs { + v := d.vs[i][len(d.vs[i])-1] + // TODO: Confirm this is needed, write a test case. + // if v.Kind() == reflect.Ptr && v.IsNil() { + // v.Set(reflect.New(v.Type().Elem())) // v = new(T). + //} + + // Reset slice to empty (in case it had non-zero initial value). + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if v.Kind() != reflect.Slice { + continue + } + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) // v = make(T, 0, 0). + } + case '}', ']': + // End of object or array. + d.popAllVs() + d.popState() + default: + return xerrors.New("unexpected delimiter in JSON input") + } + default: + return xerrors.New("unexpected token in JSON input") + } + } + + return nil +} + +// pushState pushes a new parse state s onto the stack. +func (d *Decoder) pushState(s json.Delim) { + d.parseState = append(d.parseState, s) +} + +// popState pops a parse state (already obtained) off the stack. +// The stack must be non-empty. +func (d *Decoder) popState() { + d.parseState = d.parseState[:len(d.parseState)-1] +} + +// state reports the parse state on top of stack, or 0 if empty. +func (d *Decoder) state() json.Delim { + if len(d.parseState) == 0 { + return 0 + } + + return d.parseState[len(d.parseState)-1] +} + +// popAllVs pops from all d.vs stacks, keeping only non-empty ones. +func (d *Decoder) popAllVs() { + var nonEmpty [][]reflect.Value + for i := range d.vs { + d.vs[i] = d.vs[i][:len(d.vs[i])-1] + if len(d.vs[i]) > 0 { + nonEmpty = append(nonEmpty, d.vs[i]) + } + } + d.vs = nonEmpty +} + +// fieldByGraphQLName returns an exported struct field of struct v +// that matches GraphQL name, or invalid reflect.Value if none found. +func fieldByGraphQLName(v reflect.Value, name string) reflect.Value { + for i := 0; i < v.NumField(); i++ { + if v.Type().Field(i).PkgPath != "" { + // Skip unexported field. + continue + } + if hasGraphQLName(v.Type().Field(i), name) { + return v.Field(i) + } + } + + return reflect.Value{} +} + +// hasGraphQLName reports whether struct field f has GraphQL name. +func hasGraphQLName(f reflect.StructField, name string) bool { + value, ok := f.Tag.Lookup("graphql") + if !ok { + // TODO: caseconv package is relatively slow. Optimize it, then consider using it here. + // return caseconv.MixedCapsToLowerCamelCase(f.Name) == name + return strings.EqualFold(f.Name, name) + } + value = strings.TrimSpace(value) // TODO: Parse better. + if strings.HasPrefix(value, "...") { + // GraphQL fragment. It doesn't have a name. + return false + } + if i := strings.Index(value, "("); i != -1 { + value = value[:i] + } + if i := strings.Index(value, ":"); i != -1 { + value = value[:i] + } + + return strings.TrimSpace(value) == name +} + +// isGraphQLFragment reports whether struct field f is a GraphQL fragment. +func isGraphQLFragment(f reflect.StructField) bool { + value, ok := f.Tag.Lookup("graphql") + if !ok { + return false + } + value = strings.TrimSpace(value) // TODO: Parse better. + + return strings.HasPrefix(value, "...") +} + +// unmarshalValue unmarshals JSON value into v. +// v must be addressable and not obtained by the use of unexported +// struct fields, otherwise unmarshalValue will panic. +func unmarshalValue(value json.Token, v reflect.Value) error { + b, err := json.Marshal(value) // TODO: Short-circuit (if profiling says it's worth it). + if err != nil { + return xerrors.Errorf(": %w", err) + } + + return json.Unmarshal(b, v.Addr().Interface()) +} + +// Errors represents the "Errors" array in a response from a GraphQL server. +// If returned via error interface, the slice is expected to contain at least 1 element. +// +// Specification: https://facebook.github.io/graphql/#sec-Errors. +type Errors []struct { + Message string + Locations []struct { + Line int + Column int + } +} + +// Error implements error interface. +func (e Errors) Error() string { + return e[0].Message +} diff --git a/vendor/github.com/Yamashou/gqlgenc/introspection/parse.go b/vendor/github.com/Yamashou/gqlgenc/introspection/parse.go new file mode 100644 index 000000000..8ffb4649d --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/introspection/parse.go @@ -0,0 +1,289 @@ +package introspection + +import ( + "fmt" + + "github.com/vektah/gqlparser/v2/ast" +) + +func ParseIntrospectionQuery(query Query) *ast.SchemaDocument { + var doc ast.SchemaDocument + typeMap := query.Schema.Types.NameMap() + + doc.Schema = append(doc.Schema, parseSchemaDefinition(query, typeMap)) + + for _, typeVale := range typeMap { + doc.Definitions = append(doc.Definitions, parseTypeSystemDefinition(typeVale)) + } + + for _, directiveValue := range query.Schema.Directives { + doc.Directives = append(doc.Directives, parseDirectiveDefinition(directiveValue)) + } + + return &doc +} + +func parseSchemaDefinition(query Query, typeMap map[string]*FullType) *ast.SchemaDefinition { + def := ast.SchemaDefinition{} + + def.OperationTypes = append(def.OperationTypes, + parseOperationTypeDefinitionForQuery(typeMap[*query.Schema.QueryType.Name]), + parseOperationTypeDefinitionForMutation(typeMap[*query.Schema.MutationType.Name]), + ) + + return &def +} + +func parseOperationTypeDefinitionForQuery(fullType *FullType) *ast.OperationTypeDefinition { + var op ast.OperationTypeDefinition + op.Operation = ast.Query + op.Type = *fullType.Name + + return &op +} + +func parseOperationTypeDefinitionForMutation(fullType *FullType) *ast.OperationTypeDefinition { + var op ast.OperationTypeDefinition + op.Operation = ast.Mutation + op.Type = *fullType.Name + + return &op +} + +func parseDirectiveDefinition(directiveValue *DirectiveType) *ast.DirectiveDefinition { + args := make(ast.ArgumentDefinitionList, 0, len(directiveValue.Args)) + for _, arg := range directiveValue.Args { + argumentDefinition := buildInputValue(arg) + args = append(args, argumentDefinition) + } + locations := make([]ast.DirectiveLocation, 0, len(directiveValue.Locations)) + for _, locationValue := range directiveValue.Locations { + locations = append(locations, ast.DirectiveLocation(locationValue)) + } + + return &ast.DirectiveDefinition{ + Description: pointerString(directiveValue.Description), + Name: directiveValue.Name, + Arguments: args, + Locations: locations, + } +} + +func parseObjectFields(typeVale *FullType) ast.FieldList { + fieldList := make(ast.FieldList, 0, len(typeVale.Fields)) + for _, field := range typeVale.Fields { + typ := getType(&field.Type) + args := make(ast.ArgumentDefinitionList, 0, len(field.Args)) + for _, arg := range field.Args { + argumentDefinition := buildInputValue(arg) + args = append(args, argumentDefinition) + } + + fieldDefinition := &ast.FieldDefinition{ + Description: pointerString(field.Description), + Name: field.Name, + Arguments: args, + Type: typ, + } + fieldList = append(fieldList, fieldDefinition) + } + + return fieldList +} + +func parseInputObjectFields(typeVale *FullType) ast.FieldList { + fieldList := make(ast.FieldList, 0, len(typeVale.InputFields)) + for _, field := range typeVale.InputFields { + typ := getType(&field.Type) + fieldDefinition := &ast.FieldDefinition{ + Description: pointerString(field.Description), + Name: field.Name, + Type: typ, + } + fieldList = append(fieldList, fieldDefinition) + } + + return fieldList +} + +func parseObjectTypeDefinition(typeVale *FullType) *ast.Definition { + fieldList := parseObjectFields(typeVale) + interfaces := make([]string, 0, len(typeVale.Interfaces)) + for _, intf := range typeVale.Interfaces { + interfaces = append(interfaces, pointerString(intf.Name)) + } + + enums := make(ast.EnumValueList, 0, len(typeVale.EnumValues)) + for _, enum := range typeVale.EnumValues { + enumValue := &ast.EnumValueDefinition{ + Description: pointerString(enum.Description), + Name: enum.Name, + } + enums = append(enums, enumValue) + } + + return &ast.Definition{ + Kind: ast.Object, + Description: pointerString(typeVale.Description), + Name: pointerString(typeVale.Name), + Interfaces: interfaces, + Fields: fieldList, + EnumValues: enums, + Position: nil, + BuiltIn: true, + } +} + +func parseInterfaceTypeDefinition(typeVale *FullType) *ast.Definition { + fieldList := parseObjectFields(typeVale) + interfaces := make([]string, 0, len(typeVale.Interfaces)) + for _, intf := range typeVale.Interfaces { + interfaces = append(interfaces, pointerString(intf.Name)) + } + + return &ast.Definition{ + Kind: ast.Interface, + Description: pointerString(typeVale.Description), + Name: pointerString(typeVale.Name), + Interfaces: interfaces, + Fields: fieldList, + Position: nil, + BuiltIn: true, + } +} + +func parseInputObjectTypeDefinition(typeVale *FullType) *ast.Definition { + fieldList := parseInputObjectFields(typeVale) + interfaces := make([]string, 0, len(typeVale.Interfaces)) + for _, intf := range typeVale.Interfaces { + interfaces = append(interfaces, pointerString(intf.Name)) + } + + return &ast.Definition{ + Kind: ast.InputObject, + Description: pointerString(typeVale.Description), + Name: pointerString(typeVale.Name), + Interfaces: interfaces, + Fields: fieldList, + Position: nil, + BuiltIn: true, + } +} + +func parseUnionTypeDefinition(typeVale *FullType) *ast.Definition { + unions := make([]string, 0, len(typeVale.PossibleTypes)) + for _, unionValue := range typeVale.PossibleTypes { + unions = append(unions, *unionValue.Name) + } + + return &ast.Definition{ + Kind: ast.Union, + Description: pointerString(typeVale.Description), + Name: pointerString(typeVale.Name), + Types: unions, + Position: nil, + BuiltIn: true, + } +} + +func parseEnumTypeDefinition(typeVale *FullType) *ast.Definition { + enums := make(ast.EnumValueList, 0, len(typeVale.EnumValues)) + for _, enum := range typeVale.EnumValues { + enumValue := &ast.EnumValueDefinition{ + Description: pointerString(enum.Description), + Name: enum.Name, + } + enums = append(enums, enumValue) + } + + return &ast.Definition{ + Kind: ast.Enum, + Description: pointerString(typeVale.Description), + Name: pointerString(typeVale.Name), + EnumValues: enums, + Position: nil, + BuiltIn: true, + } +} + +func parseScalarTypeExtension(typeVale *FullType) *ast.Definition { + return &ast.Definition{ + Kind: ast.Scalar, + Description: pointerString(typeVale.Description), + Name: pointerString(typeVale.Name), + Position: nil, + BuiltIn: true, + } +} + +func parseTypeSystemDefinition(typeVale *FullType) *ast.Definition { + switch typeVale.Kind { + case TypeKindScalar: + return parseScalarTypeExtension(typeVale) + case TypeKindInterface: + return parseInterfaceTypeDefinition(typeVale) + case TypeKindEnum: + return parseEnumTypeDefinition(typeVale) + case TypeKindUnion: + return parseUnionTypeDefinition(typeVale) + case TypeKindObject: + return parseObjectTypeDefinition(typeVale) + case TypeKindInputObject: + return parseInputObjectTypeDefinition(typeVale) + case TypeKindList, TypeKindNonNull: + panic(fmt.Sprintf("not match Kind: %s", typeVale.Kind)) + } + + panic(fmt.Sprintf("not match Kind: %s", typeVale.Kind)) +} + +func pointerString(s *string) string { + if s == nil { + return "" + } + + return *s +} + +func buildInputValue(input *InputValue) *ast.ArgumentDefinition { + typ := getType(&input.Type) + + var defaultValue *ast.Value + if input.DefaultValue != nil { + defaultValue = &ast.Value{ + Raw: pointerString(input.DefaultValue), + Kind: ast.Variable, + } + } + + return &ast.ArgumentDefinition{ + Description: pointerString(input.Description), + Name: input.Name, + DefaultValue: defaultValue, + Type: typ, + } +} + +func getType(typeRef *TypeRef) *ast.Type { + if typeRef.Kind == TypeKindList { + itemRef := typeRef.OfType + if itemRef == nil { + panic("Decorated type deeper than introspection query.") + } + + return ast.ListType(getType(itemRef), nil) + } + + if typeRef.Kind == TypeKindNonNull { + nullableRef := typeRef.OfType + if nullableRef == nil { + panic("Decorated type deeper than introspection query.") + } + nullableType := getType(nullableRef) + nullableType.NonNull = true + + return nullableType + } + + return ast.NamedType(pointerString(typeRef.Name), nil) +} diff --git a/vendor/github.com/Yamashou/gqlgenc/introspection/query.go b/vendor/github.com/Yamashou/gqlgenc/introspection/query.go new file mode 100644 index 000000000..7bd126ac2 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/introspection/query.go @@ -0,0 +1,93 @@ +package introspection + +const Introspection = `query Query { + __schema { + queryType { name } + mutationType { name } + subscriptionType { name } + types { + ...FullType + } + directives { + name + description + locations + args { + ...InputValue + } + } + } + } + + fragment FullType on __Type { + kind + name + description + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } + } + + fragment InputValue on __InputValue { + name + description + type { ...TypeRef } + defaultValue + } + + fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } + }` diff --git a/vendor/github.com/Yamashou/gqlgenc/introspection/type.go b/vendor/github.com/Yamashou/gqlgenc/introspection/type.go new file mode 100644 index 000000000..789f72bf7 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/introspection/type.go @@ -0,0 +1,80 @@ +package introspection + +type TypeKind string + +const ( + TypeKindScalar TypeKind = "SCALAR" + TypeKindObject TypeKind = "OBJECT" + TypeKindInterface TypeKind = "INTERFACE" + TypeKindUnion TypeKind = "UNION" + TypeKindEnum TypeKind = "ENUM" + TypeKindInputObject TypeKind = "INPUT_OBJECT" + TypeKindList TypeKind = "LIST" + TypeKindNonNull TypeKind = "NON_NULL" +) + +type FullTypes []*FullType + +func (fs FullTypes) NameMap() map[string]*FullType { + typeMap := make(map[string]*FullType) + for _, typ := range fs { + typeMap[*typ.Name] = typ + } + + return typeMap +} + +type FullType struct { + Kind TypeKind + Name *string + Description *string + Fields []*FieldValue + InputFields []*InputValue + Interfaces []*TypeRef + EnumValues []*struct { + Name string + Description *string + IsDeprecated bool + DeprecationReason *string + } + PossibleTypes []*TypeRef +} + +type FieldValue struct { + Name string + Description *string + Args []*InputValue + Type TypeRef + IsDeprecated bool + DeprecationReason *string +} + +type InputValue struct { + Name string + Description *string + Type TypeRef + DefaultValue *string +} + +type TypeRef struct { + Kind TypeKind + Name *string + OfType *TypeRef +} + +type Query struct { + Schema struct { + QueryType struct{ Name *string } + MutationType *struct{ Name *string } + SubscriptionType *struct{ Name *string } + Types FullTypes + Directives []*DirectiveType + } `graphql:"__schema"` +} + +type DirectiveType struct { + Name string + Description *string + Locations []string + Args []*InputValue +} diff --git a/vendor/github.com/Yamashou/gqlgenc/main.go b/vendor/github.com/Yamashou/gqlgenc/main.go new file mode 100644 index 000000000..26747b167 --- /dev/null +++ b/vendor/github.com/Yamashou/gqlgenc/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "context" + "fmt" + "os" + + "github.com/99designs/gqlgen/api" + "github.com/Yamashou/gqlgenc/clientgen" + "github.com/Yamashou/gqlgenc/config" + "github.com/Yamashou/gqlgenc/generator" +) + +func main() { + ctx := context.Background() + cfg, err := config.LoadConfig(".gqlgenc.yml") + if err != nil { + fmt.Fprintf(os.Stderr, "%+v", err.Error()) + os.Exit(2) + } + + clientPlugin := clientgen.New(cfg.Query, cfg.Client) + if err := generator.Generate(ctx, cfg, api.AddPlugin(clientPlugin)); err != nil { + fmt.Fprintf(os.Stderr, "%+v", err.Error()) + os.Exit(4) + } +} diff --git a/vendor/github.com/agnivade/levenshtein/.travis.yml b/vendor/github.com/agnivade/levenshtein/.travis.yml index f830ec4ec..8ea828ed9 100644 --- a/vendor/github.com/agnivade/levenshtein/.travis.yml +++ b/vendor/github.com/agnivade/levenshtein/.travis.yml @@ -1,7 +1,23 @@ language: go +# See https://travis-ci.community/t/goos-js-goarch-wasm-go-run-fails-panic-newosproc-not-implemented/1651 +#addons: +# chrome: stable + +before_install: +- export GO111MODULE=on + +#install: +#- go get github.com/agnivade/wasmbrowsertest +#- mv $GOPATH/bin/wasmbrowsertest $GOPATH/bin/go_js_wasm_exec +#- export PATH=$GOPATH/bin:$PATH + go: -- 1.9.x -- 1.10.x - 1.11.x +- 1.12.x +- 1.13.x - tip + +script: +#- GOOS=js GOARCH=wasm go test -v +- go test -v diff --git a/vendor/github.com/agnivade/levenshtein/Makefile b/vendor/github.com/agnivade/levenshtein/Makefile index 4bef27dd1..5f6890d61 100644 --- a/vendor/github.com/agnivade/levenshtein/Makefile +++ b/vendor/github.com/agnivade/levenshtein/Makefile @@ -4,10 +4,12 @@ install: go install lint: - gofmt -l -s -w . && go tool vet -all . && golint + gofmt -l -s -w . && go vet . && golint -set_exit_status=1 . -test: - go test -race -v -coverprofile=coverage.txt -covermode=atomic +test: # The first 2 go gets are to support older Go versions + go get github.com/arbovm/levenshtein + go get github.com/dgryski/trifles/leven + GO111MODULE=on go test -race -v -coverprofile=coverage.txt -covermode=atomic bench: - go test -run=XXX -bench=. -benchmem + go test -run=XXX -bench=. -benchmem -count=5 diff --git a/vendor/github.com/agnivade/levenshtein/README.md b/vendor/github.com/agnivade/levenshtein/README.md index b0fd81df7..6c56689f7 100644 --- a/vendor/github.com/agnivade/levenshtein/README.md +++ b/vendor/github.com/agnivade/levenshtein/README.md @@ -6,6 +6,10 @@ levenshtein [![Build Status](https://travis-ci.org/agnivade/levenshtein.svg?bran The library is fully capable of working with non-ascii strings. But the strings are not normalized. That is left as a user-dependant use case. Please normalize the strings before passing it to the library if you have such a requirement. - https://blog.golang.org/normalization +#### Limitation + +As a performance optimization, the library can handle strings only up to 65536 characters (runes). This is only available on tip, and is not part of a tagged release yet. If you require such an optimization, please use the version at tip. + Install ------- @@ -38,10 +42,10 @@ Benchmarks ``` name time/op -Simple/ASCII-4 537ns ± 2% -Simple/French-4 956ns ± 0% -Simple/Nordic-4 1.95µs ± 1% -Simple/Tibetan-4 1.53µs ± 2% +Simple/ASCII-4 330ns ± 2% +Simple/French-4 617ns ± 2% +Simple/Nordic-4 1.16µs ± 4% +Simple/Tibetan-4 1.05µs ± 1% name alloc/op Simple/ASCII-4 96.0B ± 0% @@ -55,3 +59,22 @@ Simple/French-4 1.00 ± 0% Simple/Nordic-4 1.00 ± 0% Simple/Tibetan-4 1.00 ± 0% ``` + +Comparisons with other libraries +-------------------------------- + +``` +name time/op +Leven/ASCII/agniva-4 353ns ± 1% +Leven/ASCII/arbovm-4 485ns ± 1% +Leven/ASCII/dgryski-4 395ns ± 0% +Leven/French/agniva-4 648ns ± 1% +Leven/French/arbovm-4 791ns ± 0% +Leven/French/dgryski-4 682ns ± 0% +Leven/Nordic/agniva-4 1.28µs ± 1% +Leven/Nordic/arbovm-4 1.52µs ± 1% +Leven/Nordic/dgryski-4 1.32µs ± 1% +Leven/Tibetan/agniva-4 1.12µs ± 1% +Leven/Tibetan/arbovm-4 1.31µs ± 0% +Leven/Tibetan/dgryski-4 1.16µs ± 0% +``` diff --git a/vendor/github.com/agnivade/levenshtein/go.mod b/vendor/github.com/agnivade/levenshtein/go.mod index b2921fb35..4fcfe43e0 100644 --- a/vendor/github.com/agnivade/levenshtein/go.mod +++ b/vendor/github.com/agnivade/levenshtein/go.mod @@ -1 +1,8 @@ module github.com/agnivade/levenshtein + +go 1.13 + +require ( + github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 + github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 +) diff --git a/vendor/github.com/agnivade/levenshtein/go.sum b/vendor/github.com/agnivade/levenshtein/go.sum new file mode 100644 index 000000000..74d92aad1 --- /dev/null +++ b/vendor/github.com/agnivade/levenshtein/go.sum @@ -0,0 +1,4 @@ +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= diff --git a/vendor/github.com/agnivade/levenshtein/levenshtein.go b/vendor/github.com/agnivade/levenshtein/levenshtein.go index 6b08acade..5aecdb592 100644 --- a/vendor/github.com/agnivade/levenshtein/levenshtein.go +++ b/vendor/github.com/agnivade/levenshtein/levenshtein.go @@ -25,12 +25,10 @@ func ComputeDistance(a, b string) int { return 0 } - // We need to convert to []rune if the strings are non-ascii. + // We need to convert to []rune if the strings are non-ASCII. // This could be avoided by using utf8.RuneCountInString - // and then doing some juggling with rune indices. - // The primary challenge is keeping track of the previous rune. - // With a range loop, its not that easy. And with a for-loop - // we need to keep track of the inter-rune width using utf8.DecodeRuneInString + // and then doing some juggling with rune indices, + // but leads to far more bounds checks. It is a reasonable trade-off. s1 := []rune(a) s2 := []rune(b) @@ -42,21 +40,21 @@ func ComputeDistance(a, b string) int { lenS2 := len(s2) // init the row - x := make([]int, lenS1+1) - for i := 0; i <= lenS1; i++ { - x[i] = i + x := make([]uint16, lenS1+1) + // we start from 1 because index 0 is already 0. + for i := 1; i < len(x); i++ { + x[i] = uint16(i) } + // make a dummy bounds check to prevent the 2 bounds check down below. + // The one inside the loop is particularly costly. + _ = x[lenS1] // fill in the rest for i := 1; i <= lenS2; i++ { - prev := i - var current int - + prev := uint16(i) for j := 1; j <= lenS1; j++ { - - if s2[i-1] == s1[j-1] { - current = x[j-1] // match - } else { + current := x[j-1] // match + if s2[i-1] != s1[j-1] { current = min(min(x[j-1]+1, prev+1), x[j]+1) } x[j-1] = prev @@ -64,10 +62,10 @@ func ComputeDistance(a, b string) int { } x[lenS1] = prev } - return x[lenS1] + return int(x[lenS1]) } -func min(a, b int) int { +func min(a, b uint16) uint16 { if a < b { return a } diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md b/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md new file mode 100644 index 000000000..1cade6cef --- /dev/null +++ b/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Brian Goff + +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. diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go new file mode 100644 index 000000000..b48005673 --- /dev/null +++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go @@ -0,0 +1,14 @@ +package md2man + +import ( + "github.com/russross/blackfriday/v2" +) + +// Render converts a markdown document into a roff formatted document. +func Render(doc []byte) []byte { + renderer := NewRoffRenderer() + + return blackfriday.Run(doc, + []blackfriday.Option{blackfriday.WithRenderer(renderer), + blackfriday.WithExtensions(renderer.GetExtensions())}...) +} diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go new file mode 100644 index 000000000..0668a66cf --- /dev/null +++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go @@ -0,0 +1,345 @@ +package md2man + +import ( + "fmt" + "io" + "os" + "strings" + + "github.com/russross/blackfriday/v2" +) + +// roffRenderer implements the blackfriday.Renderer interface for creating +// roff format (manpages) from markdown text +type roffRenderer struct { + extensions blackfriday.Extensions + listCounters []int + firstHeader bool + defineTerm bool + listDepth int +} + +const ( + titleHeader = ".TH " + topLevelHeader = "\n\n.SH " + secondLevelHdr = "\n.SH " + otherHeader = "\n.SS " + crTag = "\n" + emphTag = "\\fI" + emphCloseTag = "\\fP" + strongTag = "\\fB" + strongCloseTag = "\\fP" + breakTag = "\n.br\n" + paraTag = "\n.PP\n" + hruleTag = "\n.ti 0\n\\l'\\n(.lu'\n" + linkTag = "\n\\[la]" + linkCloseTag = "\\[ra]" + codespanTag = "\\fB\\fC" + codespanCloseTag = "\\fR" + codeTag = "\n.PP\n.RS\n\n.nf\n" + codeCloseTag = "\n.fi\n.RE\n" + quoteTag = "\n.PP\n.RS\n" + quoteCloseTag = "\n.RE\n" + listTag = "\n.RS\n" + listCloseTag = "\n.RE\n" + arglistTag = "\n.TP\n" + tableStart = "\n.TS\nallbox;\n" + tableEnd = ".TE\n" + tableCellStart = "T{\n" + tableCellEnd = "\nT}\n" +) + +// NewRoffRenderer creates a new blackfriday Renderer for generating roff documents +// from markdown +func NewRoffRenderer() *roffRenderer { // nolint: golint + var extensions blackfriday.Extensions + + extensions |= blackfriday.NoIntraEmphasis + extensions |= blackfriday.Tables + extensions |= blackfriday.FencedCode + extensions |= blackfriday.SpaceHeadings + extensions |= blackfriday.Footnotes + extensions |= blackfriday.Titleblock + extensions |= blackfriday.DefinitionLists + return &roffRenderer{ + extensions: extensions, + } +} + +// GetExtensions returns the list of extensions used by this renderer implementation +func (r *roffRenderer) GetExtensions() blackfriday.Extensions { + return r.extensions +} + +// RenderHeader handles outputting the header at document start +func (r *roffRenderer) RenderHeader(w io.Writer, ast *blackfriday.Node) { + // disable hyphenation + out(w, ".nh\n") +} + +// RenderFooter handles outputting the footer at the document end; the roff +// renderer has no footer information +func (r *roffRenderer) RenderFooter(w io.Writer, ast *blackfriday.Node) { +} + +// RenderNode is called for each node in a markdown document; based on the node +// type the equivalent roff output is sent to the writer +func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + + var walkAction = blackfriday.GoToNext + + switch node.Type { + case blackfriday.Text: + r.handleText(w, node, entering) + case blackfriday.Softbreak: + out(w, crTag) + case blackfriday.Hardbreak: + out(w, breakTag) + case blackfriday.Emph: + if entering { + out(w, emphTag) + } else { + out(w, emphCloseTag) + } + case blackfriday.Strong: + if entering { + out(w, strongTag) + } else { + out(w, strongCloseTag) + } + case blackfriday.Link: + if !entering { + out(w, linkTag+string(node.LinkData.Destination)+linkCloseTag) + } + case blackfriday.Image: + // ignore images + walkAction = blackfriday.SkipChildren + case blackfriday.Code: + out(w, codespanTag) + escapeSpecialChars(w, node.Literal) + out(w, codespanCloseTag) + case blackfriday.Document: + break + case blackfriday.Paragraph: + // roff .PP markers break lists + if r.listDepth > 0 { + return blackfriday.GoToNext + } + if entering { + out(w, paraTag) + } else { + out(w, crTag) + } + case blackfriday.BlockQuote: + if entering { + out(w, quoteTag) + } else { + out(w, quoteCloseTag) + } + case blackfriday.Heading: + r.handleHeading(w, node, entering) + case blackfriday.HorizontalRule: + out(w, hruleTag) + case blackfriday.List: + r.handleList(w, node, entering) + case blackfriday.Item: + r.handleItem(w, node, entering) + case blackfriday.CodeBlock: + out(w, codeTag) + escapeSpecialChars(w, node.Literal) + out(w, codeCloseTag) + case blackfriday.Table: + r.handleTable(w, node, entering) + case blackfriday.TableCell: + r.handleTableCell(w, node, entering) + case blackfriday.TableHead: + case blackfriday.TableBody: + case blackfriday.TableRow: + // no action as cell entries do all the nroff formatting + return blackfriday.GoToNext + default: + fmt.Fprintln(os.Stderr, "WARNING: go-md2man does not handle node type "+node.Type.String()) + } + return walkAction +} + +func (r *roffRenderer) handleText(w io.Writer, node *blackfriday.Node, entering bool) { + var ( + start, end string + ) + // handle special roff table cell text encapsulation + if node.Parent.Type == blackfriday.TableCell { + if len(node.Literal) > 30 { + start = tableCellStart + end = tableCellEnd + } else { + // end rows that aren't terminated by "tableCellEnd" with a cr if end of row + if node.Parent.Next == nil && !node.Parent.IsHeader { + end = crTag + } + } + } + out(w, start) + escapeSpecialChars(w, node.Literal) + out(w, end) +} + +func (r *roffRenderer) handleHeading(w io.Writer, node *blackfriday.Node, entering bool) { + if entering { + switch node.Level { + case 1: + if !r.firstHeader { + out(w, titleHeader) + r.firstHeader = true + break + } + out(w, topLevelHeader) + case 2: + out(w, secondLevelHdr) + default: + out(w, otherHeader) + } + } +} + +func (r *roffRenderer) handleList(w io.Writer, node *blackfriday.Node, entering bool) { + openTag := listTag + closeTag := listCloseTag + if node.ListFlags&blackfriday.ListTypeDefinition != 0 { + // tags for definition lists handled within Item node + openTag = "" + closeTag = "" + } + if entering { + r.listDepth++ + if node.ListFlags&blackfriday.ListTypeOrdered != 0 { + r.listCounters = append(r.listCounters, 1) + } + out(w, openTag) + } else { + if node.ListFlags&blackfriday.ListTypeOrdered != 0 { + r.listCounters = r.listCounters[:len(r.listCounters)-1] + } + out(w, closeTag) + r.listDepth-- + } +} + +func (r *roffRenderer) handleItem(w io.Writer, node *blackfriday.Node, entering bool) { + if entering { + if node.ListFlags&blackfriday.ListTypeOrdered != 0 { + out(w, fmt.Sprintf(".IP \"%3d.\" 5\n", r.listCounters[len(r.listCounters)-1])) + r.listCounters[len(r.listCounters)-1]++ + } else if node.ListFlags&blackfriday.ListTypeDefinition != 0 { + // state machine for handling terms and following definitions + // since blackfriday does not distinguish them properly, nor + // does it seperate them into separate lists as it should + if !r.defineTerm { + out(w, arglistTag) + r.defineTerm = true + } else { + r.defineTerm = false + } + } else { + out(w, ".IP \\(bu 2\n") + } + } else { + out(w, "\n") + } +} + +func (r *roffRenderer) handleTable(w io.Writer, node *blackfriday.Node, entering bool) { + if entering { + out(w, tableStart) + //call walker to count cells (and rows?) so format section can be produced + columns := countColumns(node) + out(w, strings.Repeat("l ", columns)+"\n") + out(w, strings.Repeat("l ", columns)+".\n") + } else { + out(w, tableEnd) + } +} + +func (r *roffRenderer) handleTableCell(w io.Writer, node *blackfriday.Node, entering bool) { + var ( + start, end string + ) + if node.IsHeader { + start = codespanTag + end = codespanCloseTag + } + if entering { + if node.Prev != nil && node.Prev.Type == blackfriday.TableCell { + out(w, "\t"+start) + } else { + out(w, start) + } + } else { + // need to carriage return if we are at the end of the header row + if node.IsHeader && node.Next == nil { + end = end + crTag + } + out(w, end) + } +} + +// because roff format requires knowing the column count before outputting any table +// data we need to walk a table tree and count the columns +func countColumns(node *blackfriday.Node) int { + var columns int + + node.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + switch node.Type { + case blackfriday.TableRow: + if !entering { + return blackfriday.Terminate + } + case blackfriday.TableCell: + if entering { + columns++ + } + default: + } + return blackfriday.GoToNext + }) + return columns +} + +func out(w io.Writer, output string) { + io.WriteString(w, output) // nolint: errcheck +} + +func needsBackslash(c byte) bool { + for _, r := range []byte("-_&\\~") { + if c == r { + return true + } + } + return false +} + +func escapeSpecialChars(w io.Writer, text []byte) { + for i := 0; i < len(text); i++ { + // escape initial apostrophe or period + if len(text) >= 1 && (text[0] == '\'' || text[0] == '.') { + out(w, "\\&") + } + + // directly copy normal characters + org := i + + for i < len(text) && !needsBackslash(text[i]) { + i++ + } + if i > org { + w.Write(text[org:i]) // nolint: errcheck + } + + // escape a character + if i >= len(text) { + break + } + + w.Write([]byte{'\\', text[i]}) // nolint: errcheck + } +} diff --git a/vendor/github.com/matryer/moq/.gitignore b/vendor/github.com/matryer/moq/.gitignore new file mode 100644 index 000000000..b15784e0c --- /dev/null +++ b/vendor/github.com/matryer/moq/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +.vscode diff --git a/vendor/github.com/matryer/moq/.travis.yml b/vendor/github.com/matryer/moq/.travis.yml new file mode 100644 index 000000000..1bcf6df60 --- /dev/null +++ b/vendor/github.com/matryer/moq/.travis.yml @@ -0,0 +1,23 @@ +language: go + +sudo: false + +branches: + only: + - master + +go: + - 1.11.x + - 1.12.x + - 1.13.x + - tip + +before_install: + - go get golang.org/x/lint/golint + +before_script: + - go vet ./... + - golint ./... + +script: + - go test -v ./... diff --git a/vendor/github.com/matryer/moq/LICENSE b/vendor/github.com/matryer/moq/LICENSE new file mode 100644 index 000000000..157d9d25d --- /dev/null +++ b/vendor/github.com/matryer/moq/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Mat Ryer and David Hernandez + +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. diff --git a/vendor/github.com/matryer/moq/README.md b/vendor/github.com/matryer/moq/README.md new file mode 100644 index 000000000..5327c44e9 --- /dev/null +++ b/vendor/github.com/matryer/moq/README.md @@ -0,0 +1,110 @@ +![moq logo](moq-logo-small.png) [![Build Status](https://travis-ci.org/matryer/moq.svg?branch=master)](https://travis-ci.org/matryer/moq) [![Go Report Card](https://goreportcard.com/badge/github.com/matryer/moq)](https://goreportcard.com/report/github.com/matryer/moq) + +Interface mocking tool for go generate. + +By [Mat Ryer](https://twitter.com/matryer) and [David Hernandez](https://github.com/dahernan), with ideas lovingly stolen from [Ernesto Jimenez](https://github.com/ernesto-jimenez). + +### What is Moq? + +Moq is a tool that generates a struct from any interface. The struct can be used in test code as a mock of the interface. + +![Preview](preview.png) + +above: Moq generates the code on the right. + +You can read more in the [Meet Moq blog post](http://bit.ly/meetmoq). + +### Installing + +To start using Moq, just run go get: +``` +$ go get github.com/matryer/moq +``` + +### Usage + +``` +moq [flags] destination interface [interface2 [interface3 [...]]] + -out string + output file (default stdout) + -pkg string + package name (default will infer) +Specifying an alias for the mock is also supported with the format 'interface:alias' +Ex: moq -pkg different . MyInterface:MyMock +``` + +In a command line: + +``` +$ moq -out mocks_test.go . MyInterface +``` + +In code (for go generate): + +```go +package my + +//go:generate moq -out myinterface_moq_test.go . MyInterface + +type MyInterface interface { + Method1() error + Method2(i int) +} +``` + +Then run `go generate` for your package. + +### How to use it + +Mocking interfaces is a nice way to write unit tests where you can easily control the behaviour of the mocked object. + +Moq creates a struct that has a function field for each method, which you can declare in your test code. + +In this example, Moq generated the `EmailSenderMock` type: + +```go +func TestCompleteSignup(t *testing.T) { + + var sentTo string + + mockedEmailSender = &EmailSenderMock{ + SendFunc: func(to, subject, body string) error { + sentTo = to + return nil + }, + } + + CompleteSignUp("me@email.com", mockedEmailSender) + + callsToSend := len(mockedEmailSender.SendCalls()) + if callsToSend != 1 { + t.Errorf("Send was called %d times", callsToSend) + } + if sentTo != "me@email.com" { + t.Errorf("unexpected recipient: %s", sentTo) + } + +} + +func CompleteSignUp(to string, sender EmailSender) { + // TODO: this +} +``` + +The mocked structure implements the interface, where each method calls the associated function field. + +## Tips + +* Keep mocked logic inside the test that is using it +* Only mock the fields you need +* It will panic if a nil function gets called +* Name arguments in the interface for a better experience +* Use closured variables inside your test function to capture details about the calls to the methods +* Use `.MethodCalls()` to track the calls +* Use `go:generate` to invoke the `moq` command + +## License + +The Moq project (and all code) is licensed under the [MIT License](LICENSE). + +The Moq logo was created by [Chris Ryer](http://chrisryer.co.uk) and is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/). diff --git a/vendor/github.com/matryer/moq/main.go b/vendor/github.com/matryer/moq/main.go new file mode 100644 index 000000000..cd246cc8f --- /dev/null +++ b/vendor/github.com/matryer/moq/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "bytes" + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + + "github.com/matryer/moq/pkg/moq" +) + +type userFlags struct { + outFile string + pkgName string + args []string +} + +func main() { + var flags userFlags + flag.StringVar(&flags.outFile, "out", "", "output file (default stdout)") + flag.StringVar(&flags.pkgName, "pkg", "", "package name (default will infer)") + + flag.Usage = func() { + fmt.Println(`moq [flags] destination interface [interface2 [interface3 [...]]]`) + flag.PrintDefaults() + fmt.Println(`Specifying an alias for the mock is also supported with the format 'interface:alias'`) + fmt.Println(`Ex: moq -pkg different . MyInterface:MyMock`) + } + + flag.Parse() + flags.args = flag.Args() + + if err := run(flags); err != nil { + fmt.Fprintln(os.Stderr, err) + flag.Usage() + os.Exit(1) + } +} + +func run(flags userFlags) error { + if len(flags.args) < 2 { + return errors.New("not enough arguments") + } + + var buf bytes.Buffer + var out io.Writer = os.Stdout + if flags.outFile != "" { + out = &buf + } + + destination := flags.args[0] + args := flags.args[1:] + m, err := moq.New(destination, flags.pkgName) + if err != nil { + return err + } + + if err = m.Mock(out, args...); err != nil { + return err + } + + if flags.outFile == "" { + return nil + } + + // create the file + err = os.MkdirAll(filepath.Dir(flags.outFile), 0755) + if err != nil { + return err + } + + return ioutil.WriteFile(flags.outFile, buf.Bytes(), 0644) +} diff --git a/vendor/github.com/matryer/moq/moq-logo-small.png b/vendor/github.com/matryer/moq/moq-logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..7a71c177ec9f4051b6e0f0e8bddbd239db3d8efd GIT binary patch literal 32570 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/matryer/moq/moq-logo.png b/vendor/github.com/matryer/moq/moq-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7eae08f6f4df0ad596922f8004ceddcebbea9f8b GIT binary patch literal 29562 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 1 { + return nil, errors.New("More than one package was found") + } + return pkgs[0], nil +} + +func parseInterfaceName(name string) (ifaceName, mockName string) { + parts := strings.SplitN(name, ":", 2) + ifaceName = parts[0] + mockName = ifaceName + "Mock" + if len(parts) == 2 { + mockName = parts[1] + } + return +} + +type doc struct { + PackageName string + SourcePackagePrefix string + Objects []obj + Imports []string +} + +type obj struct { + InterfaceName string + MockName string + Methods []*method +} +type method struct { + Name string + Params []*param + Returns []*param +} + +func (m *method) Arglist() string { + params := make([]string, len(m.Params)) + for i, p := range m.Params { + params[i] = p.String() + } + return strings.Join(params, ", ") +} + +func (m *method) ArgCallList() string { + params := make([]string, len(m.Params)) + for i, p := range m.Params { + params[i] = p.CallName() + } + return strings.Join(params, ", ") +} + +func (m *method) ReturnArglist() string { + params := make([]string, len(m.Returns)) + for i, p := range m.Returns { + params[i] = p.TypeString() + } + if len(m.Returns) > 1 { + return fmt.Sprintf("(%s)", strings.Join(params, ", ")) + } + return strings.Join(params, ", ") +} + +type param struct { + Name string + Type string + Variadic bool +} + +func (p param) String() string { + return fmt.Sprintf("%s %s", p.Name, p.TypeString()) +} + +func (p param) CallName() string { + if p.Variadic { + return p.Name + "..." + } + return p.Name +} + +func (p param) TypeString() string { + if p.Variadic { + return "..." + p.Type[2:] + } + return p.Type +} + +var templateFuncs = template.FuncMap{ + "Exported": func(s string) string { + if s == "" { + return "" + } + for _, initialism := range golintInitialisms { + if strings.ToUpper(s) == initialism { + return initialism + } + } + return strings.ToUpper(s[0:1]) + s[1:] + }, +} + +// stripVendorPath strips the vendor dir prefix from a package path. +// For example we might encounter an absolute path like +// github.com/foo/bar/vendor/github.com/pkg/errors which is resolved +// to github.com/pkg/errors. +func stripVendorPath(p string) string { + parts := strings.Split(p, "/vendor/") + if len(parts) == 1 { + return p + } + return strings.TrimLeft(path.Join(parts[1:]...), "/") +} + +// stripGopath takes the directory to a package and remove the gopath to get the +// canonical package name. +// +// taken from https://github.com/ernesto-jimenez/gogen +// Copyright (c) 2015 Ernesto Jiménez +func stripGopath(p string) string { + for _, gopath := range gopaths() { + p = strings.TrimPrefix(p, path.Join(gopath, "src")+"/") + } + return p +} + +func gopaths() []string { + return strings.Split(os.Getenv("GOPATH"), string(filepath.ListSeparator)) +} diff --git a/vendor/github.com/matryer/moq/pkg/moq/template.go b/vendor/github.com/matryer/moq/pkg/moq/template.go new file mode 100644 index 000000000..bc33de236 --- /dev/null +++ b/vendor/github.com/matryer/moq/pkg/moq/template.go @@ -0,0 +1,107 @@ +package moq + +// moqImports are the imports all moq files get. +var moqImports = []string{} + +// moqTemplate is the template for mocked code. +var moqTemplate = `// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package {{.PackageName}} +{{- $sourcePackagePrefix := .SourcePackagePrefix}} + +import ( +{{- range .Imports }} + "{{.}}" +{{- end }} +) + +{{ range $i, $obj := .Objects -}} +var ( +{{- range .Methods }} + lock{{$obj.MockName}}{{.Name}} sync.RWMutex +{{- end }} +) + +// Ensure, that {{.MockName}} does implement {{$sourcePackagePrefix}}{{.InterfaceName}}. +// If this is not the case, regenerate this file with moq. +var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.MockName}}{} + +// {{.MockName}} is a mock implementation of {{$sourcePackagePrefix}}{{.InterfaceName}}. +// +// func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) { +// +// // make and configure a mocked {{$sourcePackagePrefix}}{{.InterfaceName}} +// mocked{{.InterfaceName}} := &{{.MockName}}{ {{ range .Methods }} +// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} { +// panic("mock out the {{.Name}} method") +// },{{- end }} +// } +// +// // use mocked{{.InterfaceName}} in code that requires {{$sourcePackagePrefix}}{{.InterfaceName}} +// // and then make assertions. +// +// } +type {{.MockName}} struct { +{{- range .Methods }} + // {{.Name}}Func mocks the {{.Name}} method. + {{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}} +{{ end }} + // calls tracks calls to the methods. + calls struct { +{{- range .Methods }} + // {{ .Name }} holds details about calls to the {{.Name}} method. + {{ .Name }} []struct { + {{- range .Params }} + // {{ .Name | Exported }} is the {{ .Name }} argument value. + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } +{{- end }} + } +} +{{ range .Methods }} +// {{.Name}} calls {{.Name}}Func. +func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { + if mock.{{.Name}}Func == nil { + panic("{{$obj.MockName}}.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called") + } + callInfo := struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + }{ + {{- range .Params }} + {{ .Name | Exported }}: {{ .Name }}, + {{- end }} + } + lock{{$obj.MockName}}{{.Name}}.Lock() + mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo) + lock{{$obj.MockName}}{{.Name}}.Unlock() +{{- if .ReturnArglist }} + return mock.{{.Name}}Func({{.ArgCallList}}) +{{- else }} + mock.{{.Name}}Func({{.ArgCallList}}) +{{- end }} +} + +// {{.Name}}Calls gets all the calls that were made to {{.Name}}. +// Check the length with: +// len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls()) +func (mock *{{$obj.MockName}}) {{.Name}}Calls() []struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } { + var calls []struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } + lock{{$obj.MockName}}{{.Name}}.RLock() + calls = mock.calls.{{.Name}} + lock{{$obj.MockName}}{{.Name}}.RUnlock() + return calls +} +{{ end -}} +{{ end -}}` diff --git a/vendor/github.com/matryer/moq/preview.png b/vendor/github.com/matryer/moq/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..8fa7a627479e4305ab1feb607f02e24baab211d5 GIT binary patch literal 743543 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ḅFb1Riw|NfE4^U&^Y`LlHQxG^=|gAX+mpG;&^ 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® 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 z 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

pv@PCl|*QJx1^I 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

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

}6T8u4i&;JEZ(1wpo|o=>supy$SV)7!!*y)! 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

;Vd6H)ttQ_D<78& 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

gvZ>U||B~9j%f5&ym356A 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
-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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml index d4b92663b..9159de03e 100644 --- a/vendor/github.com/pkg/errors/.travis.yml +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -1,15 +1,10 @@ language: go go_import_path: github.com/pkg/errors go: - - 1.4.x - - 1.5.x - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - 1.11.x + - 1.12.x + - 1.13.x - tip script: - - go test -v ./... + - make check diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile new file mode 100644 index 000000000..ce9d7cded --- /dev/null +++ b/vendor/github.com/pkg/errors/Makefile @@ -0,0 +1,44 @@ +PKGS := github.com/pkg/errors +SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) +GO := go + +check: test vet gofmt misspell unconvert staticcheck ineffassign unparam + +test: + $(GO) test $(PKGS) + +vet: | test + $(GO) vet $(PKGS) + +staticcheck: + $(GO) get honnef.co/go/tools/cmd/staticcheck + staticcheck -checks all $(PKGS) + +misspell: + $(GO) get github.com/client9/misspell/cmd/misspell + misspell \ + -locale GB \ + -error \ + *.md *.go + +unconvert: + $(GO) get github.com/mdempsky/unconvert + unconvert -v $(PKGS) + +ineffassign: + $(GO) get github.com/gordonklaus/ineffassign + find $(SRCDIRS) -name '*.go' | xargs ineffassign + +pedantic: check errcheck + +unparam: + $(GO) get mvdan.cc/unparam + unparam ./... + +errcheck: + $(GO) get github.com/kisielk/errcheck + errcheck $(PKGS) + +gofmt: + @echo Checking code is gofmted + @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md index 6483ba2af..54dfdcb12 100644 --- a/vendor/github.com/pkg/errors/README.md +++ b/vendor/github.com/pkg/errors/README.md @@ -41,11 +41,18 @@ default: [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). +## Roadmap + +With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: + +- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) +- 1.0. Final release. + ## Contributing -We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. +Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. -Before proposing a change, please discuss your change by raising an issue. +Before sending a PR, please discuss your change by raising an issue. ## License diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go index 7421f326f..161aea258 100644 --- a/vendor/github.com/pkg/errors/errors.go +++ b/vendor/github.com/pkg/errors/errors.go @@ -82,7 +82,7 @@ // // if err, ok := err.(stackTracer); ok { // for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d", f) +// fmt.Printf("%+s:%d\n", f, f) // } // } // @@ -159,6 +159,9 @@ type withStack struct { func (w *withStack) Cause() error { return w.error } +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withStack) Unwrap() error { return w.error } + func (w *withStack) Format(s fmt.State, verb rune) { switch verb { case 'v': @@ -241,6 +244,9 @@ type withMessage struct { func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } func (w *withMessage) Cause() error { return w.cause } +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withMessage) Unwrap() error { return w.cause } + func (w *withMessage) Format(s fmt.State, verb rune) { switch verb { case 'v': diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go new file mode 100644 index 000000000..be0d10d0c --- /dev/null +++ b/vendor/github.com/pkg/errors/go113.go @@ -0,0 +1,38 @@ +// +build go1.13 + +package errors + +import ( + stderrors "errors" +) + +// Is reports whether any error in err's chain matches target. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error is considered to match a target if it is equal to that target or if +// it implements a method Is(error) bool such that Is(target) returns true. +func Is(err, target error) bool { return stderrors.Is(err, target) } + +// As finds the first error in err's chain that matches target, and if so, sets +// target to that error value and returns true. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error matches target if the error's concrete value is assignable to the value +// pointed to by target, or if the error has a method As(interface{}) bool such that +// As(target) returns true. In the latter case, the As method is responsible for +// setting target. +// +// As will panic if target is not a non-nil pointer to either a type that implements +// error, or to any interface type. As returns false if err is nil. +func As(err error, target interface{}) bool { return stderrors.As(err, target) } + +// Unwrap returns the result of calling the Unwrap method on err, if err's +// type contains an Unwrap method returning error. +// Otherwise, Unwrap returns nil. +func Unwrap(err error) error { + return stderrors.Unwrap(err) +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go index 2874a048c..779a8348f 100644 --- a/vendor/github.com/pkg/errors/stack.go +++ b/vendor/github.com/pkg/errors/stack.go @@ -5,10 +5,13 @@ import ( "io" "path" "runtime" + "strconv" "strings" ) // Frame represents a program counter inside a stack frame. +// For historical reasons if Frame is interpreted as a uintptr +// its value represents the program counter + 1. type Frame uintptr // pc returns the program counter for this frame; @@ -37,6 +40,15 @@ func (f Frame) line() int { return line } +// name returns the name of this function, if known. +func (f Frame) name() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + return fn.Name() +} + // Format formats the frame according to the fmt.Formatter interface. // // %s source file @@ -54,22 +66,16 @@ func (f Frame) Format(s fmt.State, verb rune) { case 's': switch { case s.Flag('+'): - pc := f.pc() - fn := runtime.FuncForPC(pc) - if fn == nil { - io.WriteString(s, "unknown") - } else { - file, _ := fn.FileLine(pc) - fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) - } + io.WriteString(s, f.name()) + io.WriteString(s, "\n\t") + io.WriteString(s, f.file()) default: io.WriteString(s, path.Base(f.file())) } case 'd': - fmt.Fprintf(s, "%d", f.line()) + io.WriteString(s, strconv.Itoa(f.line())) case 'n': - name := runtime.FuncForPC(f.pc()).Name() - io.WriteString(s, funcname(name)) + io.WriteString(s, funcname(f.name())) case 'v': f.Format(s, 's') io.WriteString(s, ":") @@ -77,6 +83,16 @@ func (f Frame) Format(s fmt.State, verb rune) { } } +// MarshalText formats a stacktrace Frame as a text string. The output is the +// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. +func (f Frame) MarshalText() ([]byte, error) { + name := f.name() + if name == "unknown" { + return []byte(name), nil + } + return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil +} + // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). type StackTrace []Frame @@ -94,18 +110,32 @@ func (st StackTrace) Format(s fmt.State, verb rune) { switch { case s.Flag('+'): for _, f := range st { - fmt.Fprintf(s, "\n%+v", f) + io.WriteString(s, "\n") + f.Format(s, verb) } case s.Flag('#'): fmt.Fprintf(s, "%#v", []Frame(st)) default: - fmt.Fprintf(s, "%v", []Frame(st)) + st.formatSlice(s, verb) } case 's': - fmt.Fprintf(s, "%s", []Frame(st)) + st.formatSlice(s, verb) } } +// formatSlice will format this StackTrace into the given buffer as a slice of +// Frame, only valid when called with '%s' or '%v'. +func (st StackTrace) formatSlice(s fmt.State, verb rune) { + io.WriteString(s, "[") + for i, f := range st { + if i > 0 { + io.WriteString(s, " ") + } + f.Format(s, verb) + } + io.WriteString(s, "]") +} + // stack represents a stack of program counters. type stack []uintptr diff --git a/vendor/github.com/russross/blackfriday/v2/.gitignore b/vendor/github.com/russross/blackfriday/v2/.gitignore new file mode 100644 index 000000000..75623dccc --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/.gitignore @@ -0,0 +1,8 @@ +*.out +*.swp +*.8 +*.6 +_obj +_test* +markdown +tags diff --git a/vendor/github.com/russross/blackfriday/v2/.travis.yml b/vendor/github.com/russross/blackfriday/v2/.travis.yml new file mode 100644 index 000000000..b0b525a5a --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/.travis.yml @@ -0,0 +1,17 @@ +sudo: false +language: go +go: + - "1.10.x" + - "1.11.x" + - tip +matrix: + fast_finish: true + allow_failures: + - go: tip +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d -s .) + - go tool vet . + - go test -v ./... diff --git a/vendor/github.com/russross/blackfriday/v2/LICENSE.txt b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt new file mode 100644 index 000000000..2885af360 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt @@ -0,0 +1,29 @@ +Blackfriday is distributed under the Simplified BSD License: + +> Copyright © 2011 Russ Ross +> All rights reserved. +> +> Redistribution and use in source and binary forms, with or without +> modification, are permitted provided that the following conditions +> are met: +> +> 1. Redistributions of source code must retain the above copyright +> notice, this list of conditions and the following disclaimer. +> +> 2. Redistributions in binary form must reproduce the above +> copyright notice, this list of conditions and the following +> disclaimer in the documentation and/or other materials provided with +> the distribution. +> +> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +> POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/russross/blackfriday/v2/README.md b/vendor/github.com/russross/blackfriday/v2/README.md new file mode 100644 index 000000000..d5a8649bd --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/README.md @@ -0,0 +1,291 @@ +Blackfriday [![Build Status](https://travis-ci.org/russross/blackfriday.svg?branch=master)](https://travis-ci.org/russross/blackfriday) +=========== + +Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It +is paranoid about its input (so you can safely feed it user-supplied +data), it is fast, it supports common extensions (tables, smart +punctuation substitutions, etc.), and it is safe for all utf-8 +(unicode) input. + +HTML output is currently supported, along with Smartypants +extensions. + +It started as a translation from C of [Sundown][3]. + + +Installation +------------ + +Blackfriday is compatible with any modern Go release. With Go 1.7 and git +installed: + + go get gopkg.in/russross/blackfriday.v2 + +will download, compile, and install the package into your `$GOPATH` +directory hierarchy. Alternatively, you can achieve the same if you +import it into a project: + + import "gopkg.in/russross/blackfriday.v2" + +and `go get` without parameters. + + +Versions +-------- + +Currently maintained and recommended version of Blackfriday is `v2`. It's being +developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the +documentation is available at +https://godoc.org/gopkg.in/russross/blackfriday.v2. + +It is `go get`-able via via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`, +but we highly recommend using package management tool like [dep][7] or +[Glide][8] and make use of semantic versioning. With package management you +should import `github.com/russross/blackfriday` and specify that you're using +version 2.0.0. + +Version 2 offers a number of improvements over v1: + +* Cleaned up API +* A separate call to [`Parse`][4], which produces an abstract syntax tree for + the document +* Latest bug fixes +* Flexibility to easily add your own rendering extensions + +Potential drawbacks: + +* Our benchmarks show v2 to be slightly slower than v1. Currently in the + ballpark of around 15%. +* API breakage. If you can't afford modifying your code to adhere to the new API + and don't care too much about the new features, v2 is probably not for you. +* Several bug fixes are trailing behind and still need to be forward-ported to + v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for + tracking. + +Usage +----- + +For the most sensible markdown processing, it is as simple as getting your input +into a byte slice and calling: + +```go +output := blackfriday.Run(input) +``` + +Your input will be parsed and the output rendered with a set of most popular +extensions enabled. If you want the most basic feature set, corresponding with +the bare Markdown specification, use: + +```go +output := blackfriday.Run(input, blackfriday.WithNoExtensions()) +``` + +### Sanitize untrusted content + +Blackfriday itself does nothing to protect against malicious content. If you are +dealing with user-supplied markdown, we recommend running Blackfriday's output +through HTML sanitizer such as [Bluemonday][5]. + +Here's an example of simple usage of Blackfriday together with Bluemonday: + +```go +import ( + "github.com/microcosm-cc/bluemonday" + "github.com/russross/blackfriday" +) + +// ... +unsafe := blackfriday.Run(input) +html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) +``` + +### Custom options + +If you want to customize the set of options, use `blackfriday.WithExtensions`, +`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. + +You can also check out `blackfriday-tool` for a more complete example +of how to use it. Download and install it using: + + go get github.com/russross/blackfriday-tool + +This is a simple command-line tool that allows you to process a +markdown file using a standalone program. You can also browse the +source directly on github if you are just looking for some example +code: + +* + +Note that if you have not already done so, installing +`blackfriday-tool` will be sufficient to download and install +blackfriday in addition to the tool itself. The tool binary will be +installed in `$GOPATH/bin`. This is a statically-linked binary that +can be copied to wherever you need it without worrying about +dependencies and library versions. + + +Features +-------- + +All features of Sundown are supported, including: + +* **Compatibility**. The Markdown v1.0.3 test suite passes with + the `--tidy` option. Without `--tidy`, the differences are + mostly in whitespace and entity escaping, where blackfriday is + more consistent and cleaner. + +* **Common extensions**, including table support, fenced code + blocks, autolinks, strikethroughs, non-strict emphasis, etc. + +* **Safety**. Blackfriday is paranoid when parsing, making it safe + to feed untrusted user input without fear of bad things + happening. The test suite stress tests this and there are no + known inputs that make it crash. If you find one, please let me + know and send me the input that does it. + + NOTE: "safety" in this context means *runtime safety only*. In order to + protect yourself against JavaScript injection in untrusted content, see + [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). + +* **Fast processing**. It is fast enough to render on-demand in + most web applications without having to cache the output. + +* **Thread safety**. You can run multiple parsers in different + goroutines without ill effect. There is no dependence on global + shared state. + +* **Minimal dependencies**. Blackfriday only depends on standard + library packages in Go. The source code is pretty + self-contained, so it is easy to add to any project, including + Google App Engine projects. + +* **Standards compliant**. Output successfully validates using the + W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. + + +Extensions +---------- + +In addition to the standard markdown syntax, this package +implements the following extensions: + +* **Intra-word emphasis supression**. The `_` character is + commonly used inside words when discussing code, so having + markdown interpret it as an emphasis command is usually the + wrong thing. Blackfriday lets you treat all emphasis markers as + normal characters when they occur inside a word. + +* **Tables**. Tables can be created by drawing them in the input + using a simple syntax: + + ``` + Name | Age + --------|------ + Bob | 27 + Alice | 23 + ``` + +* **Fenced code blocks**. In addition to the normal 4-space + indentation to mark code blocks, you can explicitly mark them + and supply a language (to make syntax highlighting simple). Just + mark it like this: + + ```go + func getTrue() bool { + return true + } + ``` + + You can use 3 or more backticks to mark the beginning of the + block, and the same number to mark the end of the block. + +* **Definition lists**. A simple definition list is made of a single-line + term followed by a colon and the definition for that term. + + Cat + : Fluffy animal everyone likes + + Internet + : Vector of transmission for pictures of cats + + Terms must be separated from the previous definition by a blank line. + +* **Footnotes**. A marker in the text that will become a superscript number; + a footnote definition that will be placed in a list of footnotes at the + end of the document. A footnote looks like this: + + This is a footnote.[^1] + + [^1]: the footnote text. + +* **Autolinking**. Blackfriday can find URLs that have not been + explicitly marked as links and turn them into links. + +* **Strikethrough**. Use two tildes (`~~`) to mark text that + should be crossed out. + +* **Hard line breaks**. With this extension enabled newlines in the input + translate into line breaks in the output. This extension is off by default. + +* **Smart quotes**. Smartypants-style punctuation substitution is + supported, turning normal double- and single-quote marks into + curly quotes, etc. + +* **LaTeX-style dash parsing** is an additional option, where `--` + is translated into `–`, and `---` is translated into + `—`. This differs from most smartypants processors, which + turn a single hyphen into an ndash and a double hyphen into an + mdash. + +* **Smart fractions**, where anything that looks like a fraction + is translated into suitable HTML (instead of just a few special + cases like most smartypant processors). For example, `4/5` + becomes `45`, which renders as + 45. + + +Other renderers +--------------- + +Blackfriday is structured to allow alternative rendering engines. Here +are a few of note: + +* [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown): + provides a GitHub Flavored Markdown renderer with fenced code block + highlighting, clickable heading anchor links. + + It's not customizable, and its goal is to produce HTML output + equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), + except the rendering is performed locally. + +* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, + but for markdown. + +* [LaTeX output](https://github.com/Ambrevar/Blackfriday-LaTeX): + renders output as LaTeX. + +* [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer. + + +Todo +---- + +* More unit testing +* Improve unicode support. It does not understand all unicode + rules (about what constitutes a letter, a punctuation symbol, + etc.), so it may fail to detect word boundaries correctly in + some instances. It is safe on all utf-8 input. + + +License +------- + +[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) + + + [1]: https://daringfireball.net/projects/markdown/ "Markdown" + [2]: https://golang.org/ "Go Language" + [3]: https://github.com/vmg/sundown "Sundown" + [4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func" + [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" + [6]: https://labix.org/gopkg.in "gopkg.in" diff --git a/vendor/github.com/russross/blackfriday/v2/block.go b/vendor/github.com/russross/blackfriday/v2/block.go new file mode 100644 index 000000000..b8607474e --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/block.go @@ -0,0 +1,1590 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// Functions to parse block-level elements. +// + +package blackfriday + +import ( + "bytes" + "html" + "regexp" + "strings" + + "github.com/shurcooL/sanitized_anchor_name" +) + +const ( + charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" + escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" +) + +var ( + reBackslashOrAmp = regexp.MustCompile("[\\&]") + reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity) +) + +// Parse block-level data. +// Note: this function and many that it calls assume that +// the input buffer ends with a newline. +func (p *Markdown) block(data []byte) { + // this is called recursively: enforce a maximum depth + if p.nesting >= p.maxNesting { + return + } + p.nesting++ + + // parse out one block-level construct at a time + for len(data) > 0 { + // prefixed heading: + // + // # Heading 1 + // ## Heading 2 + // ... + // ###### Heading 6 + if p.isPrefixHeading(data) { + data = data[p.prefixHeading(data):] + continue + } + + // block of preformatted HTML: + // + //

+ if data[0] == '<' { + if i := p.html(data, true); i > 0 { + data = data[i:] + continue + } + } + + // title block + // + // % stuff + // % more stuff + // % even more stuff + if p.extensions&Titleblock != 0 { + if data[0] == '%' { + if i := p.titleBlock(data, true); i > 0 { + data = data[i:] + continue + } + } + } + + // blank lines. note: returns the # of bytes to skip + if i := p.isEmpty(data); i > 0 { + data = data[i:] + continue + } + + // indented code block: + // + // func max(a, b int) int { + // if a > b { + // return a + // } + // return b + // } + if p.codePrefix(data) > 0 { + data = data[p.code(data):] + continue + } + + // fenced code block: + // + // ``` go + // func fact(n int) int { + // if n <= 1 { + // return n + // } + // return n * fact(n-1) + // } + // ``` + if p.extensions&FencedCode != 0 { + if i := p.fencedCodeBlock(data, true); i > 0 { + data = data[i:] + continue + } + } + + // horizontal rule: + // + // ------ + // or + // ****** + // or + // ______ + if p.isHRule(data) { + p.addBlock(HorizontalRule, nil) + var i int + for i = 0; i < len(data) && data[i] != '\n'; i++ { + } + data = data[i:] + continue + } + + // block quote: + // + // > A big quote I found somewhere + // > on the web + if p.quotePrefix(data) > 0 { + data = data[p.quote(data):] + continue + } + + // table: + // + // Name | Age | Phone + // ------|-----|--------- + // Bob | 31 | 555-1234 + // Alice | 27 | 555-4321 + if p.extensions&Tables != 0 { + if i := p.table(data); i > 0 { + data = data[i:] + continue + } + } + + // an itemized/unordered list: + // + // * Item 1 + // * Item 2 + // + // also works with + or - + if p.uliPrefix(data) > 0 { + data = data[p.list(data, 0):] + continue + } + + // a numbered/ordered list: + // + // 1. Item 1 + // 2. Item 2 + if p.oliPrefix(data) > 0 { + data = data[p.list(data, ListTypeOrdered):] + continue + } + + // definition lists: + // + // Term 1 + // : Definition a + // : Definition b + // + // Term 2 + // : Definition c + if p.extensions&DefinitionLists != 0 { + if p.dliPrefix(data) > 0 { + data = data[p.list(data, ListTypeDefinition):] + continue + } + } + + // anything else must look like a normal paragraph + // note: this finds underlined headings, too + data = data[p.paragraph(data):] + } + + p.nesting-- +} + +func (p *Markdown) addBlock(typ NodeType, content []byte) *Node { + p.closeUnmatchedBlocks() + container := p.addChild(typ, 0) + container.content = content + return container +} + +func (p *Markdown) isPrefixHeading(data []byte) bool { + if data[0] != '#' { + return false + } + + if p.extensions&SpaceHeadings != 0 { + level := 0 + for level < 6 && level < len(data) && data[level] == '#' { + level++ + } + if level == len(data) || data[level] != ' ' { + return false + } + } + return true +} + +func (p *Markdown) prefixHeading(data []byte) int { + level := 0 + for level < 6 && level < len(data) && data[level] == '#' { + level++ + } + i := skipChar(data, level, ' ') + end := skipUntilChar(data, i, '\n') + skip := end + id := "" + if p.extensions&HeadingIDs != 0 { + j, k := 0, 0 + // find start/end of heading id + for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ { + } + for k = j + 1; k < end && data[k] != '}'; k++ { + } + // extract heading id iff found + if j < end && k < end { + id = string(data[j+2 : k]) + end = j + skip = k + 1 + for end > 0 && data[end-1] == ' ' { + end-- + } + } + } + for end > 0 && data[end-1] == '#' { + if isBackslashEscaped(data, end-1) { + break + } + end-- + } + for end > 0 && data[end-1] == ' ' { + end-- + } + if end > i { + if id == "" && p.extensions&AutoHeadingIDs != 0 { + id = sanitized_anchor_name.Create(string(data[i:end])) + } + block := p.addBlock(Heading, data[i:end]) + block.HeadingID = id + block.Level = level + } + return skip +} + +func (p *Markdown) isUnderlinedHeading(data []byte) int { + // test of level 1 heading + if data[0] == '=' { + i := skipChar(data, 1, '=') + i = skipChar(data, i, ' ') + if i < len(data) && data[i] == '\n' { + return 1 + } + return 0 + } + + // test of level 2 heading + if data[0] == '-' { + i := skipChar(data, 1, '-') + i = skipChar(data, i, ' ') + if i < len(data) && data[i] == '\n' { + return 2 + } + return 0 + } + + return 0 +} + +func (p *Markdown) titleBlock(data []byte, doRender bool) int { + if data[0] != '%' { + return 0 + } + splitData := bytes.Split(data, []byte("\n")) + var i int + for idx, b := range splitData { + if !bytes.HasPrefix(b, []byte("%")) { + i = idx // - 1 + break + } + } + + data = bytes.Join(splitData[0:i], []byte("\n")) + consumed := len(data) + data = bytes.TrimPrefix(data, []byte("% ")) + data = bytes.Replace(data, []byte("\n% "), []byte("\n"), -1) + block := p.addBlock(Heading, data) + block.Level = 1 + block.IsTitleblock = true + + return consumed +} + +func (p *Markdown) html(data []byte, doRender bool) int { + var i, j int + + // identify the opening tag + if data[0] != '<' { + return 0 + } + curtag, tagfound := p.htmlFindTag(data[1:]) + + // handle special cases + if !tagfound { + // check for an HTML comment + if size := p.htmlComment(data, doRender); size > 0 { + return size + } + + // check for an
tag + if size := p.htmlHr(data, doRender); size > 0 { + return size + } + + // no special case recognized + return 0 + } + + // look for an unindented matching closing tag + // followed by a blank line + found := false + /* + closetag := []byte("\n") + j = len(curtag) + 1 + for !found { + // scan for a closing tag at the beginning of a line + if skip := bytes.Index(data[j:], closetag); skip >= 0 { + j += skip + len(closetag) + } else { + break + } + + // see if it is the only thing on the line + if skip := p.isEmpty(data[j:]); skip > 0 { + // see if it is followed by a blank line/eof + j += skip + if j >= len(data) { + found = true + i = j + } else { + if skip := p.isEmpty(data[j:]); skip > 0 { + j += skip + found = true + i = j + } + } + } + } + */ + + // if not found, try a second pass looking for indented match + // but not if tag is "ins" or "del" (following original Markdown.pl) + if !found && curtag != "ins" && curtag != "del" { + i = 1 + for i < len(data) { + i++ + for i < len(data) && !(data[i-1] == '<' && data[i] == '/') { + i++ + } + + if i+2+len(curtag) >= len(data) { + break + } + + j = p.htmlFindEnd(curtag, data[i-1:]) + + if j > 0 { + i += j - 1 + found = true + break + } + } + } + + if !found { + return 0 + } + + // the end of the block has been found + if doRender { + // trim newlines + end := i + for end > 0 && data[end-1] == '\n' { + end-- + } + finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) + } + + return i +} + +func finalizeHTMLBlock(block *Node) { + block.Literal = block.content + block.content = nil +} + +// HTML comment, lax form +func (p *Markdown) htmlComment(data []byte, doRender bool) int { + i := p.inlineHTMLComment(data) + // needs to end with a blank line + if j := p.isEmpty(data[i:]); j > 0 { + size := i + j + if doRender { + // trim trailing newlines + end := size + for end > 0 && data[end-1] == '\n' { + end-- + } + block := p.addBlock(HTMLBlock, data[:end]) + finalizeHTMLBlock(block) + } + return size + } + return 0 +} + +// HR, which is the only self-closing block tag considered +func (p *Markdown) htmlHr(data []byte, doRender bool) int { + if len(data) < 4 { + return 0 + } + if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') { + return 0 + } + if data[3] != ' ' && data[3] != '/' && data[3] != '>' { + // not an
tag after all; at least not a valid one + return 0 + } + i := 3 + for i < len(data) && data[i] != '>' && data[i] != '\n' { + i++ + } + if i < len(data) && data[i] == '>' { + i++ + if j := p.isEmpty(data[i:]); j > 0 { + size := i + j + if doRender { + // trim newlines + end := size + for end > 0 && data[end-1] == '\n' { + end-- + } + finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) + } + return size + } + } + return 0 +} + +func (p *Markdown) htmlFindTag(data []byte) (string, bool) { + i := 0 + for i < len(data) && isalnum(data[i]) { + i++ + } + key := string(data[:i]) + if _, ok := blockTags[key]; ok { + return key, true + } + return "", false +} + +func (p *Markdown) htmlFindEnd(tag string, data []byte) int { + // assume data[0] == '<' && data[1] == '/' already tested + if tag == "hr" { + return 2 + } + // check if tag is a match + closetag := []byte("") + if !bytes.HasPrefix(data, closetag) { + return 0 + } + i := len(closetag) + + // check that the rest of the line is blank + skip := 0 + if skip = p.isEmpty(data[i:]); skip == 0 { + return 0 + } + i += skip + skip = 0 + + if i >= len(data) { + return i + } + + if p.extensions&LaxHTMLBlocks != 0 { + return i + } + if skip = p.isEmpty(data[i:]); skip == 0 { + // following line must be blank + return 0 + } + + return i + skip +} + +func (*Markdown) isEmpty(data []byte) int { + // it is okay to call isEmpty on an empty buffer + if len(data) == 0 { + return 0 + } + + var i int + for i = 0; i < len(data) && data[i] != '\n'; i++ { + if data[i] != ' ' && data[i] != '\t' { + return 0 + } + } + if i < len(data) && data[i] == '\n' { + i++ + } + return i +} + +func (*Markdown) isHRule(data []byte) bool { + i := 0 + + // skip up to three spaces + for i < 3 && data[i] == ' ' { + i++ + } + + // look at the hrule char + if data[i] != '*' && data[i] != '-' && data[i] != '_' { + return false + } + c := data[i] + + // the whole line must be the char or whitespace + n := 0 + for i < len(data) && data[i] != '\n' { + switch { + case data[i] == c: + n++ + case data[i] != ' ': + return false + } + i++ + } + + return n >= 3 +} + +// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data, +// and returns the end index if so, or 0 otherwise. It also returns the marker found. +// If info is not nil, it gets set to the syntax specified in the fence line. +func isFenceLine(data []byte, info *string, oldmarker string) (end int, marker string) { + i, size := 0, 0 + + // skip up to three spaces + for i < len(data) && i < 3 && data[i] == ' ' { + i++ + } + + // check for the marker characters: ~ or ` + if i >= len(data) { + return 0, "" + } + if data[i] != '~' && data[i] != '`' { + return 0, "" + } + + c := data[i] + + // the whole line must be the same char or whitespace + for i < len(data) && data[i] == c { + size++ + i++ + } + + // the marker char must occur at least 3 times + if size < 3 { + return 0, "" + } + marker = string(data[i-size : i]) + + // if this is the end marker, it must match the beginning marker + if oldmarker != "" && marker != oldmarker { + return 0, "" + } + + // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here + // into one, always get the info string, and discard it if the caller doesn't care. + if info != nil { + infoLength := 0 + i = skipChar(data, i, ' ') + + if i >= len(data) { + if i == len(data) { + return i, marker + } + return 0, "" + } + + infoStart := i + + if data[i] == '{' { + i++ + infoStart++ + + for i < len(data) && data[i] != '}' && data[i] != '\n' { + infoLength++ + i++ + } + + if i >= len(data) || data[i] != '}' { + return 0, "" + } + + // strip all whitespace at the beginning and the end + // of the {} block + for infoLength > 0 && isspace(data[infoStart]) { + infoStart++ + infoLength-- + } + + for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { + infoLength-- + } + i++ + i = skipChar(data, i, ' ') + } else { + for i < len(data) && !isverticalspace(data[i]) { + infoLength++ + i++ + } + } + + *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) + } + + if i == len(data) { + return i, marker + } + if i > len(data) || data[i] != '\n' { + return 0, "" + } + return i + 1, marker // Take newline into account. +} + +// fencedCodeBlock returns the end index if data contains a fenced code block at the beginning, +// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. +// If doRender is true, a final newline is mandatory to recognize the fenced code block. +func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { + var info string + beg, marker := isFenceLine(data, &info, "") + if beg == 0 || beg >= len(data) { + return 0 + } + + var work bytes.Buffer + work.Write([]byte(info)) + work.WriteByte('\n') + + for { + // safe to assume beg < len(data) + + // check for the end of the code block + fenceEnd, _ := isFenceLine(data[beg:], nil, marker) + if fenceEnd != 0 { + beg += fenceEnd + break + } + + // copy the current line + end := skipUntilChar(data, beg, '\n') + 1 + + // did we reach the end of the buffer without a closing marker? + if end >= len(data) { + return 0 + } + + // verbatim copy to the working buffer + if doRender { + work.Write(data[beg:end]) + } + beg = end + } + + if doRender { + block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer + block.IsFenced = true + finalizeCodeBlock(block) + } + + return beg +} + +func unescapeChar(str []byte) []byte { + if str[0] == '\\' { + return []byte{str[1]} + } + return []byte(html.UnescapeString(string(str))) +} + +func unescapeString(str []byte) []byte { + if reBackslashOrAmp.Match(str) { + return reEntityOrEscapedChar.ReplaceAllFunc(str, unescapeChar) + } + return str +} + +func finalizeCodeBlock(block *Node) { + if block.IsFenced { + newlinePos := bytes.IndexByte(block.content, '\n') + firstLine := block.content[:newlinePos] + rest := block.content[newlinePos+1:] + block.Info = unescapeString(bytes.Trim(firstLine, "\n")) + block.Literal = rest + } else { + block.Literal = block.content + } + block.content = nil +} + +func (p *Markdown) table(data []byte) int { + table := p.addBlock(Table, nil) + i, columns := p.tableHeader(data) + if i == 0 { + p.tip = table.Parent + table.Unlink() + return 0 + } + + p.addBlock(TableBody, nil) + + for i < len(data) { + pipes, rowStart := 0, i + for ; i < len(data) && data[i] != '\n'; i++ { + if data[i] == '|' { + pipes++ + } + } + + if pipes == 0 { + i = rowStart + break + } + + // include the newline in data sent to tableRow + if i < len(data) && data[i] == '\n' { + i++ + } + p.tableRow(data[rowStart:i], columns, false) + } + + return i +} + +// check if the specified position is preceded by an odd number of backslashes +func isBackslashEscaped(data []byte, i int) bool { + backslashes := 0 + for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' { + backslashes++ + } + return backslashes&1 == 1 +} + +func (p *Markdown) tableHeader(data []byte) (size int, columns []CellAlignFlags) { + i := 0 + colCount := 1 + for i = 0; i < len(data) && data[i] != '\n'; i++ { + if data[i] == '|' && !isBackslashEscaped(data, i) { + colCount++ + } + } + + // doesn't look like a table header + if colCount == 1 { + return + } + + // include the newline in the data sent to tableRow + j := i + if j < len(data) && data[j] == '\n' { + j++ + } + header := data[:j] + + // column count ignores pipes at beginning or end of line + if data[0] == '|' { + colCount-- + } + if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) { + colCount-- + } + + columns = make([]CellAlignFlags, colCount) + + // move on to the header underline + i++ + if i >= len(data) { + return + } + + if data[i] == '|' && !isBackslashEscaped(data, i) { + i++ + } + i = skipChar(data, i, ' ') + + // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3 + // and trailing | optional on last column + col := 0 + for i < len(data) && data[i] != '\n' { + dashes := 0 + + if data[i] == ':' { + i++ + columns[col] |= TableAlignmentLeft + dashes++ + } + for i < len(data) && data[i] == '-' { + i++ + dashes++ + } + if i < len(data) && data[i] == ':' { + i++ + columns[col] |= TableAlignmentRight + dashes++ + } + for i < len(data) && data[i] == ' ' { + i++ + } + if i == len(data) { + return + } + // end of column test is messy + switch { + case dashes < 3: + // not a valid column + return + + case data[i] == '|' && !isBackslashEscaped(data, i): + // marker found, now skip past trailing whitespace + col++ + i++ + for i < len(data) && data[i] == ' ' { + i++ + } + + // trailing junk found after last column + if col >= colCount && i < len(data) && data[i] != '\n' { + return + } + + case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount: + // something else found where marker was required + return + + case data[i] == '\n': + // marker is optional for the last column + col++ + + default: + // trailing junk found after last column + return + } + } + if col != colCount { + return + } + + p.addBlock(TableHead, nil) + p.tableRow(header, columns, true) + size = i + if size < len(data) && data[size] == '\n' { + size++ + } + return +} + +func (p *Markdown) tableRow(data []byte, columns []CellAlignFlags, header bool) { + p.addBlock(TableRow, nil) + i, col := 0, 0 + + if data[i] == '|' && !isBackslashEscaped(data, i) { + i++ + } + + for col = 0; col < len(columns) && i < len(data); col++ { + for i < len(data) && data[i] == ' ' { + i++ + } + + cellStart := i + + for i < len(data) && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' { + i++ + } + + cellEnd := i + + // skip the end-of-cell marker, possibly taking us past end of buffer + i++ + + for cellEnd > cellStart && cellEnd-1 < len(data) && data[cellEnd-1] == ' ' { + cellEnd-- + } + + cell := p.addBlock(TableCell, data[cellStart:cellEnd]) + cell.IsHeader = header + cell.Align = columns[col] + } + + // pad it out with empty columns to get the right number + for ; col < len(columns); col++ { + cell := p.addBlock(TableCell, nil) + cell.IsHeader = header + cell.Align = columns[col] + } + + // silently ignore rows with too many cells +} + +// returns blockquote prefix length +func (p *Markdown) quotePrefix(data []byte) int { + i := 0 + for i < 3 && i < len(data) && data[i] == ' ' { + i++ + } + if i < len(data) && data[i] == '>' { + if i+1 < len(data) && data[i+1] == ' ' { + return i + 2 + } + return i + 1 + } + return 0 +} + +// blockquote ends with at least one blank line +// followed by something without a blockquote prefix +func (p *Markdown) terminateBlockquote(data []byte, beg, end int) bool { + if p.isEmpty(data[beg:]) <= 0 { + return false + } + if end >= len(data) { + return true + } + return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0 +} + +// parse a blockquote fragment +func (p *Markdown) quote(data []byte) int { + block := p.addBlock(BlockQuote, nil) + var raw bytes.Buffer + beg, end := 0, 0 + for beg < len(data) { + end = beg + // Step over whole lines, collecting them. While doing that, check for + // fenced code and if one's found, incorporate it altogether, + // irregardless of any contents inside it + for end < len(data) && data[end] != '\n' { + if p.extensions&FencedCode != 0 { + if i := p.fencedCodeBlock(data[end:], false); i > 0 { + // -1 to compensate for the extra end++ after the loop: + end += i - 1 + break + } + } + end++ + } + if end < len(data) && data[end] == '\n' { + end++ + } + if pre := p.quotePrefix(data[beg:]); pre > 0 { + // skip the prefix + beg += pre + } else if p.terminateBlockquote(data, beg, end) { + break + } + // this line is part of the blockquote + raw.Write(data[beg:end]) + beg = end + } + p.block(raw.Bytes()) + p.finalize(block) + return end +} + +// returns prefix length for block code +func (p *Markdown) codePrefix(data []byte) int { + if len(data) >= 1 && data[0] == '\t' { + return 1 + } + if len(data) >= 4 && data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' { + return 4 + } + return 0 +} + +func (p *Markdown) code(data []byte) int { + var work bytes.Buffer + + i := 0 + for i < len(data) { + beg := i + for i < len(data) && data[i] != '\n' { + i++ + } + if i < len(data) && data[i] == '\n' { + i++ + } + + blankline := p.isEmpty(data[beg:i]) > 0 + if pre := p.codePrefix(data[beg:i]); pre > 0 { + beg += pre + } else if !blankline { + // non-empty, non-prefixed line breaks the pre + i = beg + break + } + + // verbatim copy to the working buffer + if blankline { + work.WriteByte('\n') + } else { + work.Write(data[beg:i]) + } + } + + // trim all the \n off the end of work + workbytes := work.Bytes() + eol := len(workbytes) + for eol > 0 && workbytes[eol-1] == '\n' { + eol-- + } + if eol != len(workbytes) { + work.Truncate(eol) + } + + work.WriteByte('\n') + + block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer + block.IsFenced = false + finalizeCodeBlock(block) + + return i +} + +// returns unordered list item prefix +func (p *Markdown) uliPrefix(data []byte) int { + i := 0 + // start with up to 3 spaces + for i < len(data) && i < 3 && data[i] == ' ' { + i++ + } + if i >= len(data)-1 { + return 0 + } + // need one of {'*', '+', '-'} followed by a space or a tab + if (data[i] != '*' && data[i] != '+' && data[i] != '-') || + (data[i+1] != ' ' && data[i+1] != '\t') { + return 0 + } + return i + 2 +} + +// returns ordered list item prefix +func (p *Markdown) oliPrefix(data []byte) int { + i := 0 + + // start with up to 3 spaces + for i < 3 && i < len(data) && data[i] == ' ' { + i++ + } + + // count the digits + start := i + for i < len(data) && data[i] >= '0' && data[i] <= '9' { + i++ + } + if start == i || i >= len(data)-1 { + return 0 + } + + // we need >= 1 digits followed by a dot and a space or a tab + if data[i] != '.' || !(data[i+1] == ' ' || data[i+1] == '\t') { + return 0 + } + return i + 2 +} + +// returns definition list item prefix +func (p *Markdown) dliPrefix(data []byte) int { + if len(data) < 2 { + return 0 + } + i := 0 + // need a ':' followed by a space or a tab + if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') { + return 0 + } + for i < len(data) && data[i] == ' ' { + i++ + } + return i + 2 +} + +// parse ordered or unordered list block +func (p *Markdown) list(data []byte, flags ListType) int { + i := 0 + flags |= ListItemBeginningOfList + block := p.addBlock(List, nil) + block.ListFlags = flags + block.Tight = true + + for i < len(data) { + skip := p.listItem(data[i:], &flags) + if flags&ListItemContainsBlock != 0 { + block.ListData.Tight = false + } + i += skip + if skip == 0 || flags&ListItemEndOfList != 0 { + break + } + flags &= ^ListItemBeginningOfList + } + + above := block.Parent + finalizeList(block) + p.tip = above + return i +} + +// Returns true if the list item is not the same type as its parent list +func (p *Markdown) listTypeChanged(data []byte, flags *ListType) bool { + if p.dliPrefix(data) > 0 && *flags&ListTypeDefinition == 0 { + return true + } else if p.oliPrefix(data) > 0 && *flags&ListTypeOrdered == 0 { + return true + } else if p.uliPrefix(data) > 0 && (*flags&ListTypeOrdered != 0 || *flags&ListTypeDefinition != 0) { + return true + } + return false +} + +// Returns true if block ends with a blank line, descending if needed +// into lists and sublists. +func endsWithBlankLine(block *Node) bool { + // TODO: figure this out. Always false now. + for block != nil { + //if block.lastLineBlank { + //return true + //} + t := block.Type + if t == List || t == Item { + block = block.LastChild + } else { + break + } + } + return false +} + +func finalizeList(block *Node) { + block.open = false + item := block.FirstChild + for item != nil { + // check for non-final list item ending with blank line: + if endsWithBlankLine(item) && item.Next != nil { + block.ListData.Tight = false + break + } + // recurse into children of list item, to see if there are spaces + // between any of them: + subItem := item.FirstChild + for subItem != nil { + if endsWithBlankLine(subItem) && (item.Next != nil || subItem.Next != nil) { + block.ListData.Tight = false + break + } + subItem = subItem.Next + } + item = item.Next + } +} + +// Parse a single list item. +// Assumes initial prefix is already removed if this is a sublist. +func (p *Markdown) listItem(data []byte, flags *ListType) int { + // keep track of the indentation of the first line + itemIndent := 0 + if data[0] == '\t' { + itemIndent += 4 + } else { + for itemIndent < 3 && data[itemIndent] == ' ' { + itemIndent++ + } + } + + var bulletChar byte = '*' + i := p.uliPrefix(data) + if i == 0 { + i = p.oliPrefix(data) + } else { + bulletChar = data[i-2] + } + if i == 0 { + i = p.dliPrefix(data) + // reset definition term flag + if i > 0 { + *flags &= ^ListTypeTerm + } + } + if i == 0 { + // if in definition list, set term flag and continue + if *flags&ListTypeDefinition != 0 { + *flags |= ListTypeTerm + } else { + return 0 + } + } + + // skip leading whitespace on first line + for i < len(data) && data[i] == ' ' { + i++ + } + + // find the end of the line + line := i + for i > 0 && i < len(data) && data[i-1] != '\n' { + i++ + } + + // get working buffer + var raw bytes.Buffer + + // put the first line into the working buffer + raw.Write(data[line:i]) + line = i + + // process the following lines + containsBlankLine := false + sublist := 0 + codeBlockMarker := "" + +gatherlines: + for line < len(data) { + i++ + + // find the end of this line + for i < len(data) && data[i-1] != '\n' { + i++ + } + + // if it is an empty line, guess that it is part of this item + // and move on to the next line + if p.isEmpty(data[line:i]) > 0 { + containsBlankLine = true + line = i + continue + } + + // calculate the indentation + indent := 0 + indentIndex := 0 + if data[line] == '\t' { + indentIndex++ + indent += 4 + } else { + for indent < 4 && line+indent < i && data[line+indent] == ' ' { + indent++ + indentIndex++ + } + } + + chunk := data[line+indentIndex : i] + + if p.extensions&FencedCode != 0 { + // determine if in or out of codeblock + // if in codeblock, ignore normal list processing + _, marker := isFenceLine(chunk, nil, codeBlockMarker) + if marker != "" { + if codeBlockMarker == "" { + // start of codeblock + codeBlockMarker = marker + } else { + // end of codeblock. + codeBlockMarker = "" + } + } + // we are in a codeblock, write line, and continue + if codeBlockMarker != "" || marker != "" { + raw.Write(data[line+indentIndex : i]) + line = i + continue gatherlines + } + } + + // evaluate how this line fits in + switch { + // is this a nested list item? + case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || + p.oliPrefix(chunk) > 0 || + p.dliPrefix(chunk) > 0: + + // to be a nested list, it must be indented more + // if not, it is either a different kind of list + // or the next item in the same list + if indent <= itemIndent { + if p.listTypeChanged(chunk, flags) { + *flags |= ListItemEndOfList + } else if containsBlankLine { + *flags |= ListItemContainsBlock + } + + break gatherlines + } + + if containsBlankLine { + *flags |= ListItemContainsBlock + } + + // is this the first item in the nested list? + if sublist == 0 { + sublist = raw.Len() + } + + // is this a nested prefix heading? + case p.isPrefixHeading(chunk): + // if the heading is not indented, it is not nested in the list + // and thus ends the list + if containsBlankLine && indent < 4 { + *flags |= ListItemEndOfList + break gatherlines + } + *flags |= ListItemContainsBlock + + // anything following an empty line is only part + // of this item if it is indented 4 spaces + // (regardless of the indentation of the beginning of the item) + case containsBlankLine && indent < 4: + if *flags&ListTypeDefinition != 0 && i < len(data)-1 { + // is the next item still a part of this list? + next := i + for next < len(data) && data[next] != '\n' { + next++ + } + for next < len(data)-1 && data[next] == '\n' { + next++ + } + if i < len(data)-1 && data[i] != ':' && data[next] != ':' { + *flags |= ListItemEndOfList + } + } else { + *flags |= ListItemEndOfList + } + break gatherlines + + // a blank line means this should be parsed as a block + case containsBlankLine: + raw.WriteByte('\n') + *flags |= ListItemContainsBlock + } + + // if this line was preceded by one or more blanks, + // re-introduce the blank into the buffer + if containsBlankLine { + containsBlankLine = false + raw.WriteByte('\n') + } + + // add the line into the working buffer without prefix + raw.Write(data[line+indentIndex : i]) + + line = i + } + + rawBytes := raw.Bytes() + + block := p.addBlock(Item, nil) + block.ListFlags = *flags + block.Tight = false + block.BulletChar = bulletChar + block.Delimiter = '.' // Only '.' is possible in Markdown, but ')' will also be possible in CommonMark + + // render the contents of the list item + if *flags&ListItemContainsBlock != 0 && *flags&ListTypeTerm == 0 { + // intermediate render of block item, except for definition term + if sublist > 0 { + p.block(rawBytes[:sublist]) + p.block(rawBytes[sublist:]) + } else { + p.block(rawBytes) + } + } else { + // intermediate render of inline item + if sublist > 0 { + child := p.addChild(Paragraph, 0) + child.content = rawBytes[:sublist] + p.block(rawBytes[sublist:]) + } else { + child := p.addChild(Paragraph, 0) + child.content = rawBytes + } + } + return line +} + +// render a single paragraph that has already been parsed out +func (p *Markdown) renderParagraph(data []byte) { + if len(data) == 0 { + return + } + + // trim leading spaces + beg := 0 + for data[beg] == ' ' { + beg++ + } + + end := len(data) + // trim trailing newline + if data[len(data)-1] == '\n' { + end-- + } + + // trim trailing spaces + for end > beg && data[end-1] == ' ' { + end-- + } + + p.addBlock(Paragraph, data[beg:end]) +} + +func (p *Markdown) paragraph(data []byte) int { + // prev: index of 1st char of previous line + // line: index of 1st char of current line + // i: index of cursor/end of current line + var prev, line, i int + tabSize := TabSizeDefault + if p.extensions&TabSizeEight != 0 { + tabSize = TabSizeDouble + } + // keep going until we find something to mark the end of the paragraph + for i < len(data) { + // mark the beginning of the current line + prev = line + current := data[i:] + line = i + + // did we find a reference or a footnote? If so, end a paragraph + // preceding it and report that we have consumed up to the end of that + // reference: + if refEnd := isReference(p, current, tabSize); refEnd > 0 { + p.renderParagraph(data[:i]) + return i + refEnd + } + + // did we find a blank line marking the end of the paragraph? + if n := p.isEmpty(current); n > 0 { + // did this blank line followed by a definition list item? + if p.extensions&DefinitionLists != 0 { + if i < len(data)-1 && data[i+1] == ':' { + return p.list(data[prev:], ListTypeDefinition) + } + } + + p.renderParagraph(data[:i]) + return i + n + } + + // an underline under some text marks a heading, so our paragraph ended on prev line + if i > 0 { + if level := p.isUnderlinedHeading(current); level > 0 { + // render the paragraph + p.renderParagraph(data[:prev]) + + // ignore leading and trailing whitespace + eol := i - 1 + for prev < eol && data[prev] == ' ' { + prev++ + } + for eol > prev && data[eol-1] == ' ' { + eol-- + } + + id := "" + if p.extensions&AutoHeadingIDs != 0 { + id = sanitized_anchor_name.Create(string(data[prev:eol])) + } + + block := p.addBlock(Heading, data[prev:eol]) + block.Level = level + block.HeadingID = id + + // find the end of the underline + for i < len(data) && data[i] != '\n' { + i++ + } + return i + } + } + + // if the next line starts a block of HTML, then the paragraph ends here + if p.extensions&LaxHTMLBlocks != 0 { + if data[i] == '<' && p.html(current, false) > 0 { + // rewind to before the HTML block + p.renderParagraph(data[:i]) + return i + } + } + + // if there's a prefixed heading or a horizontal rule after this, paragraph is over + if p.isPrefixHeading(current) || p.isHRule(current) { + p.renderParagraph(data[:i]) + return i + } + + // if there's a fenced code block, paragraph is over + if p.extensions&FencedCode != 0 { + if p.fencedCodeBlock(current, false) > 0 { + p.renderParagraph(data[:i]) + return i + } + } + + // if there's a definition list item, prev line is a definition term + if p.extensions&DefinitionLists != 0 { + if p.dliPrefix(current) != 0 { + ret := p.list(data[prev:], ListTypeDefinition) + return ret + } + } + + // if there's a list after this, paragraph is over + if p.extensions&NoEmptyLineBeforeBlock != 0 { + if p.uliPrefix(current) != 0 || + p.oliPrefix(current) != 0 || + p.quotePrefix(current) != 0 || + p.codePrefix(current) != 0 { + p.renderParagraph(data[:i]) + return i + } + } + + // otherwise, scan to the beginning of the next line + nl := bytes.IndexByte(data[i:], '\n') + if nl >= 0 { + i += nl + 1 + } else { + i += len(data[i:]) + } + } + + p.renderParagraph(data[:i]) + return i +} + +func skipChar(data []byte, start int, char byte) int { + i := start + for i < len(data) && data[i] == char { + i++ + } + return i +} + +func skipUntilChar(text []byte, start int, char byte) int { + i := start + for i < len(text) && text[i] != char { + i++ + } + return i +} diff --git a/vendor/github.com/russross/blackfriday/v2/doc.go b/vendor/github.com/russross/blackfriday/v2/doc.go new file mode 100644 index 000000000..5b3fa9876 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/doc.go @@ -0,0 +1,18 @@ +// Package blackfriday is a markdown processor. +// +// It translates plain text with simple formatting rules into an AST, which can +// then be further processed to HTML (provided by Blackfriday itself) or other +// formats (provided by the community). +// +// The simplest way to invoke Blackfriday is to call the Run function. It will +// take a text input and produce a text output in HTML (or other format). +// +// A slightly more sophisticated way to use Blackfriday is to create a Markdown +// processor and to call Parse, which returns a syntax tree for the input +// document. You can leverage Blackfriday's parsing for content extraction from +// markdown documents. You can assign a custom renderer and set various options +// to the Markdown processor. +// +// If you're interested in calling Blackfriday from command line, see +// https://github.com/russross/blackfriday-tool. +package blackfriday diff --git a/vendor/github.com/russross/blackfriday/v2/esc.go b/vendor/github.com/russross/blackfriday/v2/esc.go new file mode 100644 index 000000000..6385f27cb --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/esc.go @@ -0,0 +1,34 @@ +package blackfriday + +import ( + "html" + "io" +) + +var htmlEscaper = [256][]byte{ + '&': []byte("&"), + '<': []byte("<"), + '>': []byte(">"), + '"': []byte("""), +} + +func escapeHTML(w io.Writer, s []byte) { + var start, end int + for end < len(s) { + escSeq := htmlEscaper[s[end]] + if escSeq != nil { + w.Write(s[start:end]) + w.Write(escSeq) + start = end + 1 + } + end++ + } + if start < len(s) && end <= len(s) { + w.Write(s[start:end]) + } +} + +func escLink(w io.Writer, text []byte) { + unesc := html.UnescapeString(string(text)) + escapeHTML(w, []byte(unesc)) +} diff --git a/vendor/github.com/russross/blackfriday/v2/go.mod b/vendor/github.com/russross/blackfriday/v2/go.mod new file mode 100644 index 000000000..620b74e0a --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/go.mod @@ -0,0 +1 @@ +module github.com/russross/blackfriday/v2 diff --git a/vendor/github.com/russross/blackfriday/v2/html.go b/vendor/github.com/russross/blackfriday/v2/html.go new file mode 100644 index 000000000..284c87184 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/html.go @@ -0,0 +1,949 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// +// HTML rendering backend +// +// + +package blackfriday + +import ( + "bytes" + "fmt" + "io" + "regexp" + "strings" +) + +// HTMLFlags control optional behavior of HTML renderer. +type HTMLFlags int + +// HTML renderer configuration options. +const ( + HTMLFlagsNone HTMLFlags = 0 + SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks + SkipImages // Skip embedded images + SkipLinks // Skip all links + Safelink // Only link to trusted protocols + NofollowLinks // Only link with rel="nofollow" + NoreferrerLinks // Only link with rel="noreferrer" + NoopenerLinks // Only link with rel="noopener" + HrefTargetBlank // Add a blank target + CompletePage // Generate a complete HTML page + UseXHTML // Generate XHTML output instead of HTML + FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source + Smartypants // Enable smart punctuation substitutions + SmartypantsFractions // Enable smart fractions (with Smartypants) + SmartypantsDashes // Enable smart dashes (with Smartypants) + SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants) + SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering + SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants) + TOC // Generate a table of contents +) + +var ( + htmlTagRe = regexp.MustCompile("(?i)^" + htmlTag) +) + +const ( + htmlTag = "(?:" + openTag + "|" + closeTag + "|" + htmlComment + "|" + + processingInstruction + "|" + declaration + "|" + cdata + ")" + closeTag = "]" + openTag = "<" + tagName + attribute + "*" + "\\s*/?>" + attribute = "(?:" + "\\s+" + attributeName + attributeValueSpec + "?)" + attributeValue = "(?:" + unquotedValue + "|" + singleQuotedValue + "|" + doubleQuotedValue + ")" + attributeValueSpec = "(?:" + "\\s*=" + "\\s*" + attributeValue + ")" + attributeName = "[a-zA-Z_:][a-zA-Z0-9:._-]*" + cdata = "" + declaration = "]*>" + doubleQuotedValue = "\"[^\"]*\"" + htmlComment = "|" + processingInstruction = "[<][?].*?[?][>]" + singleQuotedValue = "'[^']*'" + tagName = "[A-Za-z][A-Za-z0-9-]*" + unquotedValue = "[^\"'=<>`\\x00-\\x20]+" +) + +// HTMLRendererParameters is a collection of supplementary parameters tweaking +// the behavior of various parts of HTML renderer. +type HTMLRendererParameters struct { + // Prepend this text to each relative URL. + AbsolutePrefix string + // Add this text to each footnote anchor, to ensure uniqueness. + FootnoteAnchorPrefix string + // Show this text inside the
tag for a footnote return link, if the + // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string + // [return] is used. + FootnoteReturnLinkContents string + // If set, add this text to the front of each Heading ID, to ensure + // uniqueness. + HeadingIDPrefix string + // If set, add this text to the back of each Heading ID, to ensure uniqueness. + HeadingIDSuffix string + // Increase heading levels: if the offset is 1,

becomes

etc. + // Negative offset is also valid. + // Resulting levels are clipped between 1 and 6. + HeadingLevelOffset int + + Title string // Document title (used if CompletePage is set) + CSS string // Optional CSS file URL (used if CompletePage is set) + Icon string // Optional icon file URL (used if CompletePage is set) + + Flags HTMLFlags // Flags allow customizing this renderer's behavior +} + +// HTMLRenderer is a type that implements the Renderer interface for HTML output. +// +// Do not create this directly, instead use the NewHTMLRenderer function. +type HTMLRenderer struct { + HTMLRendererParameters + + closeTag string // how to end singleton tags: either " />" or ">" + + // Track heading IDs to prevent ID collision in a single generation. + headingIDs map[string]int + + lastOutputLen int + disableTags int + + sr *SPRenderer +} + +const ( + xhtmlClose = " />" + htmlClose = ">" +) + +// NewHTMLRenderer creates and configures an HTMLRenderer object, which +// satisfies the Renderer interface. +func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer { + // configure the rendering engine + closeTag := htmlClose + if params.Flags&UseXHTML != 0 { + closeTag = xhtmlClose + } + + if params.FootnoteReturnLinkContents == "" { + params.FootnoteReturnLinkContents = `[return]` + } + + return &HTMLRenderer{ + HTMLRendererParameters: params, + + closeTag: closeTag, + headingIDs: make(map[string]int), + + sr: NewSmartypantsRenderer(params.Flags), + } +} + +func isHTMLTag(tag []byte, tagname string) bool { + found, _ := findHTMLTagPos(tag, tagname) + return found +} + +// Look for a character, but ignore it when it's in any kind of quotes, it +// might be JavaScript +func skipUntilCharIgnoreQuotes(html []byte, start int, char byte) int { + inSingleQuote := false + inDoubleQuote := false + inGraveQuote := false + i := start + for i < len(html) { + switch { + case html[i] == char && !inSingleQuote && !inDoubleQuote && !inGraveQuote: + return i + case html[i] == '\'': + inSingleQuote = !inSingleQuote + case html[i] == '"': + inDoubleQuote = !inDoubleQuote + case html[i] == '`': + inGraveQuote = !inGraveQuote + } + i++ + } + return start +} + +func findHTMLTagPos(tag []byte, tagname string) (bool, int) { + i := 0 + if i < len(tag) && tag[0] != '<' { + return false, -1 + } + i++ + i = skipSpace(tag, i) + + if i < len(tag) && tag[i] == '/' { + i++ + } + + i = skipSpace(tag, i) + j := 0 + for ; i < len(tag); i, j = i+1, j+1 { + if j >= len(tagname) { + break + } + + if strings.ToLower(string(tag[i]))[0] != tagname[j] { + return false, -1 + } + } + + if i == len(tag) { + return false, -1 + } + + rightAngle := skipUntilCharIgnoreQuotes(tag, i, '>') + if rightAngle >= i { + return true, rightAngle + } + + return false, -1 +} + +func skipSpace(tag []byte, i int) int { + for i < len(tag) && isspace(tag[i]) { + i++ + } + return i +} + +func isRelativeLink(link []byte) (yes bool) { + // a tag begin with '#' + if link[0] == '#' { + return true + } + + // link begin with '/' but not '//', the second maybe a protocol relative link + if len(link) >= 2 && link[0] == '/' && link[1] != '/' { + return true + } + + // only the root '/' + if len(link) == 1 && link[0] == '/' { + return true + } + + // current directory : begin with "./" + if bytes.HasPrefix(link, []byte("./")) { + return true + } + + // parent directory : begin with "../" + if bytes.HasPrefix(link, []byte("../")) { + return true + } + + return false +} + +func (r *HTMLRenderer) ensureUniqueHeadingID(id string) string { + for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] { + tmp := fmt.Sprintf("%s-%d", id, count+1) + + if _, tmpFound := r.headingIDs[tmp]; !tmpFound { + r.headingIDs[id] = count + 1 + id = tmp + } else { + id = id + "-1" + } + } + + if _, found := r.headingIDs[id]; !found { + r.headingIDs[id] = 0 + } + + return id +} + +func (r *HTMLRenderer) addAbsPrefix(link []byte) []byte { + if r.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' { + newDest := r.AbsolutePrefix + if link[0] != '/' { + newDest += "/" + } + newDest += string(link) + return []byte(newDest) + } + return link +} + +func appendLinkAttrs(attrs []string, flags HTMLFlags, link []byte) []string { + if isRelativeLink(link) { + return attrs + } + val := []string{} + if flags&NofollowLinks != 0 { + val = append(val, "nofollow") + } + if flags&NoreferrerLinks != 0 { + val = append(val, "noreferrer") + } + if flags&NoopenerLinks != 0 { + val = append(val, "noopener") + } + if flags&HrefTargetBlank != 0 { + attrs = append(attrs, "target=\"_blank\"") + } + if len(val) == 0 { + return attrs + } + attr := fmt.Sprintf("rel=%q", strings.Join(val, " ")) + return append(attrs, attr) +} + +func isMailto(link []byte) bool { + return bytes.HasPrefix(link, []byte("mailto:")) +} + +func needSkipLink(flags HTMLFlags, dest []byte) bool { + if flags&SkipLinks != 0 { + return true + } + return flags&Safelink != 0 && !isSafeLink(dest) && !isMailto(dest) +} + +func isSmartypantable(node *Node) bool { + pt := node.Parent.Type + return pt != Link && pt != CodeBlock && pt != Code +} + +func appendLanguageAttr(attrs []string, info []byte) []string { + if len(info) == 0 { + return attrs + } + endOfLang := bytes.IndexAny(info, "\t ") + if endOfLang < 0 { + endOfLang = len(info) + } + return append(attrs, fmt.Sprintf("class=\"language-%s\"", info[:endOfLang])) +} + +func (r *HTMLRenderer) tag(w io.Writer, name []byte, attrs []string) { + w.Write(name) + if len(attrs) > 0 { + w.Write(spaceBytes) + w.Write([]byte(strings.Join(attrs, " "))) + } + w.Write(gtBytes) + r.lastOutputLen = 1 +} + +func footnoteRef(prefix string, node *Node) []byte { + urlFrag := prefix + string(slugify(node.Destination)) + anchor := fmt.Sprintf(`%d`, urlFrag, node.NoteID) + return []byte(fmt.Sprintf(`%s`, urlFrag, anchor)) +} + +func footnoteItem(prefix string, slug []byte) []byte { + return []byte(fmt.Sprintf(`
  • `, prefix, slug)) +} + +func footnoteReturnLink(prefix, returnLink string, slug []byte) []byte { + const format = ` %s` + return []byte(fmt.Sprintf(format, prefix, slug, returnLink)) +} + +func itemOpenCR(node *Node) bool { + if node.Prev == nil { + return false + } + ld := node.Parent.ListData + return !ld.Tight && ld.ListFlags&ListTypeDefinition == 0 +} + +func skipParagraphTags(node *Node) bool { + grandparent := node.Parent.Parent + if grandparent == nil || grandparent.Type != List { + return false + } + tightOrTerm := grandparent.Tight || node.Parent.ListFlags&ListTypeTerm != 0 + return grandparent.Type == List && tightOrTerm +} + +func cellAlignment(align CellAlignFlags) string { + switch align { + case TableAlignmentLeft: + return "left" + case TableAlignmentRight: + return "right" + case TableAlignmentCenter: + return "center" + default: + return "" + } +} + +func (r *HTMLRenderer) out(w io.Writer, text []byte) { + if r.disableTags > 0 { + w.Write(htmlTagRe.ReplaceAll(text, []byte{})) + } else { + w.Write(text) + } + r.lastOutputLen = len(text) +} + +func (r *HTMLRenderer) cr(w io.Writer) { + if r.lastOutputLen > 0 { + r.out(w, nlBytes) + } +} + +var ( + nlBytes = []byte{'\n'} + gtBytes = []byte{'>'} + spaceBytes = []byte{' '} +) + +var ( + brTag = []byte("
    ") + brXHTMLTag = []byte("
    ") + emTag = []byte("") + emCloseTag = []byte("") + strongTag = []byte("") + strongCloseTag = []byte("") + delTag = []byte("") + delCloseTag = []byte("") + ttTag = []byte("") + ttCloseTag = []byte("") + aTag = []byte("") + preTag = []byte("
    ")
    +	preCloseTag        = []byte("
    ") + codeTag = []byte("") + codeCloseTag = []byte("") + pTag = []byte("

    ") + pCloseTag = []byte("

    ") + blockquoteTag = []byte("
    ") + blockquoteCloseTag = []byte("
    ") + hrTag = []byte("
    ") + hrXHTMLTag = []byte("
    ") + ulTag = []byte("
      ") + ulCloseTag = []byte("
    ") + olTag = []byte("
      ") + olCloseTag = []byte("
    ") + dlTag = []byte("
    ") + dlCloseTag = []byte("
    ") + liTag = []byte("
  • ") + liCloseTag = []byte("
  • ") + ddTag = []byte("
    ") + ddCloseTag = []byte("
    ") + dtTag = []byte("
    ") + dtCloseTag = []byte("
    ") + tableTag = []byte("") + tableCloseTag = []byte("
    ") + tdTag = []byte("") + thTag = []byte("") + theadTag = []byte("") + theadCloseTag = []byte("") + tbodyTag = []byte("") + tbodyCloseTag = []byte("") + trTag = []byte("") + trCloseTag = []byte("") + h1Tag = []byte("") + h2Tag = []byte("") + h3Tag = []byte("") + h4Tag = []byte("") + h5Tag = []byte("") + h6Tag = []byte("") + + footnotesDivBytes = []byte("\n
    \n\n") + footnotesCloseDivBytes = []byte("\n
    \n") +) + +func headingTagsFromLevel(level int) ([]byte, []byte) { + if level <= 1 { + return h1Tag, h1CloseTag + } + switch level { + case 2: + return h2Tag, h2CloseTag + case 3: + return h3Tag, h3CloseTag + case 4: + return h4Tag, h4CloseTag + case 5: + return h5Tag, h5CloseTag + } + return h6Tag, h6CloseTag +} + +func (r *HTMLRenderer) outHRTag(w io.Writer) { + if r.Flags&UseXHTML == 0 { + r.out(w, hrTag) + } else { + r.out(w, hrXHTMLTag) + } +} + +// RenderNode is a default renderer of a single node of a syntax tree. For +// block nodes it will be called twice: first time with entering=true, second +// time with entering=false, so that it could know when it's working on an open +// tag and when on close. It writes the result to w. +// +// The return value is a way to tell the calling walker to adjust its walk +// pattern: e.g. it can terminate the traversal by returning Terminate. Or it +// can ask the walker to skip a subtree of this node by returning SkipChildren. +// The typical behavior is to return GoToNext, which asks for the usual +// traversal to the next node. +func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkStatus { + attrs := []string{} + switch node.Type { + case Text: + if r.Flags&Smartypants != 0 { + var tmp bytes.Buffer + escapeHTML(&tmp, node.Literal) + r.sr.Process(w, tmp.Bytes()) + } else { + if node.Parent.Type == Link { + escLink(w, node.Literal) + } else { + escapeHTML(w, node.Literal) + } + } + case Softbreak: + r.cr(w) + // TODO: make it configurable via out(renderer.softbreak) + case Hardbreak: + if r.Flags&UseXHTML == 0 { + r.out(w, brTag) + } else { + r.out(w, brXHTMLTag) + } + r.cr(w) + case Emph: + if entering { + r.out(w, emTag) + } else { + r.out(w, emCloseTag) + } + case Strong: + if entering { + r.out(w, strongTag) + } else { + r.out(w, strongCloseTag) + } + case Del: + if entering { + r.out(w, delTag) + } else { + r.out(w, delCloseTag) + } + case HTMLSpan: + if r.Flags&SkipHTML != 0 { + break + } + r.out(w, node.Literal) + case Link: + // mark it but don't link it if it is not a safe link: no smartypants + dest := node.LinkData.Destination + if needSkipLink(r.Flags, dest) { + if entering { + r.out(w, ttTag) + } else { + r.out(w, ttCloseTag) + } + } else { + if entering { + dest = r.addAbsPrefix(dest) + var hrefBuf bytes.Buffer + hrefBuf.WriteString("href=\"") + escLink(&hrefBuf, dest) + hrefBuf.WriteByte('"') + attrs = append(attrs, hrefBuf.String()) + if node.NoteID != 0 { + r.out(w, footnoteRef(r.FootnoteAnchorPrefix, node)) + break + } + attrs = appendLinkAttrs(attrs, r.Flags, dest) + if len(node.LinkData.Title) > 0 { + var titleBuff bytes.Buffer + titleBuff.WriteString("title=\"") + escapeHTML(&titleBuff, node.LinkData.Title) + titleBuff.WriteByte('"') + attrs = append(attrs, titleBuff.String()) + } + r.tag(w, aTag, attrs) + } else { + if node.NoteID != 0 { + break + } + r.out(w, aCloseTag) + } + } + case Image: + if r.Flags&SkipImages != 0 { + return SkipChildren + } + if entering { + dest := node.LinkData.Destination + dest = r.addAbsPrefix(dest) + if r.disableTags == 0 { + //if options.safe && potentiallyUnsafe(dest) { + //out(w, ``)
+				//} else {
+				r.out(w, []byte(`<img src=`)) + } + } + case Code: + r.out(w, codeTag) + escapeHTML(w, node.Literal) + r.out(w, codeCloseTag) + case Document: + break + case Paragraph: + if skipParagraphTags(node) { + break + } + if entering { + // TODO: untangle this clusterfuck about when the newlines need + // to be added and when not. + if node.Prev != nil { + switch node.Prev.Type { + case HTMLBlock, List, Paragraph, Heading, CodeBlock, BlockQuote, HorizontalRule: + r.cr(w) + } + } + if node.Parent.Type == BlockQuote && node.Prev == nil { + r.cr(w) + } + r.out(w, pTag) + } else { + r.out(w, pCloseTag) + if !(node.Parent.Type == Item && node.Next == nil) { + r.cr(w) + } + } + case BlockQuote: + if entering { + r.cr(w) + r.out(w, blockquoteTag) + } else { + r.out(w, blockquoteCloseTag) + r.cr(w) + } + case HTMLBlock: + if r.Flags&SkipHTML != 0 { + break + } + r.cr(w) + r.out(w, node.Literal) + r.cr(w) + case Heading: + headingLevel := r.HTMLRendererParameters.HeadingLevelOffset + node.Level + openTag, closeTag := headingTagsFromLevel(headingLevel) + if entering { + if node.IsTitleblock { + attrs = append(attrs, `class="title"`) + } + if node.HeadingID != "" { + id := r.ensureUniqueHeadingID(node.HeadingID) + if r.HeadingIDPrefix != "" { + id = r.HeadingIDPrefix + id + } + if r.HeadingIDSuffix != "" { + id = id + r.HeadingIDSuffix + } + attrs = append(attrs, fmt.Sprintf(`id="%s"`, id)) + } + r.cr(w) + r.tag(w, openTag, attrs) + } else { + r.out(w, closeTag) + if !(node.Parent.Type == Item && node.Next == nil) { + r.cr(w) + } + } + case HorizontalRule: + r.cr(w) + r.outHRTag(w) + r.cr(w) + case List: + openTag := ulTag + closeTag := ulCloseTag + if node.ListFlags&ListTypeOrdered != 0 { + openTag = olTag + closeTag = olCloseTag + } + if node.ListFlags&ListTypeDefinition != 0 { + openTag = dlTag + closeTag = dlCloseTag + } + if entering { + if node.IsFootnotesList { + r.out(w, footnotesDivBytes) + r.outHRTag(w) + r.cr(w) + } + r.cr(w) + if node.Parent.Type == Item && node.Parent.Parent.Tight { + r.cr(w) + } + r.tag(w, openTag[:len(openTag)-1], attrs) + r.cr(w) + } else { + r.out(w, closeTag) + //cr(w) + //if node.parent.Type != Item { + // cr(w) + //} + if node.Parent.Type == Item && node.Next != nil { + r.cr(w) + } + if node.Parent.Type == Document || node.Parent.Type == BlockQuote { + r.cr(w) + } + if node.IsFootnotesList { + r.out(w, footnotesCloseDivBytes) + } + } + case Item: + openTag := liTag + closeTag := liCloseTag + if node.ListFlags&ListTypeDefinition != 0 { + openTag = ddTag + closeTag = ddCloseTag + } + if node.ListFlags&ListTypeTerm != 0 { + openTag = dtTag + closeTag = dtCloseTag + } + if entering { + if itemOpenCR(node) { + r.cr(w) + } + if node.ListData.RefLink != nil { + slug := slugify(node.ListData.RefLink) + r.out(w, footnoteItem(r.FootnoteAnchorPrefix, slug)) + break + } + r.out(w, openTag) + } else { + if node.ListData.RefLink != nil { + slug := slugify(node.ListData.RefLink) + if r.Flags&FootnoteReturnLinks != 0 { + r.out(w, footnoteReturnLink(r.FootnoteAnchorPrefix, r.FootnoteReturnLinkContents, slug)) + } + } + r.out(w, closeTag) + r.cr(w) + } + case CodeBlock: + attrs = appendLanguageAttr(attrs, node.Info) + r.cr(w) + r.out(w, preTag) + r.tag(w, codeTag[:len(codeTag)-1], attrs) + escapeHTML(w, node.Literal) + r.out(w, codeCloseTag) + r.out(w, preCloseTag) + if node.Parent.Type != Item { + r.cr(w) + } + case Table: + if entering { + r.cr(w) + r.out(w, tableTag) + } else { + r.out(w, tableCloseTag) + r.cr(w) + } + case TableCell: + openTag := tdTag + closeTag := tdCloseTag + if node.IsHeader { + openTag = thTag + closeTag = thCloseTag + } + if entering { + align := cellAlignment(node.Align) + if align != "" { + attrs = append(attrs, fmt.Sprintf(`align="%s"`, align)) + } + if node.Prev == nil { + r.cr(w) + } + r.tag(w, openTag, attrs) + } else { + r.out(w, closeTag) + r.cr(w) + } + case TableHead: + if entering { + r.cr(w) + r.out(w, theadTag) + } else { + r.out(w, theadCloseTag) + r.cr(w) + } + case TableBody: + if entering { + r.cr(w) + r.out(w, tbodyTag) + // XXX: this is to adhere to a rather silly test. Should fix test. + if node.FirstChild == nil { + r.cr(w) + } + } else { + r.out(w, tbodyCloseTag) + r.cr(w) + } + case TableRow: + if entering { + r.cr(w) + r.out(w, trTag) + } else { + r.out(w, trCloseTag) + r.cr(w) + } + default: + panic("Unknown node type " + node.Type.String()) + } + return GoToNext +} + +// RenderHeader writes HTML document preamble and TOC if requested. +func (r *HTMLRenderer) RenderHeader(w io.Writer, ast *Node) { + r.writeDocumentHeader(w) + if r.Flags&TOC != 0 { + r.writeTOC(w, ast) + } +} + +// RenderFooter writes HTML document footer. +func (r *HTMLRenderer) RenderFooter(w io.Writer, ast *Node) { + if r.Flags&CompletePage == 0 { + return + } + io.WriteString(w, "\n\n\n") +} + +func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) { + if r.Flags&CompletePage == 0 { + return + } + ending := "" + if r.Flags&UseXHTML != 0 { + io.WriteString(w, "\n") + io.WriteString(w, "\n") + ending = " /" + } else { + io.WriteString(w, "\n") + io.WriteString(w, "\n") + } + io.WriteString(w, "\n") + io.WriteString(w, " ") + if r.Flags&Smartypants != 0 { + r.sr.Process(w, []byte(r.Title)) + } else { + escapeHTML(w, []byte(r.Title)) + } + io.WriteString(w, "\n") + io.WriteString(w, " \n") + io.WriteString(w, " \n") + if r.CSS != "" { + io.WriteString(w, " \n") + } + if r.Icon != "" { + io.WriteString(w, " \n") + } + io.WriteString(w, "\n") + io.WriteString(w, "\n\n") +} + +func (r *HTMLRenderer) writeTOC(w io.Writer, ast *Node) { + buf := bytes.Buffer{} + + inHeading := false + tocLevel := 0 + headingCount := 0 + + ast.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Heading && !node.HeadingData.IsTitleblock { + inHeading = entering + if entering { + node.HeadingID = fmt.Sprintf("toc_%d", headingCount) + if node.Level == tocLevel { + buf.WriteString("\n\n
  • ") + } else if node.Level < tocLevel { + for node.Level < tocLevel { + tocLevel-- + buf.WriteString("
  • \n") + } + buf.WriteString("\n\n
  • ") + } else { + for node.Level > tocLevel { + tocLevel++ + buf.WriteString("\n") + } + + if buf.Len() > 0 { + io.WriteString(w, "\n") + } + r.lastOutputLen = buf.Len() +} diff --git a/vendor/github.com/russross/blackfriday/v2/inline.go b/vendor/github.com/russross/blackfriday/v2/inline.go new file mode 100644 index 000000000..4ed290792 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/inline.go @@ -0,0 +1,1228 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// Functions to parse inline elements. +// + +package blackfriday + +import ( + "bytes" + "regexp" + "strconv" +) + +var ( + urlRe = `((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+` + anchorRe = regexp.MustCompile(`^(]+")?\s?>` + urlRe + `<\/a>)`) + + // https://www.w3.org/TR/html5/syntax.html#character-references + // highest unicode code point in 17 planes (2^20): 1,114,112d = + // 7 dec digits or 6 hex digits + // named entity references can be 2-31 characters with stuff like < + // at one end and ∳ at the other. There + // are also sometimes numbers at the end, although this isn't inherent + // in the specification; there are never numbers anywhere else in + // current character references, though; see ¾ and ▒, etc. + // https://www.w3.org/TR/html5/syntax.html#named-character-references + // + // entity := "&" (named group | number ref) ";" + // named group := [a-zA-Z]{2,31}[0-9]{0,2} + // number ref := "#" (dec ref | hex ref) + // dec ref := [0-9]{1,7} + // hex ref := ("x" | "X") [0-9a-fA-F]{1,6} + htmlEntityRe = regexp.MustCompile(`&([a-zA-Z]{2,31}[0-9]{0,2}|#([0-9]{1,7}|[xX][0-9a-fA-F]{1,6}));`) +) + +// Functions to parse text within a block +// Each function returns the number of chars taken care of +// data is the complete block being rendered +// offset is the number of valid chars before the current cursor + +func (p *Markdown) inline(currBlock *Node, data []byte) { + // handlers might call us recursively: enforce a maximum depth + if p.nesting >= p.maxNesting || len(data) == 0 { + return + } + p.nesting++ + beg, end := 0, 0 + for end < len(data) { + handler := p.inlineCallback[data[end]] + if handler != nil { + if consumed, node := handler(p, data, end); consumed == 0 { + // No action from the callback. + end++ + } else { + // Copy inactive chars into the output. + currBlock.AppendChild(text(data[beg:end])) + if node != nil { + currBlock.AppendChild(node) + } + // Skip past whatever the callback used. + beg = end + consumed + end = beg + } + } else { + end++ + } + } + if beg < len(data) { + if data[end-1] == '\n' { + end-- + } + currBlock.AppendChild(text(data[beg:end])) + } + p.nesting-- +} + +// single and double emphasis parsing +func emphasis(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + c := data[0] + + if len(data) > 2 && data[1] != c { + // whitespace cannot follow an opening emphasis; + // strikethrough only takes two characters '~~' + if c == '~' || isspace(data[1]) { + return 0, nil + } + ret, node := helperEmphasis(p, data[1:], c) + if ret == 0 { + return 0, nil + } + + return ret + 1, node + } + + if len(data) > 3 && data[1] == c && data[2] != c { + if isspace(data[2]) { + return 0, nil + } + ret, node := helperDoubleEmphasis(p, data[2:], c) + if ret == 0 { + return 0, nil + } + + return ret + 2, node + } + + if len(data) > 4 && data[1] == c && data[2] == c && data[3] != c { + if c == '~' || isspace(data[3]) { + return 0, nil + } + ret, node := helperTripleEmphasis(p, data, 3, c) + if ret == 0 { + return 0, nil + } + + return ret + 3, node + } + + return 0, nil +} + +func codeSpan(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + + nb := 0 + + // count the number of backticks in the delimiter + for nb < len(data) && data[nb] == '`' { + nb++ + } + + // find the next delimiter + i, end := 0, 0 + for end = nb; end < len(data) && i < nb; end++ { + if data[end] == '`' { + i++ + } else { + i = 0 + } + } + + // no matching delimiter? + if i < nb && end >= len(data) { + return 0, nil + } + + // trim outside whitespace + fBegin := nb + for fBegin < end && data[fBegin] == ' ' { + fBegin++ + } + + fEnd := end - nb + for fEnd > fBegin && data[fEnd-1] == ' ' { + fEnd-- + } + + // render the code span + if fBegin != fEnd { + code := NewNode(Code) + code.Literal = data[fBegin:fEnd] + return end, code + } + + return end, nil +} + +// newline preceded by two spaces becomes
    +func maybeLineBreak(p *Markdown, data []byte, offset int) (int, *Node) { + origOffset := offset + for offset < len(data) && data[offset] == ' ' { + offset++ + } + + if offset < len(data) && data[offset] == '\n' { + if offset-origOffset >= 2 { + return offset - origOffset + 1, NewNode(Hardbreak) + } + return offset - origOffset, nil + } + return 0, nil +} + +// newline without two spaces works when HardLineBreak is enabled +func lineBreak(p *Markdown, data []byte, offset int) (int, *Node) { + if p.extensions&HardLineBreak != 0 { + return 1, NewNode(Hardbreak) + } + return 0, nil +} + +type linkType int + +const ( + linkNormal linkType = iota + linkImg + linkDeferredFootnote + linkInlineFootnote +) + +func isReferenceStyleLink(data []byte, pos int, t linkType) bool { + if t == linkDeferredFootnote { + return false + } + return pos < len(data)-1 && data[pos] == '[' && data[pos+1] != '^' +} + +func maybeImage(p *Markdown, data []byte, offset int) (int, *Node) { + if offset < len(data)-1 && data[offset+1] == '[' { + return link(p, data, offset) + } + return 0, nil +} + +func maybeInlineFootnote(p *Markdown, data []byte, offset int) (int, *Node) { + if offset < len(data)-1 && data[offset+1] == '[' { + return link(p, data, offset) + } + return 0, nil +} + +// '[': parse a link or an image or a footnote +func link(p *Markdown, data []byte, offset int) (int, *Node) { + // no links allowed inside regular links, footnote, and deferred footnotes + if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') { + return 0, nil + } + + var t linkType + switch { + // special case: ![^text] == deferred footnote (that follows something with + // an exclamation point) + case p.extensions&Footnotes != 0 && len(data)-1 > offset && data[offset+1] == '^': + t = linkDeferredFootnote + // ![alt] == image + case offset >= 0 && data[offset] == '!': + t = linkImg + offset++ + // ^[text] == inline footnote + // [^refId] == deferred footnote + case p.extensions&Footnotes != 0: + if offset >= 0 && data[offset] == '^' { + t = linkInlineFootnote + offset++ + } else if len(data)-1 > offset && data[offset+1] == '^' { + t = linkDeferredFootnote + } + // [text] == regular link + default: + t = linkNormal + } + + data = data[offset:] + + var ( + i = 1 + noteID int + title, link, altContent []byte + textHasNl = false + ) + + if t == linkDeferredFootnote { + i++ + } + + // look for the matching closing bracket + for level := 1; level > 0 && i < len(data); i++ { + switch { + case data[i] == '\n': + textHasNl = true + + case data[i-1] == '\\': + continue + + case data[i] == '[': + level++ + + case data[i] == ']': + level-- + if level <= 0 { + i-- // compensate for extra i++ in for loop + } + } + } + + if i >= len(data) { + return 0, nil + } + + txtE := i + i++ + var footnoteNode *Node + + // skip any amount of whitespace or newline + // (this is much more lax than original markdown syntax) + for i < len(data) && isspace(data[i]) { + i++ + } + + // inline style link + switch { + case i < len(data) && data[i] == '(': + // skip initial whitespace + i++ + + for i < len(data) && isspace(data[i]) { + i++ + } + + linkB := i + + // look for link end: ' " ) + findlinkend: + for i < len(data) { + switch { + case data[i] == '\\': + i += 2 + + case data[i] == ')' || data[i] == '\'' || data[i] == '"': + break findlinkend + + default: + i++ + } + } + + if i >= len(data) { + return 0, nil + } + linkE := i + + // look for title end if present + titleB, titleE := 0, 0 + if data[i] == '\'' || data[i] == '"' { + i++ + titleB = i + + findtitleend: + for i < len(data) { + switch { + case data[i] == '\\': + i += 2 + + case data[i] == ')': + break findtitleend + + default: + i++ + } + } + + if i >= len(data) { + return 0, nil + } + + // skip whitespace after title + titleE = i - 1 + for titleE > titleB && isspace(data[titleE]) { + titleE-- + } + + // check for closing quote presence + if data[titleE] != '\'' && data[titleE] != '"' { + titleB, titleE = 0, 0 + linkE = i + } + } + + // remove whitespace at the end of the link + for linkE > linkB && isspace(data[linkE-1]) { + linkE-- + } + + // remove optional angle brackets around the link + if data[linkB] == '<' { + linkB++ + } + if data[linkE-1] == '>' { + linkE-- + } + + // build escaped link and title + if linkE > linkB { + link = data[linkB:linkE] + } + + if titleE > titleB { + title = data[titleB:titleE] + } + + i++ + + // reference style link + case isReferenceStyleLink(data, i, t): + var id []byte + altContentConsidered := false + + // look for the id + i++ + linkB := i + for i < len(data) && data[i] != ']' { + i++ + } + if i >= len(data) { + return 0, nil + } + linkE := i + + // find the reference + if linkB == linkE { + if textHasNl { + var b bytes.Buffer + + for j := 1; j < txtE; j++ { + switch { + case data[j] != '\n': + b.WriteByte(data[j]) + case data[j-1] != ' ': + b.WriteByte(' ') + } + } + + id = b.Bytes() + } else { + id = data[1:txtE] + altContentConsidered = true + } + } else { + id = data[linkB:linkE] + } + + // find the reference with matching id + lr, ok := p.getRef(string(id)) + if !ok { + return 0, nil + } + + // keep link and title from reference + link = lr.link + title = lr.title + if altContentConsidered { + altContent = lr.text + } + i++ + + // shortcut reference style link or reference or inline footnote + default: + var id []byte + + // craft the id + if textHasNl { + var b bytes.Buffer + + for j := 1; j < txtE; j++ { + switch { + case data[j] != '\n': + b.WriteByte(data[j]) + case data[j-1] != ' ': + b.WriteByte(' ') + } + } + + id = b.Bytes() + } else { + if t == linkDeferredFootnote { + id = data[2:txtE] // get rid of the ^ + } else { + id = data[1:txtE] + } + } + + footnoteNode = NewNode(Item) + if t == linkInlineFootnote { + // create a new reference + noteID = len(p.notes) + 1 + + var fragment []byte + if len(id) > 0 { + if len(id) < 16 { + fragment = make([]byte, len(id)) + } else { + fragment = make([]byte, 16) + } + copy(fragment, slugify(id)) + } else { + fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...) + } + + ref := &reference{ + noteID: noteID, + hasBlock: false, + link: fragment, + title: id, + footnote: footnoteNode, + } + + p.notes = append(p.notes, ref) + + link = ref.link + title = ref.title + } else { + // find the reference with matching id + lr, ok := p.getRef(string(id)) + if !ok { + return 0, nil + } + + if t == linkDeferredFootnote { + lr.noteID = len(p.notes) + 1 + lr.footnote = footnoteNode + p.notes = append(p.notes, lr) + } + + // keep link and title from reference + link = lr.link + // if inline footnote, title == footnote contents + title = lr.title + noteID = lr.noteID + } + + // rewind the whitespace + i = txtE + 1 + } + + var uLink []byte + if t == linkNormal || t == linkImg { + if len(link) > 0 { + var uLinkBuf bytes.Buffer + unescapeText(&uLinkBuf, link) + uLink = uLinkBuf.Bytes() + } + + // links need something to click on and somewhere to go + if len(uLink) == 0 || (t == linkNormal && txtE <= 1) { + return 0, nil + } + } + + // call the relevant rendering function + var linkNode *Node + switch t { + case linkNormal: + linkNode = NewNode(Link) + linkNode.Destination = normalizeURI(uLink) + linkNode.Title = title + if len(altContent) > 0 { + linkNode.AppendChild(text(altContent)) + } else { + // links cannot contain other links, so turn off link parsing + // temporarily and recurse + insideLink := p.insideLink + p.insideLink = true + p.inline(linkNode, data[1:txtE]) + p.insideLink = insideLink + } + + case linkImg: + linkNode = NewNode(Image) + linkNode.Destination = uLink + linkNode.Title = title + linkNode.AppendChild(text(data[1:txtE])) + i++ + + case linkInlineFootnote, linkDeferredFootnote: + linkNode = NewNode(Link) + linkNode.Destination = link + linkNode.Title = title + linkNode.NoteID = noteID + linkNode.Footnote = footnoteNode + if t == linkInlineFootnote { + i++ + } + + default: + return 0, nil + } + + return i, linkNode +} + +func (p *Markdown) inlineHTMLComment(data []byte) int { + if len(data) < 5 { + return 0 + } + if data[0] != '<' || data[1] != '!' || data[2] != '-' || data[3] != '-' { + return 0 + } + i := 5 + // scan for an end-of-comment marker, across lines if necessary + for i < len(data) && !(data[i-2] == '-' && data[i-1] == '-' && data[i] == '>') { + i++ + } + // no end-of-comment marker + if i >= len(data) { + return 0 + } + return i + 1 +} + +func stripMailto(link []byte) []byte { + if bytes.HasPrefix(link, []byte("mailto://")) { + return link[9:] + } else if bytes.HasPrefix(link, []byte("mailto:")) { + return link[7:] + } else { + return link + } +} + +// autolinkType specifies a kind of autolink that gets detected. +type autolinkType int + +// These are the possible flag values for the autolink renderer. +const ( + notAutolink autolinkType = iota + normalAutolink + emailAutolink +) + +// '<' when tags or autolinks are allowed +func leftAngle(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + altype, end := tagLength(data) + if size := p.inlineHTMLComment(data); size > 0 { + end = size + } + if end > 2 { + if altype != notAutolink { + var uLink bytes.Buffer + unescapeText(&uLink, data[1:end+1-2]) + if uLink.Len() > 0 { + link := uLink.Bytes() + node := NewNode(Link) + node.Destination = link + if altype == emailAutolink { + node.Destination = append([]byte("mailto:"), link...) + } + node.AppendChild(text(stripMailto(link))) + return end, node + } + } else { + htmlTag := NewNode(HTMLSpan) + htmlTag.Literal = data[:end] + return end, htmlTag + } + } + + return end, nil +} + +// '\\' backslash escape +var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~") + +func escape(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + + if len(data) > 1 { + if p.extensions&BackslashLineBreak != 0 && data[1] == '\n' { + return 2, NewNode(Hardbreak) + } + if bytes.IndexByte(escapeChars, data[1]) < 0 { + return 0, nil + } + + return 2, text(data[1:2]) + } + + return 2, nil +} + +func unescapeText(ob *bytes.Buffer, src []byte) { + i := 0 + for i < len(src) { + org := i + for i < len(src) && src[i] != '\\' { + i++ + } + + if i > org { + ob.Write(src[org:i]) + } + + if i+1 >= len(src) { + break + } + + ob.WriteByte(src[i+1]) + i += 2 + } +} + +// '&' escaped when it doesn't belong to an entity +// valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; +func entity(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + + end := 1 + + if end < len(data) && data[end] == '#' { + end++ + } + + for end < len(data) && isalnum(data[end]) { + end++ + } + + if end < len(data) && data[end] == ';' { + end++ // real entity + } else { + return 0, nil // lone '&' + } + + ent := data[:end] + // undo & escaping or it will be converted to &amp; by another + // escaper in the renderer + if bytes.Equal(ent, []byte("&")) { + ent = []byte{'&'} + } + + return end, text(ent) +} + +func linkEndsWithEntity(data []byte, linkEnd int) bool { + entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1) + return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd +} + +// hasPrefixCaseInsensitive is a custom implementation of +// strings.HasPrefix(strings.ToLower(s), prefix) +// we rolled our own because ToLower pulls in a huge machinery of lowercasing +// anything from Unicode and that's very slow. Since this func will only be +// used on ASCII protocol prefixes, we can take shortcuts. +func hasPrefixCaseInsensitive(s, prefix []byte) bool { + if len(s) < len(prefix) { + return false + } + delta := byte('a' - 'A') + for i, b := range prefix { + if b != s[i] && b != s[i]+delta { + return false + } + } + return true +} + +var protocolPrefixes = [][]byte{ + []byte("http://"), + []byte("https://"), + []byte("ftp://"), + []byte("file://"), + []byte("mailto:"), +} + +const shortestPrefix = 6 // len("ftp://"), the shortest of the above + +func maybeAutoLink(p *Markdown, data []byte, offset int) (int, *Node) { + // quick check to rule out most false hits + if p.insideLink || len(data) < offset+shortestPrefix { + return 0, nil + } + for _, prefix := range protocolPrefixes { + endOfHead := offset + 8 // 8 is the len() of the longest prefix + if endOfHead > len(data) { + endOfHead = len(data) + } + if hasPrefixCaseInsensitive(data[offset:endOfHead], prefix) { + return autoLink(p, data, offset) + } + } + return 0, nil +} + +func autoLink(p *Markdown, data []byte, offset int) (int, *Node) { + // Now a more expensive check to see if we're not inside an anchor element + anchorStart := offset + offsetFromAnchor := 0 + for anchorStart > 0 && data[anchorStart] != '<' { + anchorStart-- + offsetFromAnchor++ + } + + anchorStr := anchorRe.Find(data[anchorStart:]) + if anchorStr != nil { + anchorClose := NewNode(HTMLSpan) + anchorClose.Literal = anchorStr[offsetFromAnchor:] + return len(anchorStr) - offsetFromAnchor, anchorClose + } + + // scan backward for a word boundary + rewind := 0 + for offset-rewind > 0 && rewind <= 7 && isletter(data[offset-rewind-1]) { + rewind++ + } + if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters + return 0, nil + } + + origData := data + data = data[offset-rewind:] + + if !isSafeLink(data) { + return 0, nil + } + + linkEnd := 0 + for linkEnd < len(data) && !isEndOfLink(data[linkEnd]) { + linkEnd++ + } + + // Skip punctuation at the end of the link + if (data[linkEnd-1] == '.' || data[linkEnd-1] == ',') && data[linkEnd-2] != '\\' { + linkEnd-- + } + + // But don't skip semicolon if it's a part of escaped entity: + if data[linkEnd-1] == ';' && data[linkEnd-2] != '\\' && !linkEndsWithEntity(data, linkEnd) { + linkEnd-- + } + + // See if the link finishes with a punctuation sign that can be closed. + var copen byte + switch data[linkEnd-1] { + case '"': + copen = '"' + case '\'': + copen = '\'' + case ')': + copen = '(' + case ']': + copen = '[' + case '}': + copen = '{' + default: + copen = 0 + } + + if copen != 0 { + bufEnd := offset - rewind + linkEnd - 2 + + openDelim := 1 + + /* Try to close the final punctuation sign in this same line; + * if we managed to close it outside of the URL, that means that it's + * not part of the URL. If it closes inside the URL, that means it + * is part of the URL. + * + * Examples: + * + * foo http://www.pokemon.com/Pikachu_(Electric) bar + * => http://www.pokemon.com/Pikachu_(Electric) + * + * foo (http://www.pokemon.com/Pikachu_(Electric)) bar + * => http://www.pokemon.com/Pikachu_(Electric) + * + * foo http://www.pokemon.com/Pikachu_(Electric)) bar + * => http://www.pokemon.com/Pikachu_(Electric)) + * + * (foo http://www.pokemon.com/Pikachu_(Electric)) bar + * => foo http://www.pokemon.com/Pikachu_(Electric) + */ + + for bufEnd >= 0 && origData[bufEnd] != '\n' && openDelim != 0 { + if origData[bufEnd] == data[linkEnd-1] { + openDelim++ + } + + if origData[bufEnd] == copen { + openDelim-- + } + + bufEnd-- + } + + if openDelim == 0 { + linkEnd-- + } + } + + var uLink bytes.Buffer + unescapeText(&uLink, data[:linkEnd]) + + if uLink.Len() > 0 { + node := NewNode(Link) + node.Destination = uLink.Bytes() + node.AppendChild(text(uLink.Bytes())) + return linkEnd, node + } + + return linkEnd, nil +} + +func isEndOfLink(char byte) bool { + return isspace(char) || char == '<' +} + +var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")} +var validPaths = [][]byte{[]byte("/"), []byte("./"), []byte("../")} + +func isSafeLink(link []byte) bool { + for _, path := range validPaths { + if len(link) >= len(path) && bytes.Equal(link[:len(path)], path) { + if len(link) == len(path) { + return true + } else if isalnum(link[len(path)]) { + return true + } + } + } + + for _, prefix := range validUris { + // TODO: handle unicode here + // case-insensitive prefix test + if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) { + return true + } + } + + return false +} + +// return the length of the given tag, or 0 is it's not valid +func tagLength(data []byte) (autolink autolinkType, end int) { + var i, j int + + // a valid tag can't be shorter than 3 chars + if len(data) < 3 { + return notAutolink, 0 + } + + // begins with a '<' optionally followed by '/', followed by letter or number + if data[0] != '<' { + return notAutolink, 0 + } + if data[1] == '/' { + i = 2 + } else { + i = 1 + } + + if !isalnum(data[i]) { + return notAutolink, 0 + } + + // scheme test + autolink = notAutolink + + // try to find the beginning of an URI + for i < len(data) && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') { + i++ + } + + if i > 1 && i < len(data) && data[i] == '@' { + if j = isMailtoAutoLink(data[i:]); j != 0 { + return emailAutolink, i + j + } + } + + if i > 2 && i < len(data) && data[i] == ':' { + autolink = normalAutolink + i++ + } + + // complete autolink test: no whitespace or ' or " + switch { + case i >= len(data): + autolink = notAutolink + case autolink != notAutolink: + j = i + + for i < len(data) { + if data[i] == '\\' { + i += 2 + } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isspace(data[i]) { + break + } else { + i++ + } + + } + + if i >= len(data) { + return autolink, 0 + } + if i > j && data[i] == '>' { + return autolink, i + 1 + } + + // one of the forbidden chars has been found + autolink = notAutolink + } + i += bytes.IndexByte(data[i:], '>') + if i < 0 { + return autolink, 0 + } + return autolink, i + 1 +} + +// look for the address part of a mail autolink and '>' +// this is less strict than the original markdown e-mail address matching +func isMailtoAutoLink(data []byte) int { + nb := 0 + + // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' + for i := 0; i < len(data); i++ { + if isalnum(data[i]) { + continue + } + + switch data[i] { + case '@': + nb++ + + case '-', '.', '_': + break + + case '>': + if nb == 1 { + return i + 1 + } + return 0 + default: + return 0 + } + } + + return 0 +} + +// look for the next emph char, skipping other constructs +func helperFindEmphChar(data []byte, c byte) int { + i := 0 + + for i < len(data) { + for i < len(data) && data[i] != c && data[i] != '`' && data[i] != '[' { + i++ + } + if i >= len(data) { + return 0 + } + // do not count escaped chars + if i != 0 && data[i-1] == '\\' { + i++ + continue + } + if data[i] == c { + return i + } + + if data[i] == '`' { + // skip a code span + tmpI := 0 + i++ + for i < len(data) && data[i] != '`' { + if tmpI == 0 && data[i] == c { + tmpI = i + } + i++ + } + if i >= len(data) { + return tmpI + } + i++ + } else if data[i] == '[' { + // skip a link + tmpI := 0 + i++ + for i < len(data) && data[i] != ']' { + if tmpI == 0 && data[i] == c { + tmpI = i + } + i++ + } + i++ + for i < len(data) && (data[i] == ' ' || data[i] == '\n') { + i++ + } + if i >= len(data) { + return tmpI + } + if data[i] != '[' && data[i] != '(' { // not a link + if tmpI > 0 { + return tmpI + } + continue + } + cc := data[i] + i++ + for i < len(data) && data[i] != cc { + if tmpI == 0 && data[i] == c { + return i + } + i++ + } + if i >= len(data) { + return tmpI + } + i++ + } + } + return 0 +} + +func helperEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { + i := 0 + + // skip one symbol if coming from emph3 + if len(data) > 1 && data[0] == c && data[1] == c { + i = 1 + } + + for i < len(data) { + length := helperFindEmphChar(data[i:], c) + if length == 0 { + return 0, nil + } + i += length + if i >= len(data) { + return 0, nil + } + + if i+1 < len(data) && data[i+1] == c { + i++ + continue + } + + if data[i] == c && !isspace(data[i-1]) { + + if p.extensions&NoIntraEmphasis != 0 { + if !(i+1 == len(data) || isspace(data[i+1]) || ispunct(data[i+1])) { + continue + } + } + + emph := NewNode(Emph) + p.inline(emph, data[:i]) + return i + 1, emph + } + } + + return 0, nil +} + +func helperDoubleEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { + i := 0 + + for i < len(data) { + length := helperFindEmphChar(data[i:], c) + if length == 0 { + return 0, nil + } + i += length + + if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !isspace(data[i-1]) { + nodeType := Strong + if c == '~' { + nodeType = Del + } + node := NewNode(nodeType) + p.inline(node, data[:i]) + return i + 2, node + } + i++ + } + return 0, nil +} + +func helperTripleEmphasis(p *Markdown, data []byte, offset int, c byte) (int, *Node) { + i := 0 + origData := data + data = data[offset:] + + for i < len(data) { + length := helperFindEmphChar(data[i:], c) + if length == 0 { + return 0, nil + } + i += length + + // skip whitespace preceded symbols + if data[i] != c || isspace(data[i-1]) { + continue + } + + switch { + case i+2 < len(data) && data[i+1] == c && data[i+2] == c: + // triple symbol found + strong := NewNode(Strong) + em := NewNode(Emph) + strong.AppendChild(em) + p.inline(em, data[:i]) + return i + 3, strong + case (i+1 < len(data) && data[i+1] == c): + // double symbol found, hand over to emph1 + length, node := helperEmphasis(p, origData[offset-2:], c) + if length == 0 { + return 0, nil + } + return length - 2, node + default: + // single symbol found, hand over to emph2 + length, node := helperDoubleEmphasis(p, origData[offset-1:], c) + if length == 0 { + return 0, nil + } + return length - 1, node + } + } + return 0, nil +} + +func text(s []byte) *Node { + node := NewNode(Text) + node.Literal = s + return node +} + +func normalizeURI(s []byte) []byte { + return s // TODO: implement +} diff --git a/vendor/github.com/russross/blackfriday/v2/markdown.go b/vendor/github.com/russross/blackfriday/v2/markdown.go new file mode 100644 index 000000000..58d2e4538 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/markdown.go @@ -0,0 +1,950 @@ +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. + +package blackfriday + +import ( + "bytes" + "fmt" + "io" + "strings" + "unicode/utf8" +) + +// +// Markdown parsing and processing +// + +// Version string of the package. Appears in the rendered document when +// CompletePage flag is on. +const Version = "2.0" + +// Extensions is a bitwise or'ed collection of enabled Blackfriday's +// extensions. +type Extensions int + +// These are the supported markdown parsing extensions. +// OR these values together to select multiple extensions. +const ( + NoExtensions Extensions = 0 + NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words + Tables // Render tables + FencedCode // Render fenced code blocks + Autolink // Detect embedded URLs that are not explicitly marked + Strikethrough // Strikethrough text using ~~test~~ + LaxHTMLBlocks // Loosen up HTML block parsing rules + SpaceHeadings // Be strict about prefix heading rules + HardLineBreak // Translate newlines into line breaks + TabSizeEight // Expand tabs to eight spaces instead of four + Footnotes // Pandoc-style footnotes + NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block + HeadingIDs // specify heading IDs with {#id} + Titleblock // Titleblock ala pandoc + AutoHeadingIDs // Create the heading ID from the text + BackslashLineBreak // Translate trailing backslashes into line breaks + DefinitionLists // Render definition lists + + CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants | + SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes + + CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode | + Autolink | Strikethrough | SpaceHeadings | HeadingIDs | + BackslashLineBreak | DefinitionLists +) + +// ListType contains bitwise or'ed flags for list and list item objects. +type ListType int + +// These are the possible flag values for the ListItem renderer. +// Multiple flag values may be ORed together. +// These are mostly of interest if you are writing a new output format. +const ( + ListTypeOrdered ListType = 1 << iota + ListTypeDefinition + ListTypeTerm + + ListItemContainsBlock + ListItemBeginningOfList // TODO: figure out if this is of any use now + ListItemEndOfList +) + +// CellAlignFlags holds a type of alignment in a table cell. +type CellAlignFlags int + +// These are the possible flag values for the table cell renderer. +// Only a single one of these values will be used; they are not ORed together. +// These are mostly of interest if you are writing a new output format. +const ( + TableAlignmentLeft CellAlignFlags = 1 << iota + TableAlignmentRight + TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight) +) + +// The size of a tab stop. +const ( + TabSizeDefault = 4 + TabSizeDouble = 8 +) + +// blockTags is a set of tags that are recognized as HTML block tags. +// Any of these can be included in markdown text without special escaping. +var blockTags = map[string]struct{}{ + "blockquote": {}, + "del": {}, + "div": {}, + "dl": {}, + "fieldset": {}, + "form": {}, + "h1": {}, + "h2": {}, + "h3": {}, + "h4": {}, + "h5": {}, + "h6": {}, + "iframe": {}, + "ins": {}, + "math": {}, + "noscript": {}, + "ol": {}, + "pre": {}, + "p": {}, + "script": {}, + "style": {}, + "table": {}, + "ul": {}, + + // HTML5 + "address": {}, + "article": {}, + "aside": {}, + "canvas": {}, + "figcaption": {}, + "figure": {}, + "footer": {}, + "header": {}, + "hgroup": {}, + "main": {}, + "nav": {}, + "output": {}, + "progress": {}, + "section": {}, + "video": {}, +} + +// Renderer is the rendering interface. This is mostly of interest if you are +// implementing a new rendering format. +// +// Only an HTML implementation is provided in this repository, see the README +// for external implementations. +type Renderer interface { + // RenderNode is the main rendering method. It will be called once for + // every leaf node and twice for every non-leaf node (first with + // entering=true, then with entering=false). The method should write its + // rendition of the node to the supplied writer w. + RenderNode(w io.Writer, node *Node, entering bool) WalkStatus + + // RenderHeader is a method that allows the renderer to produce some + // content preceding the main body of the output document. The header is + // understood in the broad sense here. For example, the default HTML + // renderer will write not only the HTML document preamble, but also the + // table of contents if it was requested. + // + // The method will be passed an entire document tree, in case a particular + // implementation needs to inspect it to produce output. + // + // The output should be written to the supplied writer w. If your + // implementation has no header to write, supply an empty implementation. + RenderHeader(w io.Writer, ast *Node) + + // RenderFooter is a symmetric counterpart of RenderHeader. + RenderFooter(w io.Writer, ast *Node) +} + +// Callback functions for inline parsing. One such function is defined +// for each character that triggers a response when parsing inline data. +type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node) + +// Markdown is a type that holds extensions and the runtime state used by +// Parse, and the renderer. You can not use it directly, construct it with New. +type Markdown struct { + renderer Renderer + referenceOverride ReferenceOverrideFunc + refs map[string]*reference + inlineCallback [256]inlineParser + extensions Extensions + nesting int + maxNesting int + insideLink bool + + // Footnotes need to be ordered as well as available to quickly check for + // presence. If a ref is also a footnote, it's stored both in refs and here + // in notes. Slice is nil if footnotes not enabled. + notes []*reference + + doc *Node + tip *Node // = doc + oldTip *Node + lastMatchedContainer *Node // = doc + allClosed bool +} + +func (p *Markdown) getRef(refid string) (ref *reference, found bool) { + if p.referenceOverride != nil { + r, overridden := p.referenceOverride(refid) + if overridden { + if r == nil { + return nil, false + } + return &reference{ + link: []byte(r.Link), + title: []byte(r.Title), + noteID: 0, + hasBlock: false, + text: []byte(r.Text)}, true + } + } + // refs are case insensitive + ref, found = p.refs[strings.ToLower(refid)] + return ref, found +} + +func (p *Markdown) finalize(block *Node) { + above := block.Parent + block.open = false + p.tip = above +} + +func (p *Markdown) addChild(node NodeType, offset uint32) *Node { + return p.addExistingChild(NewNode(node), offset) +} + +func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node { + for !p.tip.canContain(node.Type) { + p.finalize(p.tip) + } + p.tip.AppendChild(node) + p.tip = node + return node +} + +func (p *Markdown) closeUnmatchedBlocks() { + if !p.allClosed { + for p.oldTip != p.lastMatchedContainer { + parent := p.oldTip.Parent + p.finalize(p.oldTip) + p.oldTip = parent + } + p.allClosed = true + } +} + +// +// +// Public interface +// +// + +// Reference represents the details of a link. +// See the documentation in Options for more details on use-case. +type Reference struct { + // Link is usually the URL the reference points to. + Link string + // Title is the alternate text describing the link in more detail. + Title string + // Text is the optional text to override the ref with if the syntax used was + // [refid][] + Text string +} + +// ReferenceOverrideFunc is expected to be called with a reference string and +// return either a valid Reference type that the reference string maps to or +// nil. If overridden is false, the default reference logic will be executed. +// See the documentation in Options for more details on use-case. +type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool) + +// New constructs a Markdown processor. You can use the same With* functions as +// for Run() to customize parser's behavior and the renderer. +func New(opts ...Option) *Markdown { + var p Markdown + for _, opt := range opts { + opt(&p) + } + p.refs = make(map[string]*reference) + p.maxNesting = 16 + p.insideLink = false + docNode := NewNode(Document) + p.doc = docNode + p.tip = docNode + p.oldTip = docNode + p.lastMatchedContainer = docNode + p.allClosed = true + // register inline parsers + p.inlineCallback[' '] = maybeLineBreak + p.inlineCallback['*'] = emphasis + p.inlineCallback['_'] = emphasis + if p.extensions&Strikethrough != 0 { + p.inlineCallback['~'] = emphasis + } + p.inlineCallback['`'] = codeSpan + p.inlineCallback['\n'] = lineBreak + p.inlineCallback['['] = link + p.inlineCallback['<'] = leftAngle + p.inlineCallback['\\'] = escape + p.inlineCallback['&'] = entity + p.inlineCallback['!'] = maybeImage + p.inlineCallback['^'] = maybeInlineFootnote + if p.extensions&Autolink != 0 { + p.inlineCallback['h'] = maybeAutoLink + p.inlineCallback['m'] = maybeAutoLink + p.inlineCallback['f'] = maybeAutoLink + p.inlineCallback['H'] = maybeAutoLink + p.inlineCallback['M'] = maybeAutoLink + p.inlineCallback['F'] = maybeAutoLink + } + if p.extensions&Footnotes != 0 { + p.notes = make([]*reference, 0) + } + return &p +} + +// Option customizes the Markdown processor's default behavior. +type Option func(*Markdown) + +// WithRenderer allows you to override the default renderer. +func WithRenderer(r Renderer) Option { + return func(p *Markdown) { + p.renderer = r + } +} + +// WithExtensions allows you to pick some of the many extensions provided by +// Blackfriday. You can bitwise OR them. +func WithExtensions(e Extensions) Option { + return func(p *Markdown) { + p.extensions = e + } +} + +// WithNoExtensions turns off all extensions and custom behavior. +func WithNoExtensions() Option { + return func(p *Markdown) { + p.extensions = NoExtensions + p.renderer = NewHTMLRenderer(HTMLRendererParameters{ + Flags: HTMLFlagsNone, + }) + } +} + +// WithRefOverride sets an optional function callback that is called every +// time a reference is resolved. +// +// In Markdown, the link reference syntax can be made to resolve a link to +// a reference instead of an inline URL, in one of the following ways: +// +// * [link text][refid] +// * [refid][] +// +// Usually, the refid is defined at the bottom of the Markdown document. If +// this override function is provided, the refid is passed to the override +// function first, before consulting the defined refids at the bottom. If +// the override function indicates an override did not occur, the refids at +// the bottom will be used to fill in the link details. +func WithRefOverride(o ReferenceOverrideFunc) Option { + return func(p *Markdown) { + p.referenceOverride = o + } +} + +// Run is the main entry point to Blackfriday. It parses and renders a +// block of markdown-encoded text. +// +// The simplest invocation of Run takes one argument, input: +// output := Run(input) +// This will parse the input with CommonExtensions enabled and render it with +// the default HTMLRenderer (with CommonHTMLFlags). +// +// Variadic arguments opts can customize the default behavior. Since Markdown +// type does not contain exported fields, you can not use it directly. Instead, +// use the With* functions. For example, this will call the most basic +// functionality, with no extensions: +// output := Run(input, WithNoExtensions()) +// +// You can use any number of With* arguments, even contradicting ones. They +// will be applied in order of appearance and the latter will override the +// former: +// output := Run(input, WithNoExtensions(), WithExtensions(exts), +// WithRenderer(yourRenderer)) +func Run(input []byte, opts ...Option) []byte { + r := NewHTMLRenderer(HTMLRendererParameters{ + Flags: CommonHTMLFlags, + }) + optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)} + optList = append(optList, opts...) + parser := New(optList...) + ast := parser.Parse(input) + var buf bytes.Buffer + parser.renderer.RenderHeader(&buf, ast) + ast.Walk(func(node *Node, entering bool) WalkStatus { + return parser.renderer.RenderNode(&buf, node, entering) + }) + parser.renderer.RenderFooter(&buf, ast) + return buf.Bytes() +} + +// Parse is an entry point to the parsing part of Blackfriday. It takes an +// input markdown document and produces a syntax tree for its contents. This +// tree can then be rendered with a default or custom renderer, or +// analyzed/transformed by the caller to whatever non-standard needs they have. +// The return value is the root node of the syntax tree. +func (p *Markdown) Parse(input []byte) *Node { + p.block(input) + // Walk the tree and finish up some of unfinished blocks + for p.tip != nil { + p.finalize(p.tip) + } + // Walk the tree again and process inline markdown in each block + p.doc.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell { + p.inline(node, node.content) + node.content = nil + } + return GoToNext + }) + p.parseRefsToAST() + return p.doc +} + +func (p *Markdown) parseRefsToAST() { + if p.extensions&Footnotes == 0 || len(p.notes) == 0 { + return + } + p.tip = p.doc + block := p.addBlock(List, nil) + block.IsFootnotesList = true + block.ListFlags = ListTypeOrdered + flags := ListItemBeginningOfList + // Note: this loop is intentionally explicit, not range-form. This is + // because the body of the loop will append nested footnotes to p.notes and + // we need to process those late additions. Range form would only walk over + // the fixed initial set. + for i := 0; i < len(p.notes); i++ { + ref := p.notes[i] + p.addExistingChild(ref.footnote, 0) + block := ref.footnote + block.ListFlags = flags | ListTypeOrdered + block.RefLink = ref.link + if ref.hasBlock { + flags |= ListItemContainsBlock + p.block(ref.title) + } else { + p.inline(block, ref.title) + } + flags &^= ListItemBeginningOfList | ListItemContainsBlock + } + above := block.Parent + finalizeList(block) + p.tip = above + block.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Paragraph || node.Type == Heading { + p.inline(node, node.content) + node.content = nil + } + return GoToNext + }) +} + +// +// Link references +// +// This section implements support for references that (usually) appear +// as footnotes in a document, and can be referenced anywhere in the document. +// The basic format is: +// +// [1]: http://www.google.com/ "Google" +// [2]: http://www.github.com/ "Github" +// +// Anywhere in the document, the reference can be linked by referring to its +// label, i.e., 1 and 2 in this example, as in: +// +// This library is hosted on [Github][2], a git hosting site. +// +// Actual footnotes as specified in Pandoc and supported by some other Markdown +// libraries such as php-markdown are also taken care of. They look like this: +// +// This sentence needs a bit of further explanation.[^note] +// +// [^note]: This is the explanation. +// +// Footnotes should be placed at the end of the document in an ordered list. +// Finally, there are inline footnotes such as: +// +// Inline footnotes^[Also supported.] provide a quick inline explanation, +// but are rendered at the bottom of the document. +// + +// reference holds all information necessary for a reference-style links or +// footnotes. +// +// Consider this markdown with reference-style links: +// +// [link][ref] +// +// [ref]: /url/ "tooltip title" +// +// It will be ultimately converted to this HTML: +// +//

    link

    +// +// And a reference structure will be populated as follows: +// +// p.refs["ref"] = &reference{ +// link: "/url/", +// title: "tooltip title", +// } +// +// Alternatively, reference can contain information about a footnote. Consider +// this markdown: +// +// Text needing a footnote.[^a] +// +// [^a]: This is the note +// +// A reference structure will be populated as follows: +// +// p.refs["a"] = &reference{ +// link: "a", +// title: "This is the note", +// noteID: , +// } +// +// TODO: As you can see, it begs for splitting into two dedicated structures +// for refs and for footnotes. +type reference struct { + link []byte + title []byte + noteID int // 0 if not a footnote ref + hasBlock bool + footnote *Node // a link to the Item node within a list of footnotes + + text []byte // only gets populated by refOverride feature with Reference.Text +} + +func (r *reference) String() string { + return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}", + r.link, r.title, r.text, r.noteID, r.hasBlock) +} + +// Check whether or not data starts with a reference link. +// If so, it is parsed and stored in the list of references +// (in the render struct). +// Returns the number of bytes to skip to move past it, +// or zero if the first line is not a reference. +func isReference(p *Markdown, data []byte, tabSize int) int { + // up to 3 optional leading spaces + if len(data) < 4 { + return 0 + } + i := 0 + for i < 3 && data[i] == ' ' { + i++ + } + + noteID := 0 + + // id part: anything but a newline between brackets + if data[i] != '[' { + return 0 + } + i++ + if p.extensions&Footnotes != 0 { + if i < len(data) && data[i] == '^' { + // we can set it to anything here because the proper noteIds will + // be assigned later during the second pass. It just has to be != 0 + noteID = 1 + i++ + } + } + idOffset := i + for i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != ']' { + i++ + } + if i >= len(data) || data[i] != ']' { + return 0 + } + idEnd := i + // footnotes can have empty ID, like this: [^], but a reference can not be + // empty like this: []. Break early if it's not a footnote and there's no ID + if noteID == 0 && idOffset == idEnd { + return 0 + } + // spacer: colon (space | tab)* newline? (space | tab)* + i++ + if i >= len(data) || data[i] != ':' { + return 0 + } + i++ + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + if i < len(data) && (data[i] == '\n' || data[i] == '\r') { + i++ + if i < len(data) && data[i] == '\n' && data[i-1] == '\r' { + i++ + } + } + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + if i >= len(data) { + return 0 + } + + var ( + linkOffset, linkEnd int + titleOffset, titleEnd int + lineEnd int + raw []byte + hasBlock bool + ) + + if p.extensions&Footnotes != 0 && noteID != 0 { + linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize) + lineEnd = linkEnd + } else { + linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i) + } + if lineEnd == 0 { + return 0 + } + + // a valid ref has been found + + ref := &reference{ + noteID: noteID, + hasBlock: hasBlock, + } + + if noteID > 0 { + // reusing the link field for the id since footnotes don't have links + ref.link = data[idOffset:idEnd] + // if footnote, it's not really a title, it's the contained text + ref.title = raw + } else { + ref.link = data[linkOffset:linkEnd] + ref.title = data[titleOffset:titleEnd] + } + + // id matches are case-insensitive + id := string(bytes.ToLower(data[idOffset:idEnd])) + + p.refs[id] = ref + + return lineEnd +} + +func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) { + // link: whitespace-free sequence, optionally between angle brackets + if data[i] == '<' { + i++ + } + linkOffset = i + for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' { + i++ + } + linkEnd = i + if data[linkOffset] == '<' && data[linkEnd-1] == '>' { + linkOffset++ + linkEnd-- + } + + // optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + if i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != '\'' && data[i] != '"' && data[i] != '(' { + return + } + + // compute end-of-line + if i >= len(data) || data[i] == '\r' || data[i] == '\n' { + lineEnd = i + } + if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' { + lineEnd++ + } + + // optional (space|tab)* spacer after a newline + if lineEnd > 0 { + i = lineEnd + 1 + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + } + + // optional title: any non-newline sequence enclosed in '"() alone on its line + if i+1 < len(data) && (data[i] == '\'' || data[i] == '"' || data[i] == '(') { + i++ + titleOffset = i + + // look for EOL + for i < len(data) && data[i] != '\n' && data[i] != '\r' { + i++ + } + if i+1 < len(data) && data[i] == '\n' && data[i+1] == '\r' { + titleEnd = i + 1 + } else { + titleEnd = i + } + + // step back + i-- + for i > titleOffset && (data[i] == ' ' || data[i] == '\t') { + i-- + } + if i > titleOffset && (data[i] == '\'' || data[i] == '"' || data[i] == ')') { + lineEnd = titleEnd + titleEnd = i + } + } + + return +} + +// The first bit of this logic is the same as Parser.listItem, but the rest +// is much simpler. This function simply finds the entire block and shifts it +// over by one tab if it is indeed a block (just returns the line if it's not). +// blockEnd is the end of the section in the input buffer, and contents is the +// extracted text that was shifted over one tab. It will need to be rendered at +// the end of the document. +func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) { + if i == 0 || len(data) == 0 { + return + } + + // skip leading whitespace on first line + for i < len(data) && data[i] == ' ' { + i++ + } + + blockStart = i + + // find the end of the line + blockEnd = i + for i < len(data) && data[i-1] != '\n' { + i++ + } + + // get working buffer + var raw bytes.Buffer + + // put the first line into the working buffer + raw.Write(data[blockEnd:i]) + blockEnd = i + + // process the following lines + containsBlankLine := false + +gatherLines: + for blockEnd < len(data) { + i++ + + // find the end of this line + for i < len(data) && data[i-1] != '\n' { + i++ + } + + // if it is an empty line, guess that it is part of this item + // and move on to the next line + if p.isEmpty(data[blockEnd:i]) > 0 { + containsBlankLine = true + blockEnd = i + continue + } + + n := 0 + if n = isIndented(data[blockEnd:i], indentSize); n == 0 { + // this is the end of the block. + // we don't want to include this last line in the index. + break gatherLines + } + + // if there were blank lines before this one, insert a new one now + if containsBlankLine { + raw.WriteByte('\n') + containsBlankLine = false + } + + // get rid of that first tab, write to buffer + raw.Write(data[blockEnd+n : i]) + hasBlock = true + + blockEnd = i + } + + if data[blockEnd-1] != '\n' { + raw.WriteByte('\n') + } + + contents = raw.Bytes() + + return +} + +// +// +// Miscellaneous helper functions +// +// + +// Test if a character is a punctuation symbol. +// Taken from a private function in regexp in the stdlib. +func ispunct(c byte) bool { + for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") { + if c == r { + return true + } + } + return false +} + +// Test if a character is a whitespace character. +func isspace(c byte) bool { + return ishorizontalspace(c) || isverticalspace(c) +} + +// Test if a character is a horizontal whitespace character. +func ishorizontalspace(c byte) bool { + return c == ' ' || c == '\t' +} + +// Test if a character is a vertical character. +func isverticalspace(c byte) bool { + return c == '\n' || c == '\r' || c == '\f' || c == '\v' +} + +// Test if a character is letter. +func isletter(c byte) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') +} + +// Test if a character is a letter or a digit. +// TODO: check when this is looking for ASCII alnum and when it should use unicode +func isalnum(c byte) bool { + return (c >= '0' && c <= '9') || isletter(c) +} + +// Replace tab characters with spaces, aligning to the next TAB_SIZE column. +// always ends output with a newline +func expandTabs(out *bytes.Buffer, line []byte, tabSize int) { + // first, check for common cases: no tabs, or only tabs at beginning of line + i, prefix := 0, 0 + slowcase := false + for i = 0; i < len(line); i++ { + if line[i] == '\t' { + if prefix == i { + prefix++ + } else { + slowcase = true + break + } + } + } + + // no need to decode runes if all tabs are at the beginning of the line + if !slowcase { + for i = 0; i < prefix*tabSize; i++ { + out.WriteByte(' ') + } + out.Write(line[prefix:]) + return + } + + // the slow case: we need to count runes to figure out how + // many spaces to insert for each tab + column := 0 + i = 0 + for i < len(line) { + start := i + for i < len(line) && line[i] != '\t' { + _, size := utf8.DecodeRune(line[i:]) + i += size + column++ + } + + if i > start { + out.Write(line[start:i]) + } + + if i >= len(line) { + break + } + + for { + out.WriteByte(' ') + column++ + if column%tabSize == 0 { + break + } + } + + i++ + } +} + +// Find if a line counts as indented or not. +// Returns number of characters the indent is (0 = not indented). +func isIndented(data []byte, indentSize int) int { + if len(data) == 0 { + return 0 + } + if data[0] == '\t' { + return 1 + } + if len(data) < indentSize { + return 0 + } + for i := 0; i < indentSize; i++ { + if data[i] != ' ' { + return 0 + } + } + return indentSize +} + +// Create a url-safe slug for fragments +func slugify(in []byte) []byte { + if len(in) == 0 { + return in + } + out := make([]byte, 0, len(in)) + sym := false + + for _, ch := range in { + if isalnum(ch) { + sym = false + out = append(out, ch) + } else if sym { + continue + } else { + out = append(out, '-') + sym = true + } + } + var a, b int + var ch byte + for a, ch = range out { + if ch != '-' { + break + } + } + for b = len(out) - 1; b > 0; b-- { + if out[b] != '-' { + break + } + } + return out[a : b+1] +} diff --git a/vendor/github.com/russross/blackfriday/v2/node.go b/vendor/github.com/russross/blackfriday/v2/node.go new file mode 100644 index 000000000..51b9e8c1b --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/node.go @@ -0,0 +1,354 @@ +package blackfriday + +import ( + "bytes" + "fmt" +) + +// NodeType specifies a type of a single node of a syntax tree. Usually one +// node (and its type) corresponds to a single markdown feature, e.g. emphasis +// or code block. +type NodeType int + +// Constants for identifying different types of nodes. See NodeType. +const ( + Document NodeType = iota + BlockQuote + List + Item + Paragraph + Heading + HorizontalRule + Emph + Strong + Del + Link + Image + Text + HTMLBlock + CodeBlock + Softbreak + Hardbreak + Code + HTMLSpan + Table + TableCell + TableHead + TableBody + TableRow +) + +var nodeTypeNames = []string{ + Document: "Document", + BlockQuote: "BlockQuote", + List: "List", + Item: "Item", + Paragraph: "Paragraph", + Heading: "Heading", + HorizontalRule: "HorizontalRule", + Emph: "Emph", + Strong: "Strong", + Del: "Del", + Link: "Link", + Image: "Image", + Text: "Text", + HTMLBlock: "HTMLBlock", + CodeBlock: "CodeBlock", + Softbreak: "Softbreak", + Hardbreak: "Hardbreak", + Code: "Code", + HTMLSpan: "HTMLSpan", + Table: "Table", + TableCell: "TableCell", + TableHead: "TableHead", + TableBody: "TableBody", + TableRow: "TableRow", +} + +func (t NodeType) String() string { + return nodeTypeNames[t] +} + +// ListData contains fields relevant to a List and Item node type. +type ListData struct { + ListFlags ListType + Tight bool // Skip

    s around list item data if true + BulletChar byte // '*', '+' or '-' in bullet lists + Delimiter byte // '.' or ')' after the number in ordered lists + RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering + IsFootnotesList bool // This is a list of footnotes +} + +// LinkData contains fields relevant to a Link node type. +type LinkData struct { + Destination []byte // Destination is what goes into a href + Title []byte // Title is the tooltip thing that goes in a title attribute + NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote + Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil. +} + +// CodeBlockData contains fields relevant to a CodeBlock node type. +type CodeBlockData struct { + IsFenced bool // Specifies whether it's a fenced code block or an indented one + Info []byte // This holds the info string + FenceChar byte + FenceLength int + FenceOffset int +} + +// TableCellData contains fields relevant to a TableCell node type. +type TableCellData struct { + IsHeader bool // This tells if it's under the header row + Align CellAlignFlags // This holds the value for align attribute +} + +// HeadingData contains fields relevant to a Heading node type. +type HeadingData struct { + Level int // This holds the heading level number + HeadingID string // This might hold heading ID, if present + IsTitleblock bool // Specifies whether it's a title block +} + +// Node is a single element in the abstract syntax tree of the parsed document. +// It holds connections to the structurally neighboring nodes and, for certain +// types of nodes, additional information that might be needed when rendering. +type Node struct { + Type NodeType // Determines the type of the node + Parent *Node // Points to the parent + FirstChild *Node // Points to the first child, if any + LastChild *Node // Points to the last child, if any + Prev *Node // Previous sibling; nil if it's the first child + Next *Node // Next sibling; nil if it's the last child + + Literal []byte // Text contents of the leaf nodes + + HeadingData // Populated if Type is Heading + ListData // Populated if Type is List + CodeBlockData // Populated if Type is CodeBlock + LinkData // Populated if Type is Link + TableCellData // Populated if Type is TableCell + + content []byte // Markdown content of the block nodes + open bool // Specifies an open block node that has not been finished to process yet +} + +// NewNode allocates a node of a specified type. +func NewNode(typ NodeType) *Node { + return &Node{ + Type: typ, + open: true, + } +} + +func (n *Node) String() string { + ellipsis := "" + snippet := n.Literal + if len(snippet) > 16 { + snippet = snippet[:16] + ellipsis = "..." + } + return fmt.Sprintf("%s: '%s%s'", n.Type, snippet, ellipsis) +} + +// Unlink removes node 'n' from the tree. +// It panics if the node is nil. +func (n *Node) Unlink() { + if n.Prev != nil { + n.Prev.Next = n.Next + } else if n.Parent != nil { + n.Parent.FirstChild = n.Next + } + if n.Next != nil { + n.Next.Prev = n.Prev + } else if n.Parent != nil { + n.Parent.LastChild = n.Prev + } + n.Parent = nil + n.Next = nil + n.Prev = nil +} + +// AppendChild adds a node 'child' as a child of 'n'. +// It panics if either node is nil. +func (n *Node) AppendChild(child *Node) { + child.Unlink() + child.Parent = n + if n.LastChild != nil { + n.LastChild.Next = child + child.Prev = n.LastChild + n.LastChild = child + } else { + n.FirstChild = child + n.LastChild = child + } +} + +// InsertBefore inserts 'sibling' immediately before 'n'. +// It panics if either node is nil. +func (n *Node) InsertBefore(sibling *Node) { + sibling.Unlink() + sibling.Prev = n.Prev + if sibling.Prev != nil { + sibling.Prev.Next = sibling + } + sibling.Next = n + n.Prev = sibling + sibling.Parent = n.Parent + if sibling.Prev == nil { + sibling.Parent.FirstChild = sibling + } +} + +func (n *Node) isContainer() bool { + switch n.Type { + case Document: + fallthrough + case BlockQuote: + fallthrough + case List: + fallthrough + case Item: + fallthrough + case Paragraph: + fallthrough + case Heading: + fallthrough + case Emph: + fallthrough + case Strong: + fallthrough + case Del: + fallthrough + case Link: + fallthrough + case Image: + fallthrough + case Table: + fallthrough + case TableHead: + fallthrough + case TableBody: + fallthrough + case TableRow: + fallthrough + case TableCell: + return true + default: + return false + } +} + +func (n *Node) canContain(t NodeType) bool { + if n.Type == List { + return t == Item + } + if n.Type == Document || n.Type == BlockQuote || n.Type == Item { + return t != Item + } + if n.Type == Table { + return t == TableHead || t == TableBody + } + if n.Type == TableHead || n.Type == TableBody { + return t == TableRow + } + if n.Type == TableRow { + return t == TableCell + } + return false +} + +// WalkStatus allows NodeVisitor to have some control over the tree traversal. +// It is returned from NodeVisitor and different values allow Node.Walk to +// decide which node to go to next. +type WalkStatus int + +const ( + // GoToNext is the default traversal of every node. + GoToNext WalkStatus = iota + // SkipChildren tells walker to skip all children of current node. + SkipChildren + // Terminate tells walker to terminate the traversal. + Terminate +) + +// NodeVisitor is a callback to be called when traversing the syntax tree. +// Called twice for every node: once with entering=true when the branch is +// first visited, then with entering=false after all the children are done. +type NodeVisitor func(node *Node, entering bool) WalkStatus + +// Walk is a convenience method that instantiates a walker and starts a +// traversal of subtree rooted at n. +func (n *Node) Walk(visitor NodeVisitor) { + w := newNodeWalker(n) + for w.current != nil { + status := visitor(w.current, w.entering) + switch status { + case GoToNext: + w.next() + case SkipChildren: + w.entering = false + w.next() + case Terminate: + return + } + } +} + +type nodeWalker struct { + current *Node + root *Node + entering bool +} + +func newNodeWalker(root *Node) *nodeWalker { + return &nodeWalker{ + current: root, + root: root, + entering: true, + } +} + +func (nw *nodeWalker) next() { + if (!nw.current.isContainer() || !nw.entering) && nw.current == nw.root { + nw.current = nil + return + } + if nw.entering && nw.current.isContainer() { + if nw.current.FirstChild != nil { + nw.current = nw.current.FirstChild + nw.entering = true + } else { + nw.entering = false + } + } else if nw.current.Next == nil { + nw.current = nw.current.Parent + nw.entering = false + } else { + nw.current = nw.current.Next + nw.entering = true + } +} + +func dump(ast *Node) { + fmt.Println(dumpString(ast)) +} + +func dumpR(ast *Node, depth int) string { + if ast == nil { + return "" + } + indent := bytes.Repeat([]byte("\t"), depth) + content := ast.Literal + if content == nil { + content = ast.content + } + result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content) + for n := ast.FirstChild; n != nil; n = n.Next { + result += dumpR(n, depth+1) + } + return result +} + +func dumpString(ast *Node) string { + return dumpR(ast, 0) +} diff --git a/vendor/github.com/russross/blackfriday/v2/smartypants.go b/vendor/github.com/russross/blackfriday/v2/smartypants.go new file mode 100644 index 000000000..3a220e942 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/smartypants.go @@ -0,0 +1,457 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// +// SmartyPants rendering +// +// + +package blackfriday + +import ( + "bytes" + "io" +) + +// SPRenderer is a struct containing state of a Smartypants renderer. +type SPRenderer struct { + inSingleQuote bool + inDoubleQuote bool + callbacks [256]smartCallback +} + +func wordBoundary(c byte) bool { + return c == 0 || isspace(c) || ispunct(c) +} + +func tolower(c byte) byte { + if c >= 'A' && c <= 'Z' { + return c - 'A' + 'a' + } + return c +} + +func isdigit(c byte) bool { + return c >= '0' && c <= '9' +} + +func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool { + // edge of the buffer is likely to be a tag that we don't get to see, + // so we treat it like text sometimes + + // enumerate all sixteen possibilities for (previousChar, nextChar) + // each can be one of {0, space, punct, other} + switch { + case previousChar == 0 && nextChar == 0: + // context is not any help here, so toggle + *isOpen = !*isOpen + case isspace(previousChar) && nextChar == 0: + // [ "] might be [ "foo...] + *isOpen = true + case ispunct(previousChar) && nextChar == 0: + // [!"] hmm... could be [Run!"] or [("...] + *isOpen = false + case /* isnormal(previousChar) && */ nextChar == 0: + // [a"] is probably a close + *isOpen = false + case previousChar == 0 && isspace(nextChar): + // [" ] might be [...foo" ] + *isOpen = false + case isspace(previousChar) && isspace(nextChar): + // [ " ] context is not any help here, so toggle + *isOpen = !*isOpen + case ispunct(previousChar) && isspace(nextChar): + // [!" ] is probably a close + *isOpen = false + case /* isnormal(previousChar) && */ isspace(nextChar): + // [a" ] this is one of the easy cases + *isOpen = false + case previousChar == 0 && ispunct(nextChar): + // ["!] hmm... could be ["$1.95] or ["!...] + *isOpen = false + case isspace(previousChar) && ispunct(nextChar): + // [ "!] looks more like [ "$1.95] + *isOpen = true + case ispunct(previousChar) && ispunct(nextChar): + // [!"!] context is not any help here, so toggle + *isOpen = !*isOpen + case /* isnormal(previousChar) && */ ispunct(nextChar): + // [a"!] is probably a close + *isOpen = false + case previousChar == 0 /* && isnormal(nextChar) */ : + // ["a] is probably an open + *isOpen = true + case isspace(previousChar) /* && isnormal(nextChar) */ : + // [ "a] this is one of the easy cases + *isOpen = true + case ispunct(previousChar) /* && isnormal(nextChar) */ : + // [!"a] is probably an open + *isOpen = true + default: + // [a'b] maybe a contraction? + *isOpen = false + } + + // Note that with the limited lookahead, this non-breaking + // space will also be appended to single double quotes. + if addNBSP && !*isOpen { + out.WriteString(" ") + } + + out.WriteByte('&') + if *isOpen { + out.WriteByte('l') + } else { + out.WriteByte('r') + } + out.WriteByte(quote) + out.WriteString("quo;") + + if addNBSP && *isOpen { + out.WriteString(" ") + } + + return true +} + +func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 2 { + t1 := tolower(text[1]) + + if t1 == '\'' { + nextChar := byte(0) + if len(text) >= 3 { + nextChar = text[2] + } + if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { + return 1 + } + } + + if (t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') && (len(text) < 3 || wordBoundary(text[2])) { + out.WriteString("’") + return 0 + } + + if len(text) >= 3 { + t2 := tolower(text[2]) + + if ((t1 == 'r' && t2 == 'e') || (t1 == 'l' && t2 == 'l') || (t1 == 'v' && t2 == 'e')) && + (len(text) < 4 || wordBoundary(text[3])) { + out.WriteString("’") + return 0 + } + } + } + + nextChar := byte(0) + if len(text) > 1 { + nextChar = text[1] + } + if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote, false) { + return 0 + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 3 { + t1 := tolower(text[1]) + t2 := tolower(text[2]) + + if t1 == 'c' && t2 == ')' { + out.WriteString("©") + return 2 + } + + if t1 == 'r' && t2 == ')' { + out.WriteString("®") + return 2 + } + + if len(text) >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')' { + out.WriteString("™") + return 3 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 2 { + if text[1] == '-' { + out.WriteString("—") + return 1 + } + + if wordBoundary(previousChar) && wordBoundary(text[1]) { + out.WriteString("–") + return 0 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 3 && text[1] == '-' && text[2] == '-' { + out.WriteString("—") + return 2 + } + if len(text) >= 2 && text[1] == '-' { + out.WriteString("–") + return 1 + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte, addNBSP bool) int { + if bytes.HasPrefix(text, []byte(""")) { + nextChar := byte(0) + if len(text) >= 7 { + nextChar = text[6] + } + if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, addNBSP) { + return 5 + } + } + + if bytes.HasPrefix(text, []byte("�")) { + return 3 + } + + out.WriteByte('&') + return 0 +} + +func (r *SPRenderer) smartAmp(angledQuotes, addNBSP bool) func(*bytes.Buffer, byte, []byte) int { + var quote byte = 'd' + if angledQuotes { + quote = 'a' + } + + return func(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartAmpVariant(out, previousChar, text, quote, addNBSP) + } +} + +func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 3 && text[1] == '.' && text[2] == '.' { + out.WriteString("…") + return 2 + } + + if len(text) >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.' { + out.WriteString("…") + return 4 + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 2 && text[1] == '`' { + nextChar := byte(0) + if len(text) >= 3 { + nextChar = text[2] + } + if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { + return 1 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int { + if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { + // is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b + // note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8) + // and avoid changing dates like 1/23/2005 into fractions. + numEnd := 0 + for len(text) > numEnd && isdigit(text[numEnd]) { + numEnd++ + } + if numEnd == 0 { + out.WriteByte(text[0]) + return 0 + } + denStart := numEnd + 1 + if len(text) > numEnd+3 && text[numEnd] == 0xe2 && text[numEnd+1] == 0x81 && text[numEnd+2] == 0x84 { + denStart = numEnd + 3 + } else if len(text) < numEnd+2 || text[numEnd] != '/' { + out.WriteByte(text[0]) + return 0 + } + denEnd := denStart + for len(text) > denEnd && isdigit(text[denEnd]) { + denEnd++ + } + if denEnd == denStart { + out.WriteByte(text[0]) + return 0 + } + if len(text) == denEnd || wordBoundary(text[denEnd]) && text[denEnd] != '/' { + out.WriteString("") + out.Write(text[:numEnd]) + out.WriteString("") + out.Write(text[denStart:denEnd]) + out.WriteString("") + return denEnd - 1 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int { + if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { + if text[0] == '1' && text[1] == '/' && text[2] == '2' { + if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' { + out.WriteString("½") + return 2 + } + } + + if text[0] == '1' && text[1] == '/' && text[2] == '4' { + if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h') { + out.WriteString("¼") + return 2 + } + } + + if text[0] == '3' && text[1] == '/' && text[2] == '4' { + if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's') { + out.WriteString("¾") + return 2 + } + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { + nextChar := byte(0) + if len(text) > 1 { + nextChar = text[1] + } + if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, false) { + out.WriteString(""") + } + + return 0 +} + +func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartDoubleQuoteVariant(out, previousChar, text, 'd') +} + +func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartDoubleQuoteVariant(out, previousChar, text, 'a') +} + +func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int { + i := 0 + + for i < len(text) && text[i] != '>' { + i++ + } + + out.Write(text[:i+1]) + return i +} + +type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int + +// NewSmartypantsRenderer constructs a Smartypants renderer object. +func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer { + var ( + r SPRenderer + + smartAmpAngled = r.smartAmp(true, false) + smartAmpAngledNBSP = r.smartAmp(true, true) + smartAmpRegular = r.smartAmp(false, false) + smartAmpRegularNBSP = r.smartAmp(false, true) + + addNBSP = flags&SmartypantsQuotesNBSP != 0 + ) + + if flags&SmartypantsAngledQuotes == 0 { + r.callbacks['"'] = r.smartDoubleQuote + if !addNBSP { + r.callbacks['&'] = smartAmpRegular + } else { + r.callbacks['&'] = smartAmpRegularNBSP + } + } else { + r.callbacks['"'] = r.smartAngledDoubleQuote + if !addNBSP { + r.callbacks['&'] = smartAmpAngled + } else { + r.callbacks['&'] = smartAmpAngledNBSP + } + } + r.callbacks['\''] = r.smartSingleQuote + r.callbacks['('] = r.smartParens + if flags&SmartypantsDashes != 0 { + if flags&SmartypantsLatexDashes == 0 { + r.callbacks['-'] = r.smartDash + } else { + r.callbacks['-'] = r.smartDashLatex + } + } + r.callbacks['.'] = r.smartPeriod + if flags&SmartypantsFractions == 0 { + r.callbacks['1'] = r.smartNumber + r.callbacks['3'] = r.smartNumber + } else { + for ch := '1'; ch <= '9'; ch++ { + r.callbacks[ch] = r.smartNumberGeneric + } + } + r.callbacks['<'] = r.smartLeftAngle + r.callbacks['`'] = r.smartBacktick + return &r +} + +// Process is the entry point of the Smartypants renderer. +func (r *SPRenderer) Process(w io.Writer, text []byte) { + mark := 0 + for i := 0; i < len(text); i++ { + if action := r.callbacks[text[i]]; action != nil { + if i > mark { + w.Write(text[mark:i]) + } + previousChar := byte(0) + if i > 0 { + previousChar = text[i-1] + } + var tmp bytes.Buffer + i += action(&tmp, previousChar, text[i:]) + w.Write(tmp.Bytes()) + mark = i + 1 + } + } + if mark < len(text) { + w.Write(text[mark:]) + } +} diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml b/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml new file mode 100644 index 000000000..93b1fcdb3 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml @@ -0,0 +1,16 @@ +sudo: false +language: go +go: + - 1.x + - master +matrix: + allow_failures: + - go: master + fast_finish: true +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d -s .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE b/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE new file mode 100644 index 000000000..c35c17af9 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2015 Dmitri Shuralyov + +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. diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/README.md b/vendor/github.com/shurcooL/sanitized_anchor_name/README.md new file mode 100644 index 000000000..670bf0fe6 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/README.md @@ -0,0 +1,36 @@ +sanitized_anchor_name +===================== + +[![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name) + +Package sanitized_anchor_name provides a func to create sanitized anchor names. + +Its logic can be reused by multiple packages to create interoperable anchor names +and links to those anchors. + +At this time, it does not try to ensure that generated anchor names +are unique, that responsibility falls on the caller. + +Installation +------------ + +```bash +go get -u github.com/shurcooL/sanitized_anchor_name +``` + +Example +------- + +```Go +anchorName := sanitized_anchor_name.Create("This is a header") + +fmt.Println(anchorName) + +// Output: +// this-is-a-header +``` + +License +------- + +- [MIT License](LICENSE) diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod b/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod new file mode 100644 index 000000000..1e2553475 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod @@ -0,0 +1 @@ +module github.com/shurcooL/sanitized_anchor_name diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/main.go b/vendor/github.com/shurcooL/sanitized_anchor_name/main.go new file mode 100644 index 000000000..6a77d1243 --- /dev/null +++ b/vendor/github.com/shurcooL/sanitized_anchor_name/main.go @@ -0,0 +1,29 @@ +// Package sanitized_anchor_name provides a func to create sanitized anchor names. +// +// Its logic can be reused by multiple packages to create interoperable anchor names +// and links to those anchors. +// +// At this time, it does not try to ensure that generated anchor names +// are unique, that responsibility falls on the caller. +package sanitized_anchor_name // import "github.com/shurcooL/sanitized_anchor_name" + +import "unicode" + +// Create returns a sanitized anchor name for the given text. +func Create(text string) string { + var anchorName []rune + var futureDash = false + for _, r := range text { + switch { + case unicode.IsLetter(r) || unicode.IsNumber(r): + if futureDash && len(anchorName) > 0 { + anchorName = append(anchorName, '-') + } + futureDash = false + anchorName = append(anchorName, unicode.ToLower(r)) + default: + futureDash = true + } + } + return string(anchorName) +} diff --git a/vendor/github.com/urfave/cli/.travis.yml b/vendor/github.com/urfave/cli/.travis.yml deleted file mode 100644 index cf8d0980d..000000000 --- a/vendor/github.com/urfave/cli/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -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 diff --git a/vendor/github.com/urfave/cli/CHANGELOG.md b/vendor/github.com/urfave/cli/CHANGELOG.md deleted file mode 100644 index 401eae5a2..000000000 --- a/vendor/github.com/urfave/cli/CHANGELOG.md +++ /dev/null @@ -1,435 +0,0 @@ -# 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 -- -`cli.App.RunAndExitOnError`, which should now be done by returning an error -that fulfills `cli.ExitCoder` to `cli.App.Run`. -- 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 diff --git a/vendor/github.com/urfave/cli/README.md b/vendor/github.com/urfave/cli/README.md deleted file mode 100644 index 2bbbd8ea9..000000000 --- a/vendor/github.com/urfave/cli/README.md +++ /dev/null @@ -1,1381 +0,0 @@ -cli -=== - -[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli) -[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli) -[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) -[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) -[![top level coverage](https://gocover.io/_badge/github.com/urfave/cli?0 "top level coverage")](http://gocover.io/github.com/urfave/cli) / -[![altsrc coverage](https://gocover.io/_badge/github.com/urfave/cli/altsrc?0 "altsrc coverage")](http://gocover.io/github.com/urfave/cli/altsrc) - -**Notice:** This is the library formerly known as -`github.com/codegangsta/cli` -- Github will automatically redirect requests -to this repository, but we recommend updating your references for clarity. - -cli is a simple, fast, and fun package for building command line apps in Go. The -goal is to enable developers to write fast and distributable command line -applications in an expressive way. - - - -- [Overview](#overview) -- [Installation](#installation) - * [Supported platforms](#supported-platforms) - * [Using the `v2` branch](#using-the-v2-branch) - * [Pinning to the `v1` releases](#pinning-to-the-v1-releases) -- [Getting Started](#getting-started) -- [Examples](#examples) - * [Arguments](#arguments) - * [Flags](#flags) - + [Placeholder Values](#placeholder-values) - + [Alternate Names](#alternate-names) - + [Ordering](#ordering) - + [Values from the Environment](#values-from-the-environment) - + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others) - * [Subcommands](#subcommands) - * [Subcommands categories](#subcommands-categories) - * [Exit code](#exit-code) - * [Bash Completion](#bash-completion) - + [Enabling](#enabling) - + [Distribution](#distribution) - + [Customization](#customization) - * [Generated Help Text](#generated-help-text) - + [Customization](#customization-1) - * [Version Flag](#version-flag) - + [Customization](#customization-2) - + [Full API Example](#full-api-example) -- [Contribution Guidelines](#contribution-guidelines) - - - -## Overview - -Command line apps are usually so tiny that there is absolutely no reason why -your code should *not* be self-documenting. Things like generating help text and -parsing command flags/options should not hinder productivity when writing a -command line app. - -**This is where cli comes into play.** cli makes command line programming fun, -organized, and expressive! - -## Installation - -Make sure you have a working Go environment. Go version 1.2+ is supported. [See -the install instructions for Go](http://golang.org/doc/install.html). - -To install cli, simply run: -``` -$ go get github.com/urfave/cli -``` - -Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can -be easily used: -``` -export PATH=$PATH:$GOPATH/bin -``` - -### Supported platforms - -cli is tested against multiple versions of Go on Linux, and against the latest -released version of Go on OS X and Windows. For full details, see -[`./.travis.yml`](./.travis.yml) and [`./appveyor.yml`](./appveyor.yml). - -### Using the `v2` branch - -**Warning**: The `v2` branch is currently unreleased and considered unstable. - -There is currently a long-lived branch named `v2` that is intended to land as -the new `master` branch once development there has settled down. The current -`master` branch (mirrored as `v1`) is being manually merged into `v2` on -an irregular human-based schedule, but generally if one wants to "upgrade" to -`v2` *now* and accept the volatility (read: "awesomeness") that comes along with -that, please use whatever version pinning of your preference, such as via -`gopkg.in`: - -``` -$ go get gopkg.in/urfave/cli.v2 -``` - -``` go -... -import ( - "gopkg.in/urfave/cli.v2" // imports as package "cli" -) -... -``` - -### Pinning to the `v1` releases - -Similarly to the section above describing use of the `v2` branch, if one wants -to avoid any unexpected compatibility pains once `v2` becomes `master`, then -pinning to `v1` is an acceptable option, e.g.: - -``` -$ go get gopkg.in/urfave/cli.v1 -``` - -``` go -... -import ( - "gopkg.in/urfave/cli.v1" // imports as package "cli" -) -... -``` - -This will pull the latest tagged `v1` release (e.g. `v1.18.1` at the time of writing). - -## Getting Started - -One of the philosophies behind cli is that an API should be playful and full of -discovery. So a cli app can be as little as one line of code in `main()`. - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - cli.NewApp().Run(os.Args) -} -``` - -This app will run and show help text, but is not very useful. Let's give an -action to execute and some help documentation: - - -``` go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - app.Name = "boom" - app.Usage = "make an explosive entrance" - app.Action = func(c *cli.Context) error { - fmt.Println("boom! I say!") - return nil - } - - app.Run(os.Args) -} -``` - -Running this already gives you a ton of functionality, plus support for things -like subcommands and flags, which are covered below. - -## Examples - -Being a programmer can be a lonely job. Thankfully by the power of automation -that is not the case! Let's create a greeter app to fend off our demons of -loneliness! - -Start by creating a directory named `greet`, and within it, add a file, -`greet.go` with the following code in it: - - -``` go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - app.Name = "greet" - app.Usage = "fight the loneliness!" - app.Action = func(c *cli.Context) error { - fmt.Println("Hello friend!") - return nil - } - - app.Run(os.Args) -} -``` - -Install our command to the `$GOPATH/bin` directory: - -``` -$ go install -``` - -Finally run our new command: - -``` -$ greet -Hello friend! -``` - -cli also generates neat help text: - -``` -$ greet help -NAME: - greet - fight the loneliness! - -USAGE: - greet [global options] command [command options] [arguments...] - -VERSION: - 0.0.0 - -COMMANDS: - help, h Shows a list of commands or help for one command - -GLOBAL OPTIONS - --version Shows version information -``` - -### Arguments - -You can lookup arguments by calling the `Args` function on `cli.Context`, e.g.: - - -``` go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Action = func(c *cli.Context) error { - fmt.Printf("Hello %q", c.Args().Get(0)) - return nil - } - - app.Run(os.Args) -} -``` - -### Flags - -Setting and querying flags is simple. - - -``` go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Flags = []cli.Flag { - cli.StringFlag{ - Name: "lang", - Value: "english", - Usage: "language for the greeting", - }, - } - - app.Action = func(c *cli.Context) error { - name := "Nefertiti" - if c.NArg() > 0 { - name = c.Args().Get(0) - } - if c.String("lang") == "spanish" { - fmt.Println("Hola", name) - } else { - fmt.Println("Hello", name) - } - return nil - } - - app.Run(os.Args) -} -``` - -You can also set a destination variable for a flag, to which the content will be -scanned. - - -``` go -package main - -import ( - "os" - "fmt" - - "github.com/urfave/cli" -) - -func main() { - var language string - - app := cli.NewApp() - - app.Flags = []cli.Flag { - cli.StringFlag{ - Name: "lang", - Value: "english", - Usage: "language for the greeting", - Destination: &language, - }, - } - - app.Action = func(c *cli.Context) error { - name := "someone" - if c.NArg() > 0 { - name = c.Args()[0] - } - if language == "spanish" { - fmt.Println("Hola", name) - } else { - fmt.Println("Hello", name) - } - return nil - } - - app.Run(os.Args) -} -``` - -See full list of flags at http://godoc.org/github.com/urfave/cli - -#### Placeholder Values - -Sometimes it's useful to specify a flag's value within the usage string itself. -Such placeholders are indicated with back quotes. - -For example this: - - -```go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "config, c", - Usage: "Load configuration from `FILE`", - }, - } - - app.Run(os.Args) -} -``` - -Will result in help output like: - -``` ---config FILE, -c FILE Load configuration from FILE -``` - -Note that only the first placeholder is used. Subsequent back-quoted words will -be left as-is. - -#### Alternate Names - -You can set alternate (or short) names for flags by providing a comma-delimited -list for the `Name`. e.g. - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Flags = []cli.Flag { - cli.StringFlag{ - Name: "lang, l", - Value: "english", - Usage: "language for the greeting", - }, - } - - app.Run(os.Args) -} -``` - -That flag can then be set with `--lang spanish` or `-l spanish`. Note that -giving two different forms of the same flag in the same command invocation is an -error. - -#### Ordering - -Flags for the application and commands are shown in the order they are defined. -However, it's possible to sort them from outside this library by using `FlagsByName` -or `CommandsByName` with `sort`. - -For example this: - - -``` go -package main - -import ( - "os" - "sort" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Flags = []cli.Flag { - cli.StringFlag{ - Name: "lang, l", - Value: "english", - Usage: "Language for the greeting", - }, - cli.StringFlag{ - Name: "config, c", - Usage: "Load configuration from `FILE`", - }, - } - - app.Commands = []cli.Command{ - { - Name: "complete", - Aliases: []string{"c"}, - Usage: "complete a task on the list", - Action: func(c *cli.Context) error { - return nil - }, - }, - { - Name: "add", - Aliases: []string{"a"}, - Usage: "add a task to the list", - Action: func(c *cli.Context) error { - return nil - }, - }, - } - - sort.Sort(cli.FlagsByName(app.Flags)) - sort.Sort(cli.CommandsByName(app.Commands)) - - app.Run(os.Args) -} -``` - -Will result in help output like: - -``` ---config FILE, -c FILE Load configuration from FILE ---lang value, -l value Language for the greeting (default: "english") -``` - -#### Values from the Environment - -You can also have the default value set from the environment via `EnvVar`. e.g. - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Flags = []cli.Flag { - cli.StringFlag{ - Name: "lang, l", - Value: "english", - Usage: "language for the greeting", - EnvVar: "APP_LANG", - }, - } - - app.Run(os.Args) -} -``` - -The `EnvVar` may also be given as a comma-delimited "cascade", where the first -environment variable that resolves is used as the default. - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Flags = []cli.Flag { - cli.StringFlag{ - Name: "lang, l", - Value: "english", - Usage: "language for the greeting", - EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG", - }, - } - - app.Run(os.Args) -} -``` - -#### Values from alternate input sources (YAML, TOML, and others) - -There is a separate package altsrc that adds support for getting flag values -from other file input sources. - -Currently supported input source formats: -* YAML -* TOML - -In order to get values for a flag from an alternate input source the following -code would be added to wrap an existing cli.Flag like below: - -``` go - altsrc.NewIntFlag(cli.IntFlag{Name: "test"}) -``` - -Initialization must also occur for these flags. Below is an example initializing -getting data from a yaml file below. - -``` go - command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) -``` - -The code above will use the "load" string as a flag name to get the file name of -a yaml file from the cli.Context. It will then use that file name to initialize -the yaml input source for any flags that are defined on that command. As a note -the "load" flag used would also have to be defined on the command flags in order -for this code snipped to work. - -Currently only the aboved specified formats are supported but developers can -add support for other input sources by implementing the -altsrc.InputSourceContext for their given sources. - -Here is a more complete sample of a command using YAML support: - - -``` go -package notmain - -import ( - "fmt" - "os" - - "github.com/urfave/cli" - "github.com/urfave/cli/altsrc" -) - -func main() { - app := cli.NewApp() - - flags := []cli.Flag{ - altsrc.NewIntFlag(cli.IntFlag{Name: "test"}), - cli.StringFlag{Name: "load"}, - } - - app.Action = func(c *cli.Context) error { - fmt.Println("yaml ist rad") - return nil - } - - app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load")) - app.Flags = flags - - app.Run(os.Args) -} -``` - -### Subcommands - -Subcommands can be defined for a more git-like command line app. - - -```go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Commands = []cli.Command{ - { - Name: "add", - Aliases: []string{"a"}, - Usage: "add a task to the list", - Action: func(c *cli.Context) error { - fmt.Println("added task: ", c.Args().First()) - return nil - }, - }, - { - Name: "complete", - Aliases: []string{"c"}, - Usage: "complete a task on the list", - Action: func(c *cli.Context) error { - fmt.Println("completed task: ", c.Args().First()) - return nil - }, - }, - { - Name: "template", - Aliases: []string{"t"}, - Usage: "options for task templates", - Subcommands: []cli.Command{ - { - Name: "add", - Usage: "add a new template", - Action: func(c *cli.Context) error { - fmt.Println("new task template: ", c.Args().First()) - return nil - }, - }, - { - Name: "remove", - Usage: "remove an existing template", - Action: func(c *cli.Context) error { - fmt.Println("removed task template: ", c.Args().First()) - return nil - }, - }, - }, - }, - } - - app.Run(os.Args) -} -``` - -### Subcommands categories - -For additional organization in apps that have many subcommands, you can -associate a category for each command to group them together in the help -output. - -E.g. - -```go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - - app.Commands = []cli.Command{ - { - Name: "noop", - }, - { - Name: "add", - Category: "template", - }, - { - Name: "remove", - Category: "template", - }, - } - - app.Run(os.Args) -} -``` - -Will include: - -``` -COMMANDS: - noop - - Template actions: - add - remove -``` - -### Exit code - -Calling `App.Run` will not automatically call `os.Exit`, which means that by -default the exit code will "fall through" to being `0`. An explicit exit code -may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a -`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.: - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - app := cli.NewApp() - app.Flags = []cli.Flag{ - cli.BoolTFlag{ - Name: "ginger-crouton", - Usage: "is it in the soup?", - }, - } - app.Action = func(ctx *cli.Context) error { - if !ctx.Bool("ginger-crouton") { - return cli.NewExitError("it is not in the soup", 86) - } - return nil - } - - app.Run(os.Args) -} -``` - -### Bash Completion - -You can enable completion commands by setting the `EnableBashCompletion` -flag on the `App` object. By default, this setting will only auto-complete to -show an app's subcommands, but you can write your own completion methods for -the App or its subcommands. - - -``` go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func main() { - tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"} - - app := cli.NewApp() - app.EnableBashCompletion = true - app.Commands = []cli.Command{ - { - Name: "complete", - Aliases: []string{"c"}, - Usage: "complete a task on the list", - Action: func(c *cli.Context) error { - fmt.Println("completed task: ", c.Args().First()) - return nil - }, - BashComplete: func(c *cli.Context) { - // This will complete if no args are passed - if c.NArg() > 0 { - return - } - for _, t := range tasks { - fmt.Println(t) - } - }, - }, - } - - app.Run(os.Args) -} -``` - -#### Enabling - -Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while -setting the `PROG` variable to the name of your program: - -`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete` - -#### Distribution - -Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename -it to the name of the program you wish to add autocomplete support for (or -automatically install it there if you are distributing a package). Don't forget -to source the file to make it active in the current shell. - -``` -sudo cp src/bash_autocomplete /etc/bash_completion.d/ -source /etc/bash_completion.d/ -``` - -Alternatively, you can just document that users should source the generic -`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set -to the name of their program (as above). - -#### Customization - -The default bash completion flag (`--generate-bash-completion`) is defined as -`cli.BashCompletionFlag`, and may be redefined if desired, e.g.: - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - cli.BashCompletionFlag = cli.BoolFlag{ - Name: "compgen", - Hidden: true, - } - - app := cli.NewApp() - app.EnableBashCompletion = true - app.Commands = []cli.Command{ - { - Name: "wat", - }, - } - app.Run(os.Args) -} -``` - -### Generated Help Text - -The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked -by the cli internals in order to print generated help text for the app, command, -or subcommand, and break execution. - -#### Customization - -All of the help text generation may be customized, and at multiple levels. The -templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and -`SubcommandHelpTemplate` which may be reassigned or augmented, and full override -is possible by assigning a compatible func to the `cli.HelpPrinter` variable, -e.g.: - - -``` go -package main - -import ( - "fmt" - "io" - "os" - - "github.com/urfave/cli" -) - -func main() { - // EXAMPLE: Append to an existing template - cli.AppHelpTemplate = fmt.Sprintf(`%s - -WEBSITE: http://awesometown.example.com - -SUPPORT: support@awesometown.example.com - -`, cli.AppHelpTemplate) - - // EXAMPLE: Override a template - cli.AppHelpTemplate = `NAME: - {{.Name}} - {{.Usage}} -USAGE: - {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} - {{if len .Authors}} -AUTHOR: - {{range .Authors}}{{ . }}{{end}} - {{end}}{{if .Commands}} -COMMANDS: -{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}} -GLOBAL OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}}{{if .Copyright }} -COPYRIGHT: - {{.Copyright}} - {{end}}{{if .Version}} -VERSION: - {{.Version}} - {{end}} -` - - // EXAMPLE: Replace the `HelpPrinter` func - cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) { - fmt.Println("Ha HA. I pwnd the help!!1") - } - - cli.NewApp().Run(os.Args) -} -``` - -The default flag may be customized to something other than `-h/--help` by -setting `cli.HelpFlag`, e.g.: - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - cli.HelpFlag = cli.BoolFlag{ - Name: "halp, haaaaalp", - Usage: "HALP", - EnvVar: "SHOW_HALP,HALPPLZ", - } - - cli.NewApp().Run(os.Args) -} -``` - -### Version Flag - -The default version flag (`-v/--version`) is defined as `cli.VersionFlag`, which -is checked by the cli internals in order to print the `App.Version` via -`cli.VersionPrinter` and break execution. - -#### Customization - -The default flag may be customized to something other than `-v/--version` by -setting `cli.VersionFlag`, e.g.: - - -``` go -package main - -import ( - "os" - - "github.com/urfave/cli" -) - -func main() { - cli.VersionFlag = cli.BoolFlag{ - Name: "print-version, V", - Usage: "print only the version", - } - - app := cli.NewApp() - app.Name = "partay" - app.Version = "19.99.0" - app.Run(os.Args) -} -``` - -Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.: - - -``` go -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -var ( - Revision = "fafafaf" -) - -func main() { - cli.VersionPrinter = func(c *cli.Context) { - fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision) - } - - app := cli.NewApp() - app.Name = "partay" - app.Version = "19.99.0" - app.Run(os.Args) -} -``` - -#### Full API Example - -**Notice**: This is a contrived (functioning) example meant strictly for API -demonstration purposes. Use of one's imagination is encouraged. - - -``` go -package main - -import ( - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "time" - - "github.com/urfave/cli" -) - -func init() { - cli.AppHelpTemplate += "\nCUSTOMIZED: you bet ur muffins\n" - cli.CommandHelpTemplate += "\nYMMV\n" - cli.SubcommandHelpTemplate += "\nor something\n" - - cli.HelpFlag = cli.BoolFlag{Name: "halp"} - cli.BashCompletionFlag = cli.BoolFlag{Name: "compgen", Hidden: true} - cli.VersionFlag = cli.BoolFlag{Name: "print-version, V"} - - cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) { - fmt.Fprintf(w, "best of luck to you\n") - } - cli.VersionPrinter = func(c *cli.Context) { - fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version) - } - cli.OsExiter = func(c int) { - fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c) - } - cli.ErrWriter = ioutil.Discard - cli.FlagStringer = func(fl cli.Flag) string { - return fmt.Sprintf("\t\t%s", fl.GetName()) - } -} - -type hexWriter struct{} - -func (w *hexWriter) Write(p []byte) (int, error) { - for _, b := range p { - fmt.Printf("%x", b) - } - fmt.Printf("\n") - - return len(p), nil -} - -type genericType struct{ - s string -} - -func (g *genericType) Set(value string) error { - g.s = value - return nil -} - -func (g *genericType) String() string { - return g.s -} - -func main() { - app := cli.NewApp() - app.Name = "kənˈtrīv" - app.Version = "19.99.0" - app.Compiled = time.Now() - app.Authors = []cli.Author{ - cli.Author{ - Name: "Example Human", - Email: "human@example.com", - }, - } - app.Copyright = "(c) 1999 Serious Enterprise" - app.HelpName = "contrive" - app.Usage = "demonstrate available API" - app.UsageText = "contrive - demonstrating the available API" - app.ArgsUsage = "[args and such]" - app.Commands = []cli.Command{ - cli.Command{ - Name: "doo", - Aliases: []string{"do"}, - Category: "motion", - Usage: "do the doo", - UsageText: "doo - does the dooing", - Description: "no really, there is a lot of dooing to be done", - ArgsUsage: "[arrgh]", - Flags: []cli.Flag{ - cli.BoolFlag{Name: "forever, forevvarr"}, - }, - Subcommands: cli.Commands{ - cli.Command{ - Name: "wop", - Action: wopAction, - }, - }, - SkipFlagParsing: false, - HideHelp: false, - Hidden: false, - HelpName: "doo!", - BashComplete: func(c *cli.Context) { - fmt.Fprintf(c.App.Writer, "--better\n") - }, - Before: func(c *cli.Context) error { - fmt.Fprintf(c.App.Writer, "brace for impact\n") - return nil - }, - After: func(c *cli.Context) error { - fmt.Fprintf(c.App.Writer, "did we lose anyone?\n") - return nil - }, - Action: func(c *cli.Context) error { - c.Command.FullName() - c.Command.HasName("wop") - c.Command.Names() - c.Command.VisibleFlags() - fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n") - if c.Bool("forever") { - c.Command.Run(c) - } - return nil - }, - OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error { - fmt.Fprintf(c.App.Writer, "for shame\n") - return err - }, - }, - } - app.Flags = []cli.Flag{ - cli.BoolFlag{Name: "fancy"}, - cli.BoolTFlag{Name: "fancier"}, - cli.DurationFlag{Name: "howlong, H", Value: time.Second * 3}, - cli.Float64Flag{Name: "howmuch"}, - cli.GenericFlag{Name: "wat", Value: &genericType{}}, - cli.Int64Flag{Name: "longdistance"}, - cli.Int64SliceFlag{Name: "intervals"}, - cli.IntFlag{Name: "distance"}, - cli.IntSliceFlag{Name: "times"}, - cli.StringFlag{Name: "dance-move, d"}, - cli.StringSliceFlag{Name: "names, N"}, - cli.UintFlag{Name: "age"}, - cli.Uint64Flag{Name: "bigage"}, - } - app.EnableBashCompletion = true - app.HideHelp = false - app.HideVersion = false - app.BashComplete = func(c *cli.Context) { - fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n") - } - app.Before = func(c *cli.Context) error { - fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n") - return nil - } - app.After = func(c *cli.Context) error { - fmt.Fprintf(c.App.Writer, "Phew!\n") - return nil - } - app.CommandNotFound = func(c *cli.Context, command string) { - fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command) - } - app.OnUsageError = func(c *cli.Context, err error, isSubcommand bool) error { - if isSubcommand { - return err - } - - fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err) - return nil - } - app.Action = func(c *cli.Context) error { - cli.DefaultAppComplete(c) - cli.HandleExitCoder(errors.New("not an exit coder, though")) - cli.ShowAppHelp(c) - cli.ShowCommandCompletions(c, "nope") - cli.ShowCommandHelp(c, "also-nope") - cli.ShowCompletions(c) - cli.ShowSubcommandHelp(c) - cli.ShowVersion(c) - - categories := c.App.Categories() - categories.AddCommand("sounds", cli.Command{ - Name: "bloop", - }) - - for _, category := range c.App.Categories() { - fmt.Fprintf(c.App.Writer, "%s\n", category.Name) - fmt.Fprintf(c.App.Writer, "%#v\n", category.Commands) - fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands()) - } - - fmt.Printf("%#v\n", c.App.Command("doo")) - if c.Bool("infinite") { - c.App.Run([]string{"app", "doo", "wop"}) - } - - if c.Bool("forevar") { - c.App.RunAsSubcommand(c) - } - c.App.Setup() - fmt.Printf("%#v\n", c.App.VisibleCategories()) - fmt.Printf("%#v\n", c.App.VisibleCommands()) - fmt.Printf("%#v\n", c.App.VisibleFlags()) - - fmt.Printf("%#v\n", c.Args().First()) - if len(c.Args()) > 0 { - fmt.Printf("%#v\n", c.Args()[1]) - } - fmt.Printf("%#v\n", c.Args().Present()) - fmt.Printf("%#v\n", c.Args().Tail()) - - set := flag.NewFlagSet("contrive", 0) - nc := cli.NewContext(c.App, set, c) - - fmt.Printf("%#v\n", nc.Args()) - fmt.Printf("%#v\n", nc.Bool("nope")) - fmt.Printf("%#v\n", nc.BoolT("nerp")) - fmt.Printf("%#v\n", nc.Duration("howlong")) - fmt.Printf("%#v\n", nc.Float64("hay")) - fmt.Printf("%#v\n", nc.Generic("bloop")) - fmt.Printf("%#v\n", nc.Int64("bonk")) - fmt.Printf("%#v\n", nc.Int64Slice("burnks")) - fmt.Printf("%#v\n", nc.Int("bips")) - fmt.Printf("%#v\n", nc.IntSlice("blups")) - fmt.Printf("%#v\n", nc.String("snurt")) - fmt.Printf("%#v\n", nc.StringSlice("snurkles")) - fmt.Printf("%#v\n", nc.Uint("flub")) - fmt.Printf("%#v\n", nc.Uint64("florb")) - fmt.Printf("%#v\n", nc.GlobalBool("global-nope")) - fmt.Printf("%#v\n", nc.GlobalBoolT("global-nerp")) - fmt.Printf("%#v\n", nc.GlobalDuration("global-howlong")) - fmt.Printf("%#v\n", nc.GlobalFloat64("global-hay")) - fmt.Printf("%#v\n", nc.GlobalGeneric("global-bloop")) - fmt.Printf("%#v\n", nc.GlobalInt("global-bips")) - fmt.Printf("%#v\n", nc.GlobalIntSlice("global-blups")) - fmt.Printf("%#v\n", nc.GlobalString("global-snurt")) - fmt.Printf("%#v\n", nc.GlobalStringSlice("global-snurkles")) - - fmt.Printf("%#v\n", nc.FlagNames()) - fmt.Printf("%#v\n", nc.GlobalFlagNames()) - fmt.Printf("%#v\n", nc.GlobalIsSet("wat")) - fmt.Printf("%#v\n", nc.GlobalSet("wat", "nope")) - fmt.Printf("%#v\n", nc.NArg()) - fmt.Printf("%#v\n", nc.NumFlags()) - fmt.Printf("%#v\n", nc.Parent()) - - nc.Set("wat", "also-nope") - - ec := cli.NewExitError("ohwell", 86) - fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode()) - fmt.Printf("made it!\n") - return ec - } - - if os.Getenv("HEXY") != "" { - app.Writer = &hexWriter{} - app.ErrWriter = &hexWriter{} - } - - app.Metadata = map[string]interface{}{ - "layers": "many", - "explicable": false, - "whatever-values": 19.99, - } - - app.Run(os.Args) -} - -func wopAction(c *cli.Context) error { - fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n") - return nil -} -``` - -## Contribution Guidelines - -Feel free to put up a pull request to fix a bug or maybe add a feature. I will -give it a code review and make sure that it does not break backwards -compatibility. If I or any other collaborators agree that it is in line with -the vision of the project, we will work with you to get the code into -a mergeable state and merge it into the master branch. - -If you have contributed something significant to the project, we will most -likely add you as a collaborator. As a collaborator you are given the ability -to merge others pull requests. It is very important that new code does not -break existing code, so be careful about what code you do choose to merge. - -If you feel like you have contributed to the project but have not yet been -added as a collaborator, we probably forgot to add you, please open an issue. diff --git a/vendor/github.com/urfave/cli/appveyor.yml b/vendor/github.com/urfave/cli/appveyor.yml deleted file mode 100644 index 1e1489c36..000000000 --- a/vendor/github.com/urfave/cli/appveyor.yml +++ /dev/null @@ -1,26 +0,0 @@ -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 diff --git a/vendor/github.com/urfave/cli/category.go b/vendor/github.com/urfave/cli/category.go deleted file mode 100644 index 1a6055023..000000000 --- a/vendor/github.com/urfave/cli/category.go +++ /dev/null @@ -1,44 +0,0 @@ -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 -} diff --git a/vendor/github.com/urfave/cli/context.go b/vendor/github.com/urfave/cli/context.go deleted file mode 100644 index db94191e2..000000000 --- a/vendor/github.com/urfave/cli/context.go +++ /dev/null @@ -1,278 +0,0 @@ -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 -} diff --git a/vendor/github.com/urfave/cli/flag-types.json b/vendor/github.com/urfave/cli/flag-types.json deleted file mode 100644 index 122310785..000000000 --- a/vendor/github.com/urfave/cli/flag-types.json +++ /dev/null @@ -1,93 +0,0 @@ -[ - { - "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)" - } -] diff --git a/vendor/github.com/urfave/cli/flag.go b/vendor/github.com/urfave/cli/flag.go deleted file mode 100644 index 877ff3523..000000000 --- a/vendor/github.com/urfave/cli/flag.go +++ /dev/null @@ -1,799 +0,0 @@ -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) -} diff --git a/vendor/github.com/urfave/cli/flag_generated.go b/vendor/github.com/urfave/cli/flag_generated.go deleted file mode 100644 index 491b61956..000000000 --- a/vendor/github.com/urfave/cli/flag_generated.go +++ /dev/null @@ -1,627 +0,0 @@ -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 -} diff --git a/vendor/github.com/urfave/cli/generate-flag-types b/vendor/github.com/urfave/cli/generate-flag-types deleted file mode 100644 index 7147381ce..000000000 --- a/vendor/github.com/urfave/cli/generate-flag-types +++ /dev/null @@ -1,255 +0,0 @@ -#!/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()) diff --git a/vendor/github.com/urfave/cli/runtests b/vendor/github.com/urfave/cli/runtests deleted file mode 100644 index ee22bdeed..000000000 --- a/vendor/github.com/urfave/cli/runtests +++ /dev/null @@ -1,122 +0,0 @@ -#!/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()) diff --git a/vendor/github.com/urfave/cli/.flake8 b/vendor/github.com/urfave/cli/v2/.flake8 similarity index 100% rename from vendor/github.com/urfave/cli/.flake8 rename to vendor/github.com/urfave/cli/v2/.flake8 diff --git a/vendor/github.com/urfave/cli/.gitignore b/vendor/github.com/urfave/cli/v2/.gitignore similarity index 59% rename from vendor/github.com/urfave/cli/.gitignore rename to vendor/github.com/urfave/cli/v2/.gitignore index faf70c4c2..b013e4ac6 100644 --- a/vendor/github.com/urfave/cli/.gitignore +++ b/vendor/github.com/urfave/cli/v2/.gitignore @@ -1,2 +1,5 @@ *.coverprofile +*.orig node_modules/ +vendor +.idea diff --git a/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..41ba294f6 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting Dan Buch at dan@meatballhat.com. All complaints will be +reviewed and investigated and will result in a response that is deemed necessary +and appropriate to the circumstances. The project team is obligated to maintain +confidentiality with regard to the reporter of an incident. Further details of +specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + diff --git a/vendor/github.com/urfave/cli/LICENSE b/vendor/github.com/urfave/cli/v2/LICENSE similarity index 100% rename from vendor/github.com/urfave/cli/LICENSE rename to vendor/github.com/urfave/cli/v2/LICENSE diff --git a/vendor/github.com/urfave/cli/v2/README.md b/vendor/github.com/urfave/cli/v2/README.md new file mode 100644 index 000000000..e7fb3d755 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/README.md @@ -0,0 +1,68 @@ +cli +=== + +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli) + +[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli) +[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) +[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) +[![codecov](https://codecov.io/gh/urfave/cli/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/cli) + +cli is a simple, fast, and fun package for building command line apps in Go. The +goal is to enable developers to write fast and distributable command line +applications in an expressive way. + +## Usage Documentation + +Usage documentation exists for each major version. Don't know what version you're on? You're probably using the version from the `master` branch, which is currently `v2`. + +- `v2` - [./docs/v2/manual.md](./docs/v2/manual.md) +- `v1` - [./docs/v1/manual.md](./docs/v1/manual.md) + +## Installation + +Make sure you have a working Go environment. Go version 1.11+ is supported. [See the install instructions for Go](http://golang.org/doc/install.html). + +Go Modules are strongly recommended when using this package. [See the go blog guide on using Go Modules](https://blog.golang.org/using-go-modules). + +### Using `v2` releases + +``` +$ GO111MODULE=on go get github.com/urfave/cli/v2 +``` + +```go +... +import ( + "github.com/urfave/cli/v2" // imports as package "cli" +) +... +``` + +### Using `v1` releases + +``` +$ GO111MODULE=on go get github.com/urfave/cli +``` + +```go +... +import ( + "github.com/urfave/cli" +) +... +``` + +### GOPATH + +Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can +be easily used: +``` +export PATH=$PATH:$GOPATH/bin +``` + +### Supported platforms + +cli is tested against multiple versions of Go on Linux, and against the latest +released version of Go on OS X and Windows. This project uses Github Actions for +builds. For more build info, please look at the [./.github/workflows/cli.yml](https://github.com/urfave/cli/blob/master/.github/workflows/cli.yml). diff --git a/vendor/github.com/urfave/cli/app.go b/vendor/github.com/urfave/cli/v2/app.go similarity index 65% rename from vendor/github.com/urfave/cli/app.go rename to vendor/github.com/urfave/cli/v2/app.go index 51fc45d87..c04e9afda 100644 --- a/vendor/github.com/urfave/cli/app.go +++ b/vendor/github.com/urfave/cli/v2/app.go @@ -1,23 +1,22 @@ package cli import ( + "context" + "flag" "fmt" "io" - "io/ioutil" "os" "path/filepath" + "reflect" "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. "+ + changeLogURL = "https://github.com/urfave/cli/blob/master/docs/CHANGELOG.md" + appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", 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) ) @@ -40,7 +39,7 @@ type App struct { // Description of the program Description string // List of commands to execute - Commands []Command + Commands []*Command // List of flags to parse Flags []Flag // Boolean to enable bash completion commands @@ -49,9 +48,9 @@ type App struct { 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 contains the categorized commands and is populated on app startup categories CommandCategories - // An action to execute when the bash-completion flag is set + // An action to execute when the shell 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 @@ -59,12 +58,8 @@ type App struct { // 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{} - + Action ActionFunc // Execute this function if the proper command cannot be found CommandNotFound CommandNotFoundFunc // Execute this function if an usage error occurs @@ -72,17 +67,16 @@ type App struct { // Compilation date Compiled time.Time // List of all authors who contributed - Authors []Author + 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 + // Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to + // function as a default, so this is optional. + ExitErrHandler ExitErrHandlerFunc // Other custom info Metadata map[string]interface{} // Carries a function which returns app specific info. @@ -91,6 +85,10 @@ type App struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomAppHelpTemplate string + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool didSetup bool } @@ -113,7 +111,6 @@ func NewApp() *App { HelpName: filepath.Base(os.Args[0]), Usage: "A new cli application", UsageText: "", - Version: "0.0.0", BashComplete: DefaultAppComplete, Action: helpCommand.Action, Compiled: compileTime(), @@ -131,22 +128,52 @@ func (a *App) Setup() { a.didSetup = true - if a.Author != "" || a.Email != "" { - a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) + if a.Name == "" { + a.Name = filepath.Base(os.Args[0]) } - newCmds := []Command{} + if a.HelpName == "" { + a.HelpName = filepath.Base(os.Args[0]) + } + + if a.Usage == "" { + a.Usage = "A new cli application" + } + + if a.Version == "" { + a.HideVersion = true + } + + if a.BashComplete == nil { + a.BashComplete = DefaultAppComplete + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + if a.Compiled == (time.Time{}) { + a.Compiled = compileTime() + } + + if a.Writer == nil { + a.Writer = os.Stdout + } + + var newCommands []*Command + for _, c := range a.Commands { if c.HelpName == "" { c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) } - newCmds = append(newCmds, c) + newCommands = append(newCommands, c) } - a.Commands = newCmds + a.Commands = newCommands if a.Command(helpCommand.Name) == nil && !a.HideHelp { - a.Commands = append(a.Commands, helpCommand) - if (HelpFlag != BoolFlag{}) { + a.appendCommand(helpCommand) + + if HelpFlag != nil { a.appendFlag(HelpFlag) } } @@ -155,11 +182,11 @@ func (a *App) Setup() { a.appendFlag(VersionFlag) } - a.categories = CommandCategories{} + a.categories = newCommandCategories() for _, command := range a.Commands { - a.categories = a.categories.AddCommand(command.Category, command) + a.categories.AddCommand(command.Category, command) } - sort.Sort(a.categories) + sort.Sort(a.categories.(*commandCategories)) if a.Metadata == nil { a.Metadata = make(map[string]interface{}) @@ -170,9 +197,24 @@ func (a *App) Setup() { } } +func (a *App) newFlagSet() (*flag.FlagSet, error) { + return flagSet(a.Name, a.Flags) +} + +func (a *App) useShortOptionHandling() bool { + return a.UseShortOptionHandling +} + // 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) { + return a.RunContext(context.Background(), arguments) +} + +// RunContext is like Run except it takes a Context that will be +// passed to its commands and sub-commands. Through this, you can +// propagate timeouts and cancellation requests +func (a *App) RunContext(ctx context.Context, arguments []string) (err error) { a.Setup() // handle the completion flag separately from the flagset since @@ -183,19 +225,17 @@ func (a *App) Run(arguments []string) (err error) { // 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) + set, err := a.newFlagSet() if err != nil { return err } - set.SetOutput(ioutil.Discard) - err = set.Parse(arguments[1:]) + err = parseIter(set, a, arguments[1:], shellComplete) nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, nil) + context := NewContext(a, set, &Context{Context: ctx}) if nerr != nil { - fmt.Fprintln(a.Writer, nerr) - ShowAppHelp(context) + _, _ = fmt.Fprintln(a.Writer, nerr) + _ = ShowAppHelp(context) return nerr } context.shellComplete = shellComplete @@ -207,16 +247,16 @@ func (a *App) Run(arguments []string) (err error) { if err != nil { if a.OnUsageError != nil { err := a.OnUsageError(context, err, false) - HandleExitCoder(err) + a.handleExitCoder(context, err) return err } - fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - ShowAppHelp(context) + _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) + _ = ShowAppHelp(context) return err } if !a.HideHelp && checkHelp(context) { - ShowAppHelp(context) + _ = ShowAppHelp(context) return nil } @@ -225,11 +265,17 @@ func (a *App) Run(arguments []string) (err error) { return nil } + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + _ = ShowAppHelp(context) + return cerr + } + if a.After != nil { defer func() { if afterErr := a.After(context); afterErr != nil { if err != nil { - err = NewMultiError(err, afterErr) + err = newMultiError(err, afterErr) } else { err = afterErr } @@ -240,8 +286,9 @@ func (a *App) Run(arguments []string) (err error) { if a.Before != nil { beforeErr := a.Before(context) if beforeErr != nil { - ShowAppHelp(context) - HandleExitCoder(beforeErr) + _, _ = fmt.Fprintf(a.Writer, "%v\n\n", beforeErr) + _ = ShowAppHelp(context) + a.handleExitCoder(context, beforeErr) err = beforeErr return err } @@ -261,9 +308,9 @@ func (a *App) Run(arguments []string) (err error) { } // Run default Action - err = HandleAction(a.Action, context) + err = a.Action(context) - HandleExitCoder(err) + a.handleExitCoder(context, err) return err } @@ -274,7 +321,7 @@ func (a *App) Run(arguments []string) (err error) { // code in the cli.ExitCoder func (a *App) RunAndExitOnError() { if err := a.Run(os.Args); err != nil { - fmt.Fprintln(a.errWriter(), err) + _, _ = fmt.Fprintln(a.errWriter(), err) OsExiter(1) } } @@ -282,17 +329,20 @@ func (a *App) RunAndExitOnError() { // RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to // generate command-specific flags func (a *App) RunAsSubcommand(ctx *Context) (err error) { + a.Setup() + // 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.appendCommand(helpCommand) + + if HelpFlag != nil { a.appendFlag(HelpFlag) } } } - newCmds := []Command{} + var newCmds []*Command for _, c := range a.Commands { if c.HelpName == "" { c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) @@ -301,24 +351,22 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } a.Commands = newCmds - // parse flags - set, err := flagSet(a.Name, a.Flags) + set, err := a.newFlagSet() if err != nil { return err } - set.SetOutput(ioutil.Discard) - err = set.Parse(ctx.Args().Tail()) + err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, ctx) if nerr != nil { - fmt.Fprintln(a.Writer, nerr) - fmt.Fprintln(a.Writer) + _, _ = fmt.Fprintln(a.Writer, nerr) + _, _ = fmt.Fprintln(a.Writer) if len(a.Commands) > 0 { - ShowSubcommandHelp(context) + _ = ShowSubcommandHelp(context) } else { - ShowCommandHelp(ctx, context.Args().First()) + _ = ShowCommandHelp(ctx, context.Args().First()) } return nerr } @@ -330,11 +378,11 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { if err != nil { if a.OnUsageError != nil { err = a.OnUsageError(context, err, true) - HandleExitCoder(err) + a.handleExitCoder(context, err) return err } - fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - ShowSubcommandHelp(context) + _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) + _ = ShowSubcommandHelp(context) return err } @@ -348,13 +396,19 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } } + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + _ = ShowSubcommandHelp(context) + return cerr + } + if a.After != nil { defer func() { afterErr := a.After(context) if afterErr != nil { - HandleExitCoder(err) + a.handleExitCoder(context, err) if err != nil { - err = NewMultiError(err, afterErr) + err = newMultiError(err, afterErr) } else { err = afterErr } @@ -365,7 +419,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { if a.Before != nil { beforeErr := a.Before(context) if beforeErr != nil { - HandleExitCoder(beforeErr) + a.handleExitCoder(context, beforeErr) err = beforeErr return err } @@ -381,9 +435,9 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } // Run default Action - err = HandleAction(a.Action, context) + err = a.Action(context) - HandleExitCoder(err) + a.handleExitCoder(context, err) return err } @@ -391,28 +445,21 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { func (a *App) Command(name string) *Command { for _, c := range a.Commands { if c.HasName(name) { - return &c + 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 - } +func (a *App) VisibleCategories() []CommandCategory { + ret := []CommandCategory{} + for _, category := range a.categories.Categories() { + if visible := func() CommandCategory { + if len(category.VisibleCommands()) > 0 { + return category } return nil }(); visible != nil { @@ -423,8 +470,8 @@ func (a *App) VisibleCategories() []*CommandCategory { } // VisibleCommands returns a slice of the Commands with Hidden=false -func (a *App) VisibleCommands() []Command { - ret := []Command{} +func (a *App) VisibleCommands() []*Command { + var ret []*Command for _, command := range a.Commands { if !command.Hidden { ret = append(ret, command) @@ -440,7 +487,7 @@ func (a *App) VisibleFlags() []Flag { func (a *App) hasFlag(flag Flag) bool { for _, f := range a.Flags { - if flag == f { + if reflect.DeepEqual(flag, f) { return true } } @@ -449,7 +496,6 @@ func (a *App) hasFlag(flag Flag) bool { } func (a *App) errWriter() io.Writer { - // When the app ErrWriter is nil use the package level one. if a.ErrWriter == nil { return ErrWriter @@ -458,9 +504,23 @@ func (a *App) errWriter() io.Writer { return a.ErrWriter } -func (a *App) appendFlag(flag Flag) { - if !a.hasFlag(flag) { - a.Flags = append(a.Flags, flag) +func (a *App) appendFlag(fl Flag) { + if !hasFlag(a.Flags, fl) { + a.Flags = append(a.Flags, fl) + } +} + +func (a *App) appendCommand(c *Command) { + if !hasCommand(a.Commands, c) { + a.Commands = append(a.Commands, c) + } +} + +func (a *App) handleExitCoder(context *Context, err error) { + if a.ExitErrHandler != nil { + a.ExitErrHandler(context, err) + } else { + HandleExitCoder(err) } } @@ -471,7 +531,7 @@ type Author struct { } // String makes Author comply to the Stringer interface, to allow an easy print in the templating process -func (a Author) String() string { +func (a *Author) String() string { e := "" if a.Email != "" { e = " <" + a.Email + ">" @@ -484,14 +544,15 @@ func (a Author) String() string { // 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 { + switch a := action.(type) { + case ActionFunc: return a(context) - } else if a, ok := action.(func(*Context) error); ok { + case func(*Context) error: return a(context) - } else if a, ok := action.(func(*Context)); ok { // deprecated function signature + case func(*Context): // deprecated function signature a(context) return nil - } else { - return errInvalidActionType } + + return errInvalidActionType } diff --git a/vendor/github.com/urfave/cli/v2/appveyor.yml b/vendor/github.com/urfave/cli/v2/appveyor.yml new file mode 100644 index 000000000..f1cae90b5 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/appveyor.yml @@ -0,0 +1,28 @@ +version: "{build}" + +os: Windows Server 2016 + +image: Visual Studio 2017 + +clone_folder: c:\gopath\src\github.com\urfave\cli + +cache: + - node_modules + +environment: + GOPATH: C:\gopath + GOVERSION: 1.11.x + GO111MODULE: on + GOPROXY: https://proxy.golang.org + +install: + - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% + - go version + - go env + - go get github.com/urfave/gfmrun/cmd/gfmrun + - go mod tidy + +build_script: + - go run build.go vet + - go run build.go test + - go run build.go gfmrun docs/v1/manual.md diff --git a/vendor/github.com/urfave/cli/v2/args.go b/vendor/github.com/urfave/cli/v2/args.go new file mode 100644 index 000000000..bd65c17bd --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/args.go @@ -0,0 +1,54 @@ +package cli + +type Args interface { + // Get returns the nth argument, or else a blank string + Get(n int) string + // First returns the first argument, or else a blank string + First() string + // Tail returns the rest of the arguments (not the first one) + // or else an empty string slice + Tail() []string + // Len returns the length of the wrapped slice + Len() int + // Present checks if there are any arguments present + Present() bool + // Slice returns a copy of the internal slice + Slice() []string +} + +type args []string + +func (a *args) Get(n int) string { + if len(*a) > n { + return (*a)[n] + } + return "" +} + +func (a *args) First() string { + return a.Get(0) +} + +func (a *args) Tail() []string { + if a.Len() >= 2 { + tail := []string((*a)[1:]) + ret := make([]string, len(tail)) + copy(ret, tail) + return ret + } + return []string{} +} + +func (a *args) Len() int { + return len(*a) +} + +func (a *args) Present() bool { + return a.Len() != 0 +} + +func (a *args) Slice() []string { + ret := make([]string, len(*a)) + copy(ret, *a) + return ret +} diff --git a/vendor/github.com/urfave/cli/v2/category.go b/vendor/github.com/urfave/cli/v2/category.go new file mode 100644 index 000000000..867e3908c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/category.go @@ -0,0 +1,79 @@ +package cli + +// CommandCategories interface allows for category manipulation +type CommandCategories interface { + // AddCommand adds a command to a category, creating a new category if necessary. + AddCommand(category string, command *Command) + // categories returns a copy of the category slice + Categories() []CommandCategory +} + +type commandCategories []*commandCategory + +func newCommandCategories() CommandCategories { + ret := commandCategories([]*commandCategory{}) + return &ret +} + +func (c *commandCategories) Less(i, j int) bool { + return lexicographicLess((*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] +} + +func (c *commandCategories) AddCommand(category string, command *Command) { + for _, commandCategory := range []*commandCategory(*c) { + if commandCategory.name == category { + commandCategory.commands = append(commandCategory.commands, command) + return + } + } + newVal := append(*c, + &commandCategory{name: category, commands: []*Command{command}}) + *c = newVal +} + +func (c *commandCategories) Categories() []CommandCategory { + ret := make([]CommandCategory, len(*c)) + for i, cat := range *c { + ret[i] = cat + } + return ret +} + +// CommandCategory is a category containing commands. +type CommandCategory interface { + // Name returns the category name string + Name() string + // VisibleCommands returns a slice of the Commands with Hidden=false + VisibleCommands() []*Command +} + +type commandCategory struct { + name string + commands []*Command +} + +func (c *commandCategory) Name() string { + return c.name +} + +func (c *commandCategory) VisibleCommands() []*Command { + if c.commands == nil { + c.commands = []*Command{} + } + + var ret []*Command + for _, command := range c.commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} diff --git a/vendor/github.com/urfave/cli/cli.go b/vendor/github.com/urfave/cli/v2/cli.go similarity index 56% rename from vendor/github.com/urfave/cli/cli.go rename to vendor/github.com/urfave/cli/v2/cli.go index 90c07eb8e..62a5bc22d 100644 --- a/vendor/github.com/urfave/cli/cli.go +++ b/vendor/github.com/urfave/cli/v2/cli.go @@ -2,21 +2,22 @@ // 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) +// (&cli.App{}).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 := &cli.App{ +// Name: "greet", +// Usage: "say a greeting", +// Action: func(c *cli.Context) error { +// fmt.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 +//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go diff --git a/vendor/github.com/urfave/cli/command.go b/vendor/github.com/urfave/cli/v2/command.go similarity index 57% rename from vendor/github.com/urfave/cli/command.go rename to vendor/github.com/urfave/cli/v2/command.go index 23de2944b..db6c8024b 100644 --- a/vendor/github.com/urfave/cli/command.go +++ b/vendor/github.com/urfave/cli/v2/command.go @@ -1,8 +1,8 @@ package cli import ( + "flag" "fmt" - "io/ioutil" "sort" "strings" ) @@ -11,8 +11,6 @@ import ( 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 @@ -34,27 +32,23 @@ type Command struct { // 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? - + Action ActionFunc // Execute this function if a usage error occurs. OnUsageError OnUsageErrorFunc // List of child commands - Subcommands Commands + Subcommands []*Command // 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 + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool // Full name of command for help, defaults to full command name, including parent commands. HelpName string @@ -66,14 +60,16 @@ type Command struct { CustomHelpTemplate string } -type CommandsByName []Command +type Commands []*Command + +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 + return lexicographicLess(c[i].Name, c[j].Name) } func (c CommandsByName) Swap(i, j int) { @@ -82,81 +78,29 @@ func (c CommandsByName) Swap(i, j int) { // 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 { +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) { +func (c *Command) Run(ctx *Context) (err error) { if len(c.Subcommands) > 0 { return c.startApp(ctx) } - if !c.HideHelp && (HelpFlag != BoolFlag{}) { + if !c.HideHelp && HelpFlag != nil { // append help to flags - c.Flags = append( - c.Flags, - HelpFlag, - ) + c.appendFlag(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()) + if ctx.App.UseShortOptionHandling { + c.UseShortOptionHandling = true } - 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 - } + set, err := c.parseFlags(ctx.Args(), ctx.shellComplete) context := NewContext(ctx.App, set, ctx) context.Command = c @@ -166,13 +110,13 @@ func (c Command) Run(ctx *Context) (err error) { if err != nil { if c.OnUsageError != nil { - err := c.OnUsageError(context, err, false) - HandleExitCoder(err) + err = c.OnUsageError(context, err, false) + context.App.handleExitCoder(context, err) return err } - fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) - fmt.Fprintln(context.App.Writer) - ShowCommandHelp(context, c.Name) + _, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) + _, _ = fmt.Fprintln(context.App.Writer) + _ = ShowCommandHelp(context, c.Name) return err } @@ -180,13 +124,19 @@ func (c Command) Run(ctx *Context) (err error) { return nil } + cerr := checkRequiredFlags(c.Flags, context) + if cerr != nil { + _ = ShowCommandHelp(context, c.Name) + return cerr + } + if c.After != nil { defer func() { afterErr := c.After(context) if afterErr != nil { - HandleExitCoder(err) + context.App.handleExitCoder(context, err) if err != nil { - err = NewMultiError(err, afterErr) + err = newMultiError(err, afterErr) } else { err = afterErr } @@ -197,8 +147,8 @@ func (c Command) Run(ctx *Context) (err error) { if c.Before != nil { err = c.Before(context) if err != nil { - ShowCommandHelp(context, c.Name) - HandleExitCoder(err) + _ = ShowCommandHelp(context, c.Name) + context.App.handleExitCoder(context, err) return err } } @@ -207,27 +157,53 @@ func (c Command) Run(ctx *Context) (err error) { c.Action = helpSubcommand.Action } - err = HandleAction(c.Action, context) + context.Command = c + err = c.Action(context) if err != nil { - HandleExitCoder(err) + context.App.handleExitCoder(context, 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...) +func (c *Command) newFlagSet() (*flag.FlagSet, error) { + return flagSet(c.Name, c.Flags) } -// HasName returns true if Command.Name or Command.ShortName matches given name -func (c Command) HasName(name string) bool { +func (c *Command) useShortOptionHandling() bool { + return c.UseShortOptionHandling +} + +func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { + set, err := c.newFlagSet() + if err != nil { + return nil, err + } + + if c.SkipFlagParsing { + return set, set.Parse(append([]string{"--"}, args.Tail()...)) + } + + err = parseIter(set, c, args.Tail(), shellComplete) + if err != nil { + return nil, err + } + + err = normalizeFlags(c.Flags, set) + if err != nil { + return nil, err + } + + return set, nil +} + +// Names returns the names including short names and aliases. +func (c *Command) Names() []string { + return append([]string{c.Name}, c.Aliases...) +} + +// HasName returns true if Command.Name matches given name +func (c *Command) HasName(name string) bool { for _, n := range c.Names() { if n == name { return true @@ -236,11 +212,12 @@ func (c Command) HasName(name string) bool { 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) +func (c *Command) startApp(ctx *Context) error { + app := &App{ + Metadata: ctx.App.Metadata, + Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name), + } + if c.HelpName == "" { app.HelpName = c.HelpName } else { @@ -263,17 +240,17 @@ func (c Command) startApp(ctx *Context) error { 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.ExitErrHandler = ctx.App.ExitErrHandler + app.UseShortOptionHandling = ctx.App.UseShortOptionHandling - app.categories = CommandCategories{} + app.categories = newCommandCategories() for _, command := range c.Subcommands { - app.categories = app.categories.AddCommand(command.Category, command) + app.categories.AddCommand(command.Category, command) } - sort.Sort(app.categories) + sort.Sort(app.categories.(*commandCategories)) // bash completion app.EnableBashCompletion = ctx.App.EnableBashCompletion @@ -299,6 +276,22 @@ func (c Command) startApp(ctx *Context) error { } // VisibleFlags returns a slice of the Flags with Hidden=false -func (c Command) VisibleFlags() []Flag { +func (c *Command) VisibleFlags() []Flag { return visibleFlags(c.Flags) } + +func (c *Command) appendFlag(fl Flag) { + if !hasFlag(c.Flags, fl) { + c.Flags = append(c.Flags, fl) + } +} + +func hasCommand(commands []*Command, command *Command) bool { + for _, existing := range commands { + if command == existing { + return true + } + } + + return false +} diff --git a/vendor/github.com/urfave/cli/v2/context.go b/vendor/github.com/urfave/cli/v2/context.go new file mode 100644 index 000000000..c0c526f41 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/context.go @@ -0,0 +1,274 @@ +package cli + +import ( + "context" + "errors" + "flag" + "fmt" + "strings" +) + +// 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 { + context.Context + App *App + Command *Command + shellComplete bool + setFlags map[string]bool + flagSet *flag.FlagSet + 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.Context = parentCtx.Context + c.shellComplete = parentCtx.shellComplete + if parentCtx.flagSet == nil { + parentCtx.flagSet = &flag.FlagSet{} + } + } + + c.Command = &Command{} + + if c.Context == nil { + c.Context = context.Background() + } + + 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 { + return c.flagSet.Set(name, value) +} + +// IsSet determines if the flag was actually set +func (c *Context) IsSet(name string) bool { + if fs := lookupFlagSet(name, c); fs != nil { + if fs := lookupFlagSet(name, c); fs != nil { + isSet := false + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + isSet = true + } + }) + if isSet { + return true + } + } + + f := lookupFlag(name, c) + if f == nil { + return false + } + + return f.IsSet() + } + + return false +} + +// LocalFlagNames returns a slice of flag names used in this context. +func (c *Context) LocalFlagNames() []string { + var names []string + c.flagSet.Visit(makeFlagNameVisitor(&names)) + return names +} + +// FlagNames returns a slice of flag names used by the this context and all of +// its parent contexts. +func (c *Context) FlagNames() []string { + var names []string + for _, ctx := range c.Lineage() { + ctx.flagSet.Visit(makeFlagNameVisitor(&names)) + } + return names +} + +// Lineage returns *this* context and all of its ancestor contexts in order from +// child to parent +func (c *Context) Lineage() []*Context { + var lineage []*Context + + for cur := c; cur != nil; cur = cur.parentContext { + lineage = append(lineage, cur) + } + + return lineage +} + +// Value returns the value of the flag corresponding to `name` +func (c *Context) Value(name string) interface{} { + return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +} + +// Args returns the command line arguments associated with the context. +func (c *Context) Args() Args { + ret := args(c.flagSet.Args()) + return &ret +} + +// NArg returns the number of the command line arguments. +func (c *Context) NArg() int { + return c.Args().Len() +} + +func lookupFlag(name string, ctx *Context) Flag { + for _, c := range ctx.Lineage() { + if c.Command == nil { + continue + } + + for _, f := range c.Command.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + if ctx.App != nil { + for _, f := range ctx.App.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + return nil +} + +func lookupFlagSet(name string, ctx *Context) *flag.FlagSet { + for _, c := range ctx.Lineage() { + if f := c.flagSet.Lookup(name); f != nil { + return c.flagSet + } + } + + return nil +} + +func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { + switch ff.Value.(type) { + case Serializer: + _ = set.Set(name, ff.Value.(Serializer).Serialize()) + 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 := f.Names() + 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 +} + +func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { + return func(f *flag.Flag) { + nameParts := strings.Split(f.Name, ",") + name := strings.TrimSpace(nameParts[0]) + + for _, part := range nameParts { + part = strings.TrimSpace(part) + if len(part) > len(name) { + name = part + } + } + + if name != "" { + *names = append(*names, name) + } + } +} + +type requiredFlagsErr interface { + error + getMissingFlags() []string +} + +type errRequiredFlags struct { + missingFlags []string +} + +func (e *errRequiredFlags) Error() string { + numberOfMissingFlags := len(e.missingFlags) + if numberOfMissingFlags == 1 { + return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) + } + joinedMissingFlags := strings.Join(e.missingFlags, ", ") + return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) +} + +func (e *errRequiredFlags) getMissingFlags() []string { + return e.missingFlags +} + +func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr { + var missingFlags []string + for _, f := range flags { + if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { + var flagPresent bool + var flagName string + + for _, key := range f.Names() { + if len(key) > 1 { + flagName = key + } + + if context.IsSet(strings.TrimSpace(key)) { + flagPresent = true + } + } + + if !flagPresent && flagName != "" { + missingFlags = append(missingFlags, flagName) + } + } + } + + if len(missingFlags) != 0 { + return &errRequiredFlags{missingFlags: missingFlags} + } + + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/docs.go b/vendor/github.com/urfave/cli/v2/docs.go new file mode 100644 index 000000000..dc16fc82d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/docs.go @@ -0,0 +1,148 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "sort" + "strings" + "text/template" + + "github.com/cpuguy83/go-md2man/v2/md2man" +) + +// ToMarkdown creates a markdown string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMarkdown() (string, error) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +// ToMan creates a man page string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMan() (string, error) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + man := md2man.Render(w.Bytes()) + return string(man), nil +} + +type cliTemplate struct { + App *App + Commands []string + GlobalArgs []string + SynopsisArgs []string +} + +func (a *App) writeDocTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(MarkdownDocTemplate) + if err != nil { + return err + } + return t.ExecuteTemplate(w, name, &cliTemplate{ + App: a, + Commands: prepareCommands(a.Commands, 0), + GlobalArgs: prepareArgsWithValues(a.VisibleFlags()), + SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()), + }) +} + +func prepareCommands(commands []*Command, level int) []string { + var coms []string + for _, command := range commands { + if command.Hidden { + continue + } + usage := "" + if command.Usage != "" { + usage = command.Usage + } + + prepared := fmt.Sprintf("%s %s\n\n%s\n", + strings.Repeat("#", level+2), + strings.Join(command.Names(), ", "), + usage, + ) + + flags := prepareArgsWithValues(command.Flags) + if len(flags) > 0 { + prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n")) + } + + coms = append(coms, prepared) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + coms = append( + coms, + prepareCommands(command.Subcommands, level+1)..., + ) + } + } + + return coms +} + +func prepareArgsWithValues(flags []Flag) []string { + return prepareFlags(flags, ", ", "**", "**", `""`, true) +} + +func prepareArgsSynopsis(flags []Flag) []string { + return prepareFlags(flags, "|", "[", "]", "[value]", false) +} + +func prepareFlags( + flags []Flag, + sep, opener, closer, value string, + addDetails bool, +) []string { + args := []string{} + for _, f := range flags { + flag, ok := f.(DocGenerationFlag) + if !ok { + continue + } + modifiedArg := opener + + for _, s := range flag.Names() { + trimmed := strings.TrimSpace(s) + if len(modifiedArg) > len(opener) { + modifiedArg += sep + } + if len(trimmed) > 1 { + modifiedArg += fmt.Sprintf("--%s", trimmed) + } else { + modifiedArg += fmt.Sprintf("-%s", trimmed) + } + } + modifiedArg += closer + if flag.TakesValue() { + modifiedArg += fmt.Sprintf("=%s", value) + } + + if addDetails { + modifiedArg += flagDetails(flag) + } + + args = append(args, modifiedArg+"\n") + + } + sort.Strings(args) + return args +} + +// flagDetails returns a string containing the flags metadata +func flagDetails(flag DocGenerationFlag) string { + description := flag.GetUsage() + value := flag.GetValue() + if value != "" { + description += " (default: " + value + ")" + } + return ": " + description +} diff --git a/vendor/github.com/urfave/cli/errors.go b/vendor/github.com/urfave/cli/v2/errors.go similarity index 62% rename from vendor/github.com/urfave/cli/errors.go rename to vendor/github.com/urfave/cli/v2/errors.go index 562b2953c..344b4361e 100644 --- a/vendor/github.com/urfave/cli/errors.go +++ b/vendor/github.com/urfave/cli/v2/errors.go @@ -15,25 +15,40 @@ var OsExiter = os.Exit var ErrWriter io.Writer = os.Stderr // MultiError is an error that wraps multiple errors. -type MultiError struct { - Errors []error +type MultiError interface { + error + // Errors returns a copy of the errors slice + Errors() []error } // NewMultiError creates a new MultiError. Pass in one or more errors. -func NewMultiError(err ...error) MultiError { - return MultiError{Errors: err} +func newMultiError(err ...error) MultiError { + ret := multiError(err) + return &ret } +type multiError []error + // Error implements the error interface. -func (m MultiError) Error() string { - errs := make([]string, len(m.Errors)) - for i, err := range m.Errors { +func (m *multiError) Error() string { + errs := make([]string, len(*m)) + for i, err := range *m { errs[i] = err.Error() } return strings.Join(errs, "\n") } +// Errors returns a copy of the errors slice +func (m *multiError) Errors() []error { + errs := make([]error, len(*m)) + for _, err := range *m { + errs = append(errs, err) + } + return errs +} + +// ErrorFormatter is the interface that will suitably format the error output type ErrorFormatter interface { Format(s fmt.State, verb rune) } @@ -45,29 +60,30 @@ type ExitCoder interface { ExitCode() int } -// ExitError fulfills both the builtin `error` interface and `ExitCoder` -type ExitError struct { +type exitError struct { exitCode int message interface{} } -// NewExitError makes a new *ExitError -func NewExitError(message interface{}, exitCode int) *ExitError { - return &ExitError{ - exitCode: exitCode, +// NewExitError makes a new *exitError +func NewExitError(message interface{}, exitCode int) ExitCoder { + return Exit(message, exitCode) +} + +// Exit wraps a message and exit code into an ExitCoder suitable for handling by +// HandleExitCoder +func Exit(message interface{}, exitCode int) ExitCoder { + return &exitError{ message: message, + exitCode: exitCode, } } -// Error returns the string message, fulfilling the interface required by -// `error` -func (ee *ExitError) Error() string { +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 { +func (ee *exitError) ExitCode() int { return ee.exitCode } @@ -83,9 +99,9 @@ func HandleExitCoder(err error) { if exitErr, ok := err.(ExitCoder); ok { if err.Error() != "" { if _, ok := exitErr.(ErrorFormatter); ok { - fmt.Fprintf(ErrWriter, "%+v\n", err) + _, _ = fmt.Fprintf(ErrWriter, "%+v\n", err) } else { - fmt.Fprintln(ErrWriter, err) + _, _ = fmt.Fprintln(ErrWriter, err) } } OsExiter(exitErr.ExitCode()) @@ -101,10 +117,10 @@ func HandleExitCoder(err error) { func handleMultiError(multiErr MultiError) int { code := 1 - for _, merr := range multiErr.Errors { + for _, merr := range multiErr.Errors() { if multiErr2, ok := merr.(MultiError); ok { code = handleMultiError(multiErr2) - } else { + } else if merr != nil { fmt.Fprintln(ErrWriter, merr) if exitErr, ok := merr.(ExitCoder); ok { code = exitErr.ExitCode() diff --git a/vendor/github.com/urfave/cli/v2/fish.go b/vendor/github.com/urfave/cli/v2/fish.go new file mode 100644 index 000000000..67122c9fe --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/fish.go @@ -0,0 +1,192 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "strings" + "text/template" +) + +// ToFishCompletion creates a fish completion string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToFishCompletion() (string, error) { + var w bytes.Buffer + if err := a.writeFishCompletionTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +type fishCompletionTemplate struct { + App *App + Completions []string + AllCommands []string +} + +func (a *App) writeFishCompletionTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(FishCompletionTemplate) + if err != nil { + return err + } + allCommands := []string{} + + // Add global flags + completions := a.prepareFishFlags(a.VisibleFlags(), allCommands) + + // Add help flag + if !a.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, allCommands)..., + ) + } + + // Add version flag + if !a.HideVersion { + completions = append( + completions, + a.prepareFishFlags([]Flag{VersionFlag}, allCommands)..., + ) + } + + // Add commands and their flags + completions = append( + completions, + a.prepareFishCommands(a.VisibleCommands(), &allCommands, []string{})..., + ) + + return t.ExecuteTemplate(w, name, &fishCompletionTemplate{ + App: a, + Completions: completions, + AllCommands: allCommands, + }) +} + +func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, previousCommands []string) []string { + completions := []string{} + for _, command := range commands { + if command.Hidden { + continue + } + + var completion strings.Builder + completion.WriteString(fmt.Sprintf( + "complete -r -c %s -n '%s' -a '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + strings.Join(command.Names(), " "), + )) + + if command.Usage != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(command.Usage))) + } + + if !command.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, command.Names())..., + ) + } + + *allCommands = append(*allCommands, command.Names()...) + completions = append(completions, completion.String()) + completions = append( + completions, + a.prepareFishFlags(command.Flags, command.Names())..., + ) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + completions = append( + completions, + a.prepareFishCommands( + command.Subcommands, allCommands, command.Names(), + )..., + ) + } + } + + return completions +} + +func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string { + completions := []string{} + for _, f := range flags { + flag, ok := f.(DocGenerationFlag) + if !ok { + continue + } + + completion := &strings.Builder{} + completion.WriteString(fmt.Sprintf( + "complete -c %s -n '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + )) + + fishAddFileFlag(f, completion) + + for idx, opt := range flag.Names() { + if idx == 0 { + completion.WriteString(fmt.Sprintf( + " -l %s", strings.TrimSpace(opt), + )) + } else { + completion.WriteString(fmt.Sprintf( + " -s %s", strings.TrimSpace(opt), + )) + + } + } + + if flag.TakesValue() { + completion.WriteString(" -r") + } + + if flag.GetUsage() != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(flag.GetUsage()))) + } + + completions = append(completions, completion.String()) + } + + return completions +} + +func fishAddFileFlag(flag Flag, completion *strings.Builder) { + switch f := flag.(type) { + case *GenericFlag: + if f.TakesFile { + return + } + case *StringFlag: + if f.TakesFile { + return + } + case *StringSliceFlag: + if f.TakesFile { + return + } + } + completion.WriteString(" -f") +} + +func (a *App) fishSubcommandHelper(allCommands []string) string { + fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", a.Name) + if len(allCommands) > 0 { + fishHelper = fmt.Sprintf( + "__fish_seen_subcommand_from %s", + strings.Join(allCommands, " "), + ) + } + return fishHelper + +} + +func escapeSingleQuotes(input string) string { + return strings.Replace(input, `'`, `\'`, -1) +} diff --git a/vendor/github.com/urfave/cli/v2/flag.go b/vendor/github.com/urfave/cli/v2/flag.go new file mode 100644 index 000000000..ec128fd44 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag.go @@ -0,0 +1,398 @@ +package cli + +import ( + "flag" + "fmt" + "io/ioutil" + "reflect" + "regexp" + "runtime" + "strconv" + "strings" + "syscall" + "time" +) + +const defaultPlaceholder = "value" + +var ( + slPfx = fmt.Sprintf("sl:::%d:::", time.Now().UTC().UnixNano()) + + commaWhitespace = regexp.MustCompile("[, ]+.*") +) + +// 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", + Aliases: []string{"v"}, + Usage: "print the version", +} + +// HelpFlag prints the help for all commands and subcommands. +// Set to nil to disable the flag. The subcommand +// will still be added unless HideHelp is set to true. +var HelpFlag Flag = &BoolFlag{ + Name: "help", + Aliases: []string{"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 + +// Serializer is used to circumvent the limitations of flag.FlagSet.Set +type Serializer interface { + Serialize() string +} + +// FlagNamePrefixer converts a full flag name and its placeholder into the help +// message flag prefix. This is used by the default FlagStringer. +var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames + +// FlagEnvHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagEnvHinter FlagEnvHintFunc = withEnvHint + +// FlagFileHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagFileHinter FlagFileHintFunc = withFileHint + +// 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 { + if len(f[j].Names()) == 0 { + return false + } else if len(f[i].Names()) == 0 { + return true + } + return lexicographicLess(f[i].Names()[0], f[j].Names()[0]) +} + +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) error + Names() []string + IsSet() bool +} + +// RequiredFlag is an interface that allows us to mark flags as required +// it allows flags required flags to be backwards compatible with the Flag interface +type RequiredFlag interface { + Flag + + IsRequired() bool +} + +// DocGenerationFlag is an interface that allows documentation generation for the flag +type DocGenerationFlag interface { + Flag + + // TakesValue returns true if the flag takes a value, otherwise false + TakesValue() bool + + // GetUsage returns the usage string for the flag + GetUsage() string + + // GetValue returns the flags value as string representation and an empty + // string if the flag takes no value at all. + GetValue() string +} + +func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { + set := flag.NewFlagSet(name, flag.ContinueOnError) + + for _, f := range flags { + if err := f.Apply(set); err != nil { + return nil, err + } + } + set.SetOutput(ioutil.Discard) + return set, nil +} + +func visibleFlags(fl []Flag) []Flag { + var visible []Flag + for _, f := range fl { + field := flagValue(f).FieldByName("Hidden") + if !field.IsValid() || !field.Bool() { + visible = append(visible, f) + } + } + 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(names []string, placeholder string) string { + var prefixed string + for i, name := range names { + if name == "" { + continue + } + + prefixed += prefixFor(name) + name + if placeholder != "" { + prefixed += " " + placeholder + } + if i < len(names)-1 { + prefixed += ", " + } + } + return prefixed +} + +func withEnvHint(envVars []string, str string) string { + envText := "" + if envVars != nil && len(envVars) > 0 { + prefix := "$" + suffix := "" + sep := ", $" + if runtime.GOOS == "windows" { + prefix = "%" + suffix = "%" + sep = "%, %" + } + + envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix) + } + return str + envText +} + +func flagNames(f Flag) []string { + var ret []string + + name := flagStringField(f, "Name") + aliases := flagStringSliceField(f, "Aliases") + + for _, part := range append([]string{name}, aliases...) { + // v1 -> v2 migration warning zone: + // Strip off anything after the first found comma or space, which + // *hopefully* makes it a tiny bit more obvious that unexpected behavior is + // caused by using the v1 form of stringly typed "Name". + ret = append(ret, commaWhitespace.ReplaceAllString(part, "")) + } + + return ret +} + +func flagStringSliceField(f Flag, name string) []string { + fv := flagValue(f) + field := fv.FieldByName(name) + + if field.IsValid() { + return field.Interface().([]string) + } + + return []string{} +} + +func flagStringField(f Flag, name string) string { + fv := flagValue(f) + field := fv.FieldByName(name) + + if field.IsValid() { + return field.String() + } + + return "" +} + +func withFileHint(filePath, str string) string { + fileText := "" + if filePath != "" { + fileText = fmt.Sprintf(" [%s]", filePath) + } + return str + fileText +} + +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(flagStringSliceField(f, "EnvVars"), + stringifyIntSliceFlag(f.(*IntSliceFlag))) + case *Int64SliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyInt64SliceFlag(f.(*Int64SliceFlag))) + case *Float64SliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyFloat64SliceFlag(f.(*Float64SliceFlag))) + case *StringSliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyStringSliceFlag(f.(*StringSliceFlag))) + } + + placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) + + needsPlaceholder := false + defaultValueString := "" + val := fv.FieldByName("Value") + if val.IsValid() { + needsPlaceholder = val.Kind() != reflect.Bool + defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface()) + + if val.Kind() == reflect.String && val.String() != "" { + defaultValueString = fmt.Sprintf(" (default: %q)", val.String()) + } + } + + helpText := fv.FieldByName("DefaultText") + if helpText.IsValid() && helpText.String() != "" { + needsPlaceholder = val.Kind() != reflect.Bool + defaultValueString = fmt.Sprintf(" (default: %s)", helpText.String()) + } + + if defaultValueString == " (default: )" { + defaultValueString = "" + } + + if needsPlaceholder && placeholder == "" { + placeholder = defaultPlaceholder + } + + usageWithDefault := strings.TrimSpace(usage + defaultValueString) + + return withEnvHint(flagStringSliceField(f, "EnvVars"), + fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault)) +} + +func stringifyIntSliceFlag(f *IntSliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.Itoa(i)) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyInt64SliceFlag(f *Int64SliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyFloat64SliceFlag(f *Float64SliceFlag) string { + var defaultVals []string + + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyStringSliceFlag(f *StringSliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, s := range f.Value.Value() { + if len(s) > 0 { + defaultVals = append(defaultVals, strconv.Quote(s)) + } + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifySliceFlag(usage string, names, 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(names, placeholder), usageWithDefault) +} + +func hasFlag(flags []Flag, fl Flag) bool { + for _, existing := range flags { + if fl == existing { + return true + } + } + + return false +} + +func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool) { + for _, envVar := range envVars { + envVar = strings.TrimSpace(envVar) + if val, ok := syscall.Getenv(envVar); ok { + return val, true + } + } + for _, fileVar := range strings.Split(filePath, ",") { + if data, err := ioutil.ReadFile(fileVar); err == nil { + return string(data), true + } + } + return "", false +} diff --git a/vendor/github.com/urfave/cli/v2/flag_bool.go b/vendor/github.com/urfave/cli/v2/flag_bool.go new file mode 100644 index 000000000..6a1da61ef --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_bool.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value bool + DefaultText string + Destination *bool + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *BoolFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *BoolFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *BoolFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *BoolFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *BoolFlag) TakesValue() bool { + return false +} + +// GetUsage returns the usage string for the flag +func (f *BoolFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *BoolFlag) GetValue() string { + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *BoolFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valBool, err := strconv.ParseBool(val) + + if err != nil { + return fmt.Errorf("could not parse %q as bool value for flag %s: %s", val, f.Name, err) + } + + f.Value = valBool + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.BoolVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Bool(name, f.Value, f.Usage) + } + + return nil +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (c *Context) Bool(name string) bool { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_duration.go b/vendor/github.com/urfave/cli/v2/flag_duration.go new file mode 100644 index 000000000..2c34944a4 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_duration.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) +type DurationFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value time.Duration + DefaultText string + Destination *time.Duration + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *DurationFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *DurationFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *DurationFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *DurationFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *DurationFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *DurationFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *DurationFlag) GetValue() string { + return f.Value.String() +} + +// Apply populates the flag given the flag set and environment +func (f *DurationFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valDuration, err := time.ParseDuration(val) + + if err != nil { + return fmt.Errorf("could not parse %q as duration value for flag %s: %s", val, f.Name, err) + } + + f.Value = valDuration + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.DurationVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Duration(name, f.Value, f.Usage) + } + return nil +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (c *Context) Duration(name string) time.Duration { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64.go b/vendor/github.com/urfave/cli/v2/flag_float64.go new file mode 100644 index 000000000..31f06f35e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value float64 + DefaultText string + Destination *float64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Float64Flag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64Flag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Float64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Float64Flag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Float64Flag) GetValue() string { + return fmt.Sprintf("%f", f.Value) +} + +// Apply populates the flag given the flag set and environment +func (f *Float64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valFloat, err := strconv.ParseFloat(val, 10) + + if err != nil { + return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", val, f.Name, err) + } + + f.Value = valFloat + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Float64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Float64(name, f.Value, f.Usage) + } + + return nil +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (c *Context) Float64(name string) float64 { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64_slice.go b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go new file mode 100644 index 000000000..91d2e9d10 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go @@ -0,0 +1,165 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Float64Slice wraps []float64 to satisfy flag.Value +type Float64Slice struct { + slice []float64 + hasBeenSet bool +} + +// NewFloat64Slice makes a *Float64Slice with default values +func NewFloat64Slice(defaults ...float64) *Float64Slice { + return &Float64Slice{slice: append([]float64{}, defaults...)} +} + +// Set parses the value into a float64 and appends it to the list of values +func (f *Float64Slice) Set(value string) error { + if !f.hasBeenSet { + f.slice = []float64{} + f.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &f.slice) + f.hasBeenSet = true + return nil + } + + tmp, err := strconv.ParseFloat(value, 64) + if err != nil { + return err + } + + f.slice = append(f.slice, tmp) + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Float64Slice) String() string { + return fmt.Sprintf("%#v", f.slice) +} + +// Serialize allows Float64Slice to fulfill Serializer +func (f *Float64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(f.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of float64s set by this flag +func (f *Float64Slice) Value() []float64 { + return f.slice +} + +// Get returns the slice of float64s set by this flag +func (f *Float64Slice) Get() interface{} { + return *f +} + +// Float64SliceFlag is a flag with type *Float64Slice +type Float64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *Float64Slice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64SliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Float64SliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64SliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true if the flag takes a value, otherwise false +func (f *Float64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Float64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Float64SliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + f.Value = &Float64Slice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as float64 slice value for flag %s: %s", f.Value, f.Name, err) + } + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &Float64Slice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Float64Slice looks up the value of a local Float64SliceFlag, returns +// nil if not found +func (c *Context) Float64Slice(name string) []float64 { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupFloat64Slice(name, fs) + } + return nil +} + +func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Float64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_generic.go b/vendor/github.com/urfave/cli/v2/flag_generic.go new file mode 100644 index 000000000..2d9baa78d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_generic.go @@ -0,0 +1,108 @@ +package cli + +import ( + "flag" + "fmt" +) + +// Generic is a generic parseable type identified by a specific flag +type Generic interface { + Set(value string) error + String() string +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value Generic + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *GenericFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *GenericFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *GenericFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *GenericFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *GenericFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *GenericFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *GenericFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply 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) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err) + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Generic looks up the value of a local GenericFlag, returns +// nil if not found +func (c *Context) Generic(name string) interface{} { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int.go b/vendor/github.com/urfave/cli/v2/flag_int.go new file mode 100644 index 000000000..be961bf5f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value int + DefaultText string + Destination *int + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *IntFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *IntFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *IntFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *IntFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *IntFlag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Apply populates the flag given the flag set and environment +func (f *IntFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err) + } + + f.Value = int(valInt) + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.IntVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Int(name, f.Value, f.Usage) + } + + return nil +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (c *Context) Int(name string) int { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int64.go b/vendor/github.com/urfave/cli/v2/flag_int64.go new file mode 100644 index 000000000..c979119f8 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value int64 + DefaultText string + Destination *int64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Int64Flag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64Flag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Int64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Int64Flag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Int64Flag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Apply populates the flag given the flag set and environment +func (f *Int64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err) + } + + f.Value = valInt + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Int64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Int64(name, f.Value, f.Usage) + } + return nil +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (c *Context) Int64(name string) int64 { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int64_slice.go b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go new file mode 100644 index 000000000..41aa0667e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go @@ -0,0 +1,161 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Int64Slice wraps []int64 to satisfy flag.Value +type Int64Slice struct { + slice []int64 + hasBeenSet bool +} + +// NewInt64Slice makes an *Int64Slice with default values +func NewInt64Slice(defaults ...int64) *Int64Slice { + return &Int64Slice{slice: append([]int64{}, defaults...)} +} + +// Set parses the value into an integer and appends it to the list of values +func (i *Int64Slice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []int64{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + tmp, err := strconv.ParseInt(value, 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, tmp) + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (i *Int64Slice) String() string { + return fmt.Sprintf("%#v", i.slice) +} + +// Serialize allows Int64Slice to fulfill Serializer +func (i *Int64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *Int64Slice) Value() []int64 { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *Int64Slice) Get() interface{} { + return *i +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *Int64Slice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64SliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Int64SliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64SliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Int64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f Int64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Int64SliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &Int64Slice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &Int64Slice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// 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) +} + +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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int_slice.go b/vendor/github.com/urfave/cli/v2/flag_int_slice.go new file mode 100644 index 000000000..938897842 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int_slice.go @@ -0,0 +1,175 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// IntSlice wraps []int to satisfy flag.Value +type IntSlice struct { + slice []int + hasBeenSet bool +} + +// NewIntSlice makes an *IntSlice with default values +func NewIntSlice(defaults ...int) *IntSlice { + return &IntSlice{slice: append([]int{}, defaults...)} +} + +// TODO: Consistently have specific Set function for Int64 and Float64 ? +// SetInt directly adds an integer to the list of values +func (i *IntSlice) SetInt(value int) { + if !i.hasBeenSet { + i.slice = []int{} + i.hasBeenSet = true + } + + i.slice = append(i.slice, value) +} + +// Set parses the value into an integer and appends it to the list of values +func (i *IntSlice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []int{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + tmp, err := strconv.ParseInt(value, 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, int(tmp)) + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (i *IntSlice) String() string { + return fmt.Sprintf("%#v", i.slice) +} + +// Serialize allows IntSlice to fulfill Serializer +func (i *IntSlice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *IntSlice) Value() []int { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *IntSlice) Get() interface{} { + return *i +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *IntSlice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntSliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *IntSliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *IntSliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *IntSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f IntSliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *IntSliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &IntSlice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &IntSlice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// nil if not found +func (c *Context) IntSlice(name string) []int { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupIntSlice(name, c.flagSet) + } + 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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_path.go b/vendor/github.com/urfave/cli/v2/flag_path.go new file mode 100644 index 000000000..a32285739 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_path.go @@ -0,0 +1,95 @@ +package cli + +import "flag" + +type PathFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value string + DefaultText string + Destination *string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *PathFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *PathFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *PathFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *PathFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *PathFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *PathFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *PathFlag) GetValue() string { + return f.Value +} + +// Apply populates the flag given the flag set and environment +func (f *PathFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = val + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.StringVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.String(name, f.Value, f.Usage) + } + + return nil +} + +// Path looks up the value of a local PathFlag, returns +// "" if not found +func (c *Context) Path(name string) string { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupPath(name, fs) + } + + return "" +} + +func lookupPath(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 "" +} diff --git a/vendor/github.com/urfave/cli/v2/flag_string.go b/vendor/github.com/urfave/cli/v2/flag_string.go new file mode 100644 index 000000000..bcd82530c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string.go @@ -0,0 +1,95 @@ +package cli + +import "flag" + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value string + DefaultText string + Destination *string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *StringFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *StringFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *StringFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *StringFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *StringFlag) GetValue() string { + return f.Value +} + +// Apply populates the flag given the flag set and environment +func (f *StringFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = val + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.StringVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.String(name, f.Value, f.Usage) + } + + return nil +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (c *Context) String(name string) string { + if fs := lookupFlagSet(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 "" +} diff --git a/vendor/github.com/urfave/cli/v2/flag_string_slice.go b/vendor/github.com/urfave/cli/v2/flag_string_slice.go new file mode 100644 index 000000000..a114a495e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string_slice.go @@ -0,0 +1,159 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strings" +) + +// StringSlice wraps a []string to satisfy flag.Value +type StringSlice struct { + slice []string + hasBeenSet bool +} + +// NewStringSlice creates a *StringSlice with default values +func NewStringSlice(defaults ...string) *StringSlice { + return &StringSlice{slice: append([]string{}, defaults...)} +} + +// Set appends the string value to the list of values +func (s *StringSlice) Set(value string) error { + if !s.hasBeenSet { + s.slice = []string{} + s.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &s.slice) + s.hasBeenSet = true + return nil + } + + s.slice = append(s.slice, value) + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (s *StringSlice) String() string { + return fmt.Sprintf("%s", s.slice) +} + +// Serialize allows StringSlice to fulfill Serializer +func (s *StringSlice) Serialize() string { + jsonBytes, _ := json.Marshal(s.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of strings set by this flag +func (s *StringSlice) Value() []string { + return s.slice +} + +// Get returns the slice of strings set by this flag +func (s *StringSlice) Get() interface{} { + return *s +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value *StringSlice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringSliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *StringSliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *StringSliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *StringSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *StringSliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *StringSliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &StringSlice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &StringSlice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// nil if not found +func (c *Context) StringSlice(name string) []string { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_timestamp.go b/vendor/github.com/urfave/cli/v2/flag_timestamp.go new file mode 100644 index 000000000..d24edcd7f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_timestamp.go @@ -0,0 +1,152 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// Timestamp wrap to satisfy golang's flag interface. +type Timestamp struct { + timestamp *time.Time + hasBeenSet bool + layout string +} + +// Timestamp constructor +func NewTimestamp(timestamp time.Time) *Timestamp { + return &Timestamp{timestamp: ×tamp} +} + +// Set the timestamp value directly +func (t *Timestamp) SetTimestamp(value time.Time) { + if !t.hasBeenSet { + t.timestamp = &value + t.hasBeenSet = true + } +} + +// Set the timestamp string layout for future parsing +func (t *Timestamp) SetLayout(layout string) { + t.layout = layout +} + +// Parses the string value to timestamp +func (t *Timestamp) Set(value string) error { + timestamp, err := time.Parse(t.layout, value) + if err != nil { + return err + } + + t.timestamp = ×tamp + t.hasBeenSet = true + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (t *Timestamp) String() string { + return fmt.Sprintf("%#v", t.timestamp) +} + +// Value returns the timestamp value stored in the flag +func (t *Timestamp) Value() *time.Time { + return t.timestamp +} + +// Get returns the flag structure +func (t *Timestamp) Get() interface{} { + return *t +} + +// TimestampFlag is a flag with type time +type TimestampFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Layout string + Value *Timestamp + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *TimestampFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *TimestampFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *TimestampFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *TimestampFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *TimestampFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *TimestampFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *TimestampFlag) GetValue() string { + if f.Value != nil { + return f.Value.timestamp.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *TimestampFlag) Apply(set *flag.FlagSet) error { + if f.Layout == "" { + return fmt.Errorf("timestamp Layout is required") + } + f.Value = &Timestamp{} + f.Value.SetLayout(f.Layout) + + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err) + } + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(f.Value, name, f.Usage) + } + return nil +} + +// Timestamp gets the timestamp from a flag name +func (c *Context) Timestamp(name string) *time.Time { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupTimestamp(name, fs) + } + return nil +} + +// Fetches the timestamp value from the local timestampWrap +func lookupTimestamp(name string, set *flag.FlagSet) *time.Time { + f := set.Lookup(name) + if f != nil { + return (f.Value.(*Timestamp)).Value() + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint.go b/vendor/github.com/urfave/cli/v2/flag_uint.go new file mode 100644 index 000000000..9f592388f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value uint + DefaultText string + Destination *uint + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *UintFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *UintFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *UintFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *UintFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *UintFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *UintFlag) GetUsage() string { + return f.Usage +} + +// Apply populates the flag given the flag set and environment +func (f *UintFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint value for flag %s: %s", val, f.Name, err) + } + + f.Value = uint(valInt) + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.UintVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Uint(name, f.Value, f.Usage) + } + + return nil +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *UintFlag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (c *Context) Uint(name string) uint { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint64.go b/vendor/github.com/urfave/cli/v2/flag_uint64.go new file mode 100644 index 000000000..5bbd1fa4b --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint64.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value uint64 + DefaultText string + Destination *uint64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Uint64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Uint64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Uint64Flag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Uint64Flag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Uint64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Uint64Flag) GetUsage() string { + return f.Usage +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", val, f.Name, err) + } + + f.Value = valInt + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Uint64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Uint64(name, f.Value, f.Usage) + } + + return nil +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Uint64Flag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (c *Context) Uint64(name string) uint64 { + if fs := lookupFlagSet(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 +} diff --git a/vendor/github.com/urfave/cli/funcs.go b/vendor/github.com/urfave/cli/v2/funcs.go similarity index 59% rename from vendor/github.com/urfave/cli/funcs.go rename to vendor/github.com/urfave/cli/v2/funcs.go index cba5e6cb0..474c48faf 100644 --- a/vendor/github.com/urfave/cli/funcs.go +++ b/vendor/github.com/urfave/cli/v2/funcs.go @@ -1,6 +1,6 @@ package cli -// BashCompleteFunc is an action to execute when the bash-completion flag is set +// BashCompleteFunc is an action to execute when the shell completion flag is set type BashCompleteFunc func(*Context) // BeforeFunc is an action to execute before any subcommands are run, but after @@ -23,6 +23,22 @@ type CommandNotFoundFunc func(*Context, string) // is displayed and the execution is interrupted. type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error +// ExitErrHandlerFunc is executed if provided in order to handle exitError values +// returned by Actions and Before/After functions. +type ExitErrHandlerFunc func(context *Context, err 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 + +// FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix +// text for a flag's full name. +type FlagNamePrefixFunc func(fullName []string, placeholder string) string + +// FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help +// with the environment variable details. +type FlagEnvHintFunc func(envVars []string, str string) string + +// FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help +// with the file path details. +type FlagFileHintFunc func(filePath, str string) string diff --git a/vendor/github.com/urfave/cli/v2/go.mod b/vendor/github.com/urfave/cli/v2/go.mod new file mode 100644 index 000000000..c38d41c14 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/go.mod @@ -0,0 +1,9 @@ +module github.com/urfave/cli/v2 + +go 1.11 + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/vendor/github.com/urfave/cli/v2/go.sum b/vendor/github.com/urfave/cli/v2/go.sum new file mode 100644 index 000000000..ef121ff5d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/go.sum @@ -0,0 +1,14 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +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/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/urfave/cli/help.go b/vendor/github.com/urfave/cli/v2/help.go similarity index 50% rename from vendor/github.com/urfave/cli/help.go rename to vendor/github.com/urfave/cli/v2/help.go index 57ec98d58..c1e974a48 100644 --- a/vendor/github.com/urfave/cli/help.go +++ b/vendor/github.com/urfave/cli/v2/help.go @@ -7,78 +7,10 @@ import ( "strings" "text/tabwriter" "text/template" + "unicode/utf8" ) -// 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{ +var helpCommand = &Command{ Name: "help", Aliases: []string{"h"}, Usage: "Shows a list of commands or help for one command", @@ -89,12 +21,12 @@ var helpCommand = Command{ return ShowCommandHelp(c, args.First()) } - ShowAppHelp(c) + _ = ShowAppHelp(c) return nil }, } -var helpSubcommand = Command{ +var helpSubcommand = &Command{ Name: "help", Aliases: []string{"h"}, Usage: "Shows a list of commands or help for one command", @@ -115,13 +47,18 @@ 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{}) +// HelpPrinter is a function that writes the help output. If not set explicitly, +// this calls HelpPrinterCustom using only the default template functions. +// +// If custom logic for printing help is required, this function can be +// overridden. If the ExtraInfo field is defined on an App, this function +// should not be modified, as HelpPrinterCustom will be used directly in order +// to capture the extra information. var HelpPrinter helpPrinter = printHelp -// HelpPrinterCustom is same as HelpPrinter but -// takes a custom function for template function map. +// HelpPrinterCustom is a function that writes the help output. It is used as +// the default implementation of HelpPrinter, and may be called directly if +// the ExtraInfo field is set on an App. var HelpPrinterCustom helpPrinterCustom = printHelpCustom // VersionPrinter prints the version for the App @@ -129,43 +66,122 @@ 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) + _ = 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 +func ShowAppHelp(c *Context) error { + template := c.App.CustomAppHelpTemplate + if template == "" { + template = AppHelpTemplate } + + if c.App.ExtraInfo == nil { + HelpPrinter(c.App.Writer, template, c.App) + return nil + } + 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()) + HelpPrinterCustom(c.App.Writer, template, 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 { + DefaultCompleteWithFlags(nil)(c) +} + +func printCommandSuggestions(commands []*Command, writer io.Writer) { + for _, command := range commands { if command.Hidden { continue } - for _, name := range command.Names() { - fmt.Fprintln(c.App.Writer, name) + if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + for _, name := range command.Names() { + _, _ = fmt.Fprintf(writer, "%s:%s\n", name, command.Usage) + } + } else { + for _, name := range command.Names() { + _, _ = fmt.Fprintf(writer, "%s\n", name) + } + } + } +} + +func cliArgContains(flagName string) bool { + for _, name := range strings.Split(flagName, ",") { + name = strings.TrimSpace(name) + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 + } + flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + for _, a := range os.Args { + if a == flag { + return true + } + } + } + return false +} + +func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { + cur := strings.TrimPrefix(lastArg, "-") + cur = strings.TrimPrefix(cur, "-") + for _, flag := range flags { + if bflag, ok := flag.(*BoolFlag); ok && bflag.Hidden { + continue + } + for _, name := range flag.Names() { + name = strings.TrimSpace(name) + // this will get total count utf8 letters in flag name + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 // resuse this count to generate single - or -- in flag completion + } + // if flag name has more than one utf8 letter and last argument in cli has -- prefix then + // skip flag completion for short flags example -v or -x + if strings.HasPrefix(lastArg, "--") && count == 1 { + continue + } + // match if last argument matches this flag and it is not repeated + if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(name) { + flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + _, _ = fmt.Fprintln(writer, flagCompletion) + } + } + } +} + +func DefaultCompleteWithFlags(cmd *Command) func(c *Context) { + return func(c *Context) { + if len(os.Args) > 2 { + lastArg := os.Args[len(os.Args)-2] + if strings.HasPrefix(lastArg, "-") { + printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer) + if cmd != nil { + printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer) + } + return + } + } + if cmd != nil { + printCommandSuggestions(cmd.Subcommands, c.App.Writer) + } else { + printCommandSuggestions(c.App.Commands, c.App.Writer) } } } // ShowCommandHelpAndExit - exits with code after showing help func ShowCommandHelpAndExit(c *Context, command string, code int) { - ShowCommandHelp(c, command) + _ = ShowCommandHelp(c, command) os.Exit(code) } @@ -179,17 +195,19 @@ func ShowCommandHelp(ctx *Context, command string) error { 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) + templ := c.CustomHelpTemplate + if templ == "" { + templ = CommandHelpTemplate } + + HelpPrinter(ctx.App.Writer, templ, c) + return nil } } if ctx.App.CommandNotFound == nil { - return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3) + return Exit(fmt.Sprintf("No help topic for '%v'", command), 3) } ctx.App.CommandNotFound(ctx, command) @@ -198,7 +216,15 @@ func ShowCommandHelp(ctx *Context, command string) error { // ShowSubcommandHelp prints help for the given subcommand func ShowSubcommandHelp(c *Context) error { - return ShowCommandHelp(c, c.Command.Name) + if c == nil { + return nil + } + + if c.Command != nil { + return ShowCommandHelp(c, c.Command.Name) + } + + return ShowCommandHelp(c, "") } // ShowVersion prints the version number of the App @@ -207,7 +233,7 @@ func ShowVersion(c *Context) { } func printVersion(c *Context) { - fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) + _, _ = 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 @@ -221,66 +247,70 @@ func ShowCompletions(c *Context) { // 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) + if c != nil { + if c.BashComplete != nil { + c.BashComplete(ctx) + } else { + DefaultCompleteWithFlags(c)(ctx) + } } + } -func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) { +// printHelpCustom is the default implementation of HelpPrinterCustom. +// +// The customFuncs map will be combined with a default template.FuncMap to +// allow using arbitrary functions in template rendering. +func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { funcMap := template.FuncMap{ "join": strings.Join, } - if customFunc != nil { - for key, value := range customFunc { - funcMap[key] = value - } + for key, value := range customFuncs { + 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) + _, _ = fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err) } return } - w.Flush() + _ = w.Flush() } func printHelp(out io.Writer, templ string, data interface{}) { - printHelpCustom(out, templ, data, nil) + HelpPrinterCustom(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 - } - }) + for _, name := range VersionFlag.Names() { + if 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 - } - }) + for _, name := range HelpFlag.Names() { + if c.Bool(name) { + found = true + } } return found } func checkCommandHelp(c *Context, name string) bool { if c.Bool("h") || c.Bool("help") { - ShowCommandHelp(c, name) + _ = ShowCommandHelp(c, name) return true } @@ -289,7 +319,7 @@ func checkCommandHelp(c *Context, name string) bool { func checkSubcommandHelp(c *Context) bool { if c.Bool("h") || c.Bool("help") { - ShowSubcommandHelp(c) + _ = ShowSubcommandHelp(c) return true } @@ -304,7 +334,7 @@ func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { pos := len(arguments) - 1 lastArg := arguments[pos] - if lastArg != "--"+BashCompletionFlag.GetName() { + if lastArg != "--generate-bash-completion" { return false, arguments } diff --git a/vendor/github.com/urfave/cli/v2/parse.go b/vendor/github.com/urfave/cli/v2/parse.go new file mode 100644 index 000000000..7df17296a --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/parse.go @@ -0,0 +1,94 @@ +package cli + +import ( + "flag" + "strings" +) + +type iterativeParser interface { + newFlagSet() (*flag.FlagSet, error) + useShortOptionHandling() bool +} + +// To enable short-option handling (e.g., "-it" vs "-i -t") we have to +// iteratively catch parsing errors. This way we achieve LR parsing without +// transforming any arguments. Otherwise, there is no way we can discriminate +// combined short options from common arguments that should be left untouched. +// Pass `shellComplete` to continue parsing options on failure during shell +// completion when, the user-supplied options may be incomplete. +func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error { + for { + err := set.Parse(args) + if !ip.useShortOptionHandling() || err == nil { + if shellComplete { + return nil + } + return err + } + + errStr := err.Error() + trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") + if errStr == trimmed { + return err + } + + // regenerate the initial args with the split short opts + argsWereSplit := false + for i, arg := range args { + // skip args that are not part of the error message + if name := strings.TrimLeft(arg, "-"); name != trimmed { + continue + } + + // if we can't split, the error was accurate + shortOpts := splitShortOptions(set, arg) + if len(shortOpts) == 1 { + return err + } + + // swap current argument with the split version + args = append(args[:i], append(shortOpts, args[i+1:]...)...) + argsWereSplit = true + break + } + + // This should be an impossible to reach code path, but in case the arg + // splitting failed to happen, this will prevent infinite loops + if !argsWereSplit { + return err + } + + // Since custom parsing failed, replace the flag set before retrying + newSet, err := ip.newFlagSet() + if err != nil { + return err + } + *set = *newSet + } +} + +func splitShortOptions(set *flag.FlagSet, arg string) []string { + shortFlagsExist := func(s string) bool { + for _, c := range s[1:] { + if f := set.Lookup(string(c)); f == nil { + return false + } + } + return true + } + + if !isSplittable(arg) || !shortFlagsExist(arg) { + return []string{arg} + } + + separated := make([]string, 0, len(arg)-1) + for _, flagChar := range arg[1:] { + separated = append(separated, "-"+string(flagChar)) + } + + return separated +} + +func isSplittable(flagArg string) bool { + return strings.HasPrefix(flagArg, "-") && !strings.HasPrefix(flagArg, "--") && len(flagArg) > 2 +} diff --git a/vendor/github.com/urfave/cli/v2/sort.go b/vendor/github.com/urfave/cli/v2/sort.go new file mode 100644 index 000000000..23d1c2f77 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/sort.go @@ -0,0 +1,29 @@ +package cli + +import "unicode" + +// lexicographicLess compares strings alphabetically considering case. +func lexicographicLess(i, j string) bool { + iRunes := []rune(i) + jRunes := []rune(j) + + lenShared := len(iRunes) + if lenShared > len(jRunes) { + lenShared = len(jRunes) + } + + for index := 0; index < lenShared; index++ { + ir := iRunes[index] + jr := jRunes[index] + + if lir, ljr := unicode.ToLower(ir), unicode.ToLower(jr); lir != ljr { + return lir < ljr + } + + if ir != jr { + return ir < jr + } + } + + return i < j +} diff --git a/vendor/github.com/urfave/cli/v2/template.go b/vendor/github.com/urfave/cli/v2/template.go new file mode 100644 index 000000000..1cc4bd624 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/template.go @@ -0,0 +1,119 @@ +package cli + +// 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}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{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}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}} +` + +var MarkdownDocTemplate = `% {{ .App.Name }}(8){{ if .App.Description }} {{ .App.Description }}{{ end }} +{{ range $a := .App.Authors }} +% {{ $a }}{{ end }} + +# NAME + +{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} + +# SYNOPSIS + +{{ .App.Name }} +{{ if .SynopsisArgs }} +` + "```" + ` +{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` +{{ end }}{{ if .App.UsageText }} +# DESCRIPTION + +{{ .App.UsageText }} +{{ end }} +**Usage**: + +` + "```" + ` +{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +` + "```" + ` +{{ if .GlobalArgs }} +# GLOBAL OPTIONS +{{ range $v := .GlobalArgs }} +{{ $v }}{{ end }} +{{ end }}{{ if .Commands }} +# COMMANDS +{{ range $v := .Commands }} +{{ $v }}{{ end }}{{ end }}` + +var FishCompletionTemplate = `# {{ .App.Name }} fish shell completion + +function __fish_{{ .App.Name }}_no_subcommand --description 'Test if there has been any subcommand yet' + for i in (commandline -opc) + if contains -- $i{{ range $v := .AllCommands }} {{ $v }}{{ end }} + return 1 + end + end + return 0 +end + +{{ range $v := .Completions }}{{ $v }} +{{ end }}` diff --git a/vendor/github.com/vektah/gqlparser/.gitignore b/vendor/github.com/vektah/gqlparser/v2/.gitignore similarity index 100% rename from vendor/github.com/vektah/gqlparser/.gitignore rename to vendor/github.com/vektah/gqlparser/v2/.gitignore diff --git a/vendor/github.com/vektah/gqlparser/LICENSE b/vendor/github.com/vektah/gqlparser/v2/LICENSE similarity index 100% rename from vendor/github.com/vektah/gqlparser/LICENSE rename to vendor/github.com/vektah/gqlparser/v2/LICENSE diff --git a/vendor/github.com/vektah/gqlparser/ast/argmap.go b/vendor/github.com/vektah/gqlparser/v2/ast/argmap.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/argmap.go rename to vendor/github.com/vektah/gqlparser/v2/ast/argmap.go diff --git a/vendor/github.com/vektah/gqlparser/ast/collections.go b/vendor/github.com/vektah/gqlparser/v2/ast/collections.go similarity index 93% rename from vendor/github.com/vektah/gqlparser/ast/collections.go rename to vendor/github.com/vektah/gqlparser/v2/ast/collections.go index 6bf672976..94b800ee2 100644 --- a/vendor/github.com/vektah/gqlparser/ast/collections.go +++ b/vendor/github.com/vektah/gqlparser/v2/ast/collections.go @@ -33,6 +33,16 @@ func (l DirectiveList) ForName(name string) *Directive { return nil } +func (l DirectiveList) ForNames(name string) []*Directive { + resp := []*Directive{} + for _, it := range l { + if it.Name == name { + resp = append(resp, it) + } + } + return resp +} + type OperationList []*OperationDefinition func (l OperationList) ForName(name string) *OperationDefinition { diff --git a/vendor/github.com/vektah/gqlparser/ast/definition.go b/vendor/github.com/vektah/gqlparser/v2/ast/definition.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/definition.go rename to vendor/github.com/vektah/gqlparser/v2/ast/definition.go diff --git a/vendor/github.com/vektah/gqlparser/ast/directive.go b/vendor/github.com/vektah/gqlparser/v2/ast/directive.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/directive.go rename to vendor/github.com/vektah/gqlparser/v2/ast/directive.go diff --git a/vendor/github.com/vektah/gqlparser/ast/document.go b/vendor/github.com/vektah/gqlparser/v2/ast/document.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/document.go rename to vendor/github.com/vektah/gqlparser/v2/ast/document.go diff --git a/vendor/github.com/vektah/gqlparser/ast/dumper.go b/vendor/github.com/vektah/gqlparser/v2/ast/dumper.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/dumper.go rename to vendor/github.com/vektah/gqlparser/v2/ast/dumper.go diff --git a/vendor/github.com/vektah/gqlparser/ast/fragment.go b/vendor/github.com/vektah/gqlparser/v2/ast/fragment.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/fragment.go rename to vendor/github.com/vektah/gqlparser/v2/ast/fragment.go diff --git a/vendor/github.com/vektah/gqlparser/ast/operation.go b/vendor/github.com/vektah/gqlparser/v2/ast/operation.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/operation.go rename to vendor/github.com/vektah/gqlparser/v2/ast/operation.go diff --git a/vendor/github.com/vektah/gqlparser/v2/ast/path.go b/vendor/github.com/vektah/gqlparser/v2/ast/path.go new file mode 100644 index 000000000..9af168438 --- /dev/null +++ b/vendor/github.com/vektah/gqlparser/v2/ast/path.go @@ -0,0 +1,67 @@ +package ast + +import ( + "bytes" + "encoding/json" + "fmt" +) + +var _ json.Unmarshaler = (*Path)(nil) + +type Path []PathElement + +type PathElement interface { + isPathElement() +} + +var _ PathElement = PathIndex(0) +var _ PathElement = PathName("") + +func (path Path) String() string { + var str bytes.Buffer + for i, v := range path { + switch v := v.(type) { + case PathIndex: + str.WriteString(fmt.Sprintf("[%d]", v)) + case PathName: + if i != 0 { + str.WriteByte('.') + } + str.WriteString(string(v)) + default: + panic(fmt.Sprintf("unknown type: %T", v)) + } + } + return str.String() +} + +func (path *Path) UnmarshalJSON(b []byte) error { + var vs []interface{} + err := json.Unmarshal(b, &vs) + if err != nil { + return err + } + + *path = make([]PathElement, 0, len(vs)) + for _, v := range vs { + switch v := v.(type) { + case string: + *path = append(*path, PathName(v)) + case int: + *path = append(*path, PathIndex(v)) + case float64: + *path = append(*path, PathIndex(int(v))) + default: + return fmt.Errorf("unknown path element type: %T", v) + } + } + return nil +} + +type PathIndex int + +func (_ PathIndex) isPathElement() {} + +type PathName string + +func (_ PathName) isPathElement() {} diff --git a/vendor/github.com/vektah/gqlparser/ast/selection.go b/vendor/github.com/vektah/gqlparser/v2/ast/selection.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/selection.go rename to vendor/github.com/vektah/gqlparser/v2/ast/selection.go diff --git a/vendor/github.com/vektah/gqlparser/ast/source.go b/vendor/github.com/vektah/gqlparser/v2/ast/source.go similarity index 94% rename from vendor/github.com/vektah/gqlparser/ast/source.go rename to vendor/github.com/vektah/gqlparser/v2/ast/source.go index 08c66689a..2949f83f7 100644 --- a/vendor/github.com/vektah/gqlparser/ast/source.go +++ b/vendor/github.com/vektah/gqlparser/v2/ast/source.go @@ -3,13 +3,13 @@ package ast // Source covers a single *.graphql file type Source struct { // Name is the filename of the source - Name string + Name string // Input is the actual contents of the source file - Input string + Input string // BuiltIn indicate whether the source is a part of the specification BuiltIn bool } - + type Position struct { Start int // The starting position, in runes, of this token in the input. End int // The end position, in runes, of this token in the input. diff --git a/vendor/github.com/vektah/gqlparser/ast/type.go b/vendor/github.com/vektah/gqlparser/v2/ast/type.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/type.go rename to vendor/github.com/vektah/gqlparser/v2/ast/type.go diff --git a/vendor/github.com/vektah/gqlparser/ast/value.go b/vendor/github.com/vektah/gqlparser/v2/ast/value.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/ast/value.go rename to vendor/github.com/vektah/gqlparser/v2/ast/value.go diff --git a/vendor/github.com/vektah/gqlparser/v2/formatter/formatter.go b/vendor/github.com/vektah/gqlparser/v2/formatter/formatter.go new file mode 100644 index 000000000..194911a1e --- /dev/null +++ b/vendor/github.com/vektah/gqlparser/v2/formatter/formatter.go @@ -0,0 +1,605 @@ +package formatter + +import ( + "fmt" + "io" + "sort" + "strings" + + "github.com/vektah/gqlparser/v2/ast" +) + +type Formatter interface { + FormatSchema(schema *ast.Schema) + FormatSchemaDocument(doc *ast.SchemaDocument) + FormatQueryDocument(doc *ast.QueryDocument) +} + +func NewFormatter(w io.Writer) Formatter { + return &formatter{writer: w} +} + +type formatter struct { + writer io.Writer + + indent int + emitBuiltin bool + + padNext bool + lineHead bool +} + +func (f *formatter) writeString(s string) { + _, _ = f.writer.Write([]byte(s)) +} + +func (f *formatter) writeIndent() *formatter { + if f.lineHead { + f.writeString(strings.Repeat("\t", f.indent)) + } + f.lineHead = false + f.padNext = false + + return f +} + +func (f *formatter) WriteNewline() *formatter { + f.writeString("\n") + f.lineHead = true + f.padNext = false + + return f +} + +func (f *formatter) WriteWord(word string) *formatter { + if f.lineHead { + f.writeIndent() + } + if f.padNext { + f.writeString(" ") + } + f.writeString(strings.TrimSpace(word)) + f.padNext = true + + return f +} + +func (f *formatter) WriteString(s string) *formatter { + if f.lineHead { + f.writeIndent() + } + if f.padNext { + f.writeString(" ") + } + f.writeString(s) + f.padNext = false + + return f +} + +func (f *formatter) WriteDescription(s string) *formatter { + if s == "" { + return f + } + + f.WriteString(`"""`).WriteNewline() + + ss := strings.Split(s, "\n") + for _, s := range ss { + f.WriteString(s).WriteNewline() + } + + f.WriteString(`"""`).WriteNewline() + + return f +} + +func (f *formatter) IncrementIndent() { + f.indent++ +} + +func (f *formatter) DecrementIndent() { + f.indent-- +} + +func (f *formatter) NoPadding() *formatter { + f.padNext = false + + return f +} + +func (f *formatter) NeedPadding() *formatter { + f.padNext = true + + return f +} + +func (f *formatter) FormatSchema(schema *ast.Schema) { + if schema == nil { + return + } + + var inSchema bool + startSchema := func() { + if !inSchema { + inSchema = true + + f.WriteWord("schema").WriteString("{").WriteNewline() + f.IncrementIndent() + } + } + if schema.Query != nil && schema.Query.Name != "Query" { + startSchema() + f.WriteWord("query").NoPadding().WriteString(":").NeedPadding() + f.WriteWord(schema.Query.Name).WriteNewline() + } + if schema.Mutation != nil && schema.Mutation.Name != "Mutation" { + startSchema() + f.WriteWord("mutation").NoPadding().WriteString(":").NeedPadding() + f.WriteWord(schema.Mutation.Name).WriteNewline() + } + if schema.Subscription != nil && schema.Subscription.Name != "Subscription" { + startSchema() + f.WriteWord("subscription").NoPadding().WriteString(":").NeedPadding() + f.WriteWord(schema.Subscription.Name).WriteNewline() + } + if inSchema { + f.DecrementIndent() + f.WriteString("}").WriteNewline() + } + + directiveNames := make([]string, 0, len(schema.Directives)) + for name := range schema.Directives { + directiveNames = append(directiveNames, name) + } + sort.Strings(directiveNames) + for _, name := range directiveNames { + f.FormatDirectiveDefinition(schema.Directives[name]) + } + + typeNames := make([]string, 0, len(schema.Types)) + for name := range schema.Types { + typeNames = append(typeNames, name) + } + sort.Strings(typeNames) + for _, name := range typeNames { + f.FormatDefinition(schema.Types[name], false) + } +} + +func (f *formatter) FormatSchemaDocument(doc *ast.SchemaDocument) { + // TODO emit by position based order + + if doc == nil { + return + } + + f.FormatSchemaDefinitionList(doc.Schema, false) + f.FormatSchemaDefinitionList(doc.SchemaExtension, true) + + f.FormatDirectiveDefinitionList(doc.Directives) + + f.FormatDefinitionList(doc.Definitions, false) + f.FormatDefinitionList(doc.Extensions, true) +} + +func (f *formatter) FormatQueryDocument(doc *ast.QueryDocument) { + // TODO emit by position based order + + if doc == nil { + return + } + + f.FormatOperationList(doc.Operations) + f.FormatFragmentDefinitionList(doc.Fragments) +} + +func (f *formatter) FormatSchemaDefinitionList(lists ast.SchemaDefinitionList, extension bool) { + if len(lists) == 0 { + return + } + + if extension { + f.WriteWord("extend") + } + f.WriteWord("schema").WriteString("{").WriteNewline() + f.IncrementIndent() + + for _, def := range lists { + f.FormatSchemaDefinition(def) + } + + f.DecrementIndent() + f.WriteString("}").WriteNewline() +} + +func (f *formatter) FormatSchemaDefinition(def *ast.SchemaDefinition) { + f.WriteDescription(def.Description) + + f.FormatDirectiveList(def.Directives) + + f.FormatOperationTypeDefinitionList(def.OperationTypes) +} + +func (f *formatter) FormatOperationTypeDefinitionList(lists ast.OperationTypeDefinitionList) { + for _, def := range lists { + f.FormatOperationTypeDefinition(def) + } +} + +func (f *formatter) FormatOperationTypeDefinition(def *ast.OperationTypeDefinition) { + f.WriteWord(string(def.Operation)).NoPadding().WriteString(":").NeedPadding() + f.WriteWord(def.Type) + f.WriteNewline() +} + +func (f *formatter) FormatFieldList(fieldList ast.FieldList) { + if len(fieldList) == 0 { + return + } + + f.WriteString("{").WriteNewline() + f.IncrementIndent() + + for _, field := range fieldList { + f.FormatFieldDefinition(field) + } + + f.DecrementIndent() + f.WriteString("}") +} + +func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) { + if !f.emitBuiltin && strings.HasPrefix(field.Name, "__") { + return + } + + f.WriteDescription(field.Description) + + f.WriteWord(field.Name).NoPadding() + f.FormatArgumentDefinitionList(field.Arguments) + f.NoPadding().WriteString(":").NeedPadding() + f.FormatType(field.Type) + + if field.DefaultValue != nil { + f.WriteWord("=") + f.FormatValue(field.DefaultValue) + } + + f.FormatDirectiveList(field.Directives) + + f.WriteNewline() +} + +func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionList) { + if len(lists) == 0 { + return + } + + f.WriteString("(") + for idx, arg := range lists { + f.FormatArgumentDefinition(arg) + + if idx != len(lists)-1 { + f.NoPadding().WriteWord(",") + } + } + f.NoPadding().WriteString(")").NeedPadding() +} + +func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) { + f.WriteDescription(def.Description) + + f.WriteWord(def.Name).NoPadding().WriteString(":").NeedPadding() + f.FormatType(def.Type) + + if def.DefaultValue != nil { + f.WriteWord("=") + f.FormatValue(def.DefaultValue) + } +} + +func (f *formatter) FormatDirectiveLocation(location ast.DirectiveLocation) { + f.WriteWord(string(location)) +} + +func (f *formatter) FormatDirectiveDefinitionList(lists ast.DirectiveDefinitionList) { + if len(lists) == 0 { + return + } + + for _, dec := range lists { + f.FormatDirectiveDefinition(dec) + } +} + +func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) { + if !f.emitBuiltin { + if def.Position.Src.BuiltIn { + return + } + } + + f.WriteDescription(def.Description) + f.WriteWord("directive").WriteString("@").WriteWord(def.Name) + + if len(def.Arguments) != 0 { + f.NoPadding() + f.FormatArgumentDefinitionList(def.Arguments) + } + + if len(def.Locations) != 0 { + f.WriteWord("on") + + for idx, dirLoc := range def.Locations { + f.FormatDirectiveLocation(dirLoc) + + if idx != len(def.Locations)-1 { + f.WriteWord("|") + } + } + } + + f.WriteNewline() +} + +func (f *formatter) FormatDefinitionList(lists ast.DefinitionList, extend bool) { + if len(lists) == 0 { + return + } + + for _, dec := range lists { + f.FormatDefinition(dec, extend) + } +} + +func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) { + if !f.emitBuiltin && def.BuiltIn { + return + } + + f.WriteDescription(def.Description) + + if extend { + f.WriteWord("extend") + } + + switch def.Kind { + case ast.Scalar: + f.WriteWord("scalar").WriteWord(def.Name) + + case ast.Object: + f.WriteWord("type").WriteWord(def.Name) + + case ast.Interface: + f.WriteWord("interface").WriteWord(def.Name) + + case ast.Union: + f.WriteWord("union").WriteWord(def.Name) + + case ast.Enum: + f.WriteWord("enum").WriteWord(def.Name) + + case ast.InputObject: + f.WriteWord("input").WriteWord(def.Name) + } + + if len(def.Interfaces) != 0 { + f.WriteWord("implements").WriteWord(strings.Join(def.Interfaces, " & ")) + } + + f.FormatDirectiveList(def.Directives) + + if len(def.Types) != 0 { + f.WriteWord("=").WriteWord(strings.Join(def.Types, " | ")) + } + + f.FormatFieldList(def.Fields) + + f.FormatEnumValueList(def.EnumValues) + + f.WriteNewline() +} + +func (f *formatter) FormatEnumValueList(lists ast.EnumValueList) { + if len(lists) == 0 { + return + } + + f.WriteString("{").WriteNewline() + f.IncrementIndent() + + for _, v := range lists { + f.FormatEnumValueDefinition(v) + } + + f.DecrementIndent() + f.WriteString("}") +} + +func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) { + f.WriteDescription(def.Description) + + f.WriteWord(def.Name) + f.FormatDirectiveList(def.Directives) + + f.WriteNewline() +} + +func (f *formatter) FormatOperationList(lists ast.OperationList) { + for _, def := range lists { + f.FormatOperationDefinition(def) + } +} + +func (f *formatter) FormatOperationDefinition(def *ast.OperationDefinition) { + f.WriteWord(string(def.Operation)) + if def.Name != "" { + f.WriteWord(def.Name) + } + f.FormatVariableDefinitionList(def.VariableDefinitions) + f.FormatDirectiveList(def.Directives) + + if len(def.SelectionSet) != 0 { + f.FormatSelectionSet(def.SelectionSet) + f.WriteNewline() + } +} + +func (f *formatter) FormatDirectiveList(lists ast.DirectiveList) { + if len(lists) == 0 { + return + } + + for _, dir := range lists { + f.FormatDirective(dir) + } +} + +func (f *formatter) FormatDirective(dir *ast.Directive) { + f.WriteString("@").WriteWord(dir.Name) + f.FormatArgumentList(dir.Arguments) +} + +func (f *formatter) FormatArgumentList(lists ast.ArgumentList) { + if len(lists) == 0 { + return + } + f.NoPadding().WriteString("(") + for idx, arg := range lists { + f.FormatArgument(arg) + + if idx != len(lists)-1 { + f.NoPadding().WriteWord(",") + } + } + f.WriteString(")").NeedPadding() +} + +func (f *formatter) FormatArgument(arg *ast.Argument) { + f.WriteWord(arg.Name).NoPadding().WriteString(":").NeedPadding() + f.WriteString(arg.Value.String()) +} + +func (f *formatter) FormatFragmentDefinitionList(lists ast.FragmentDefinitionList) { + for _, def := range lists { + f.FormatFragmentDefinition(def) + } +} + +func (f *formatter) FormatFragmentDefinition(def *ast.FragmentDefinition) { + f.WriteWord("fragment").WriteWord(def.Name) + f.FormatVariableDefinitionList(def.VariableDefinition) + f.WriteWord("on").WriteWord(def.TypeCondition) + f.FormatDirectiveList(def.Directives) + + if len(def.SelectionSet) != 0 { + f.FormatSelectionSet(def.SelectionSet) + f.WriteNewline() + } +} + +func (f *formatter) FormatVariableDefinitionList(lists ast.VariableDefinitionList) { + if len(lists) == 0 { + return + } + + f.WriteString("(") + for idx, def := range lists { + f.FormatVariableDefinition(def) + + if idx != len(lists)-1 { + f.NoPadding().WriteWord(",") + } + } + f.NoPadding().WriteString(")").NeedPadding() +} + +func (f *formatter) FormatVariableDefinition(def *ast.VariableDefinition) { + f.WriteString("$").WriteWord(def.Variable).NoPadding().WriteString(":").NeedPadding() + f.FormatType(def.Type) + + if def.DefaultValue != nil { + f.WriteWord("=") + f.FormatValue(def.DefaultValue) + } + + // TODO https://github.com/vektah/gqlparser/v2/issues/102 + // VariableDefinition : Variable : Type DefaultValue? Directives[Const]? +} + +func (f *formatter) FormatSelectionSet(sets ast.SelectionSet) { + if len(sets) == 0 { + return + } + + f.WriteString("{").WriteNewline() + f.IncrementIndent() + + for _, sel := range sets { + f.FormatSelection(sel) + } + + f.DecrementIndent() + f.WriteString("}") +} + +func (f *formatter) FormatSelection(selection ast.Selection) { + switch v := selection.(type) { + case *ast.Field: + f.FormatField(v) + + case *ast.FragmentSpread: + f.FormatFragmentSpread(v) + + case *ast.InlineFragment: + f.FormatInlineFragment(v) + + default: + panic(fmt.Errorf("unknown Selection type: %T", selection)) + } + + f.WriteNewline() +} + +func (f *formatter) FormatField(field *ast.Field) { + if field.Alias != "" && field.Alias != field.Name { + f.WriteWord(field.Alias).NoPadding().WriteString(":").NeedPadding() + } + f.WriteWord(field.Name) + + if len(field.Arguments) != 0 { + f.NoPadding() + f.FormatArgumentList(field.Arguments) + f.NeedPadding() + } + + f.FormatDirectiveList(field.Directives) + + f.FormatSelectionSet(field.SelectionSet) +} + +func (f *formatter) FormatFragmentSpread(spread *ast.FragmentSpread) { + f.WriteWord("...").WriteWord(spread.Name) + + f.FormatDirectiveList(spread.Directives) +} + +func (f *formatter) FormatInlineFragment(inline *ast.InlineFragment) { + f.WriteWord("...") + if inline.TypeCondition != "" { + f.WriteWord("on").WriteWord(inline.TypeCondition) + } + + f.FormatDirectiveList(inline.Directives) + + f.FormatSelectionSet(inline.SelectionSet) +} + +func (f *formatter) FormatType(t *ast.Type) { + f.WriteWord(t.String()) +} + +func (f *formatter) FormatValue(value *ast.Value) { + f.WriteString(value.String()) +} diff --git a/vendor/github.com/vektah/gqlparser/go.mod b/vendor/github.com/vektah/gqlparser/v2/go.mod similarity index 52% rename from vendor/github.com/vektah/gqlparser/go.mod rename to vendor/github.com/vektah/gqlparser/v2/go.mod index dff172f6f..afdb99d8c 100644 --- a/vendor/github.com/vektah/gqlparser/go.mod +++ b/vendor/github.com/vektah/gqlparser/v2/go.mod @@ -1,10 +1,12 @@ -module github.com/vektah/gqlparser +module github.com/vektah/gqlparser/v2 + +go 1.12 require ( github.com/agnivade/levenshtein v1.0.1 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 - github.com/sergi/go-diff v1.0.0 // indirect - github.com/stretchr/testify v1.3.0 + github.com/sergi/go-diff v1.1.0 // indirect + github.com/stretchr/testify v1.4.0 golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 - gopkg.in/yaml.v2 v2.2.2 + gopkg.in/yaml.v2 v2.2.4 ) diff --git a/vendor/github.com/vektah/gqlparser/go.sum b/vendor/github.com/vektah/gqlparser/v2/go.sum similarity index 52% rename from vendor/github.com/vektah/gqlparser/go.sum rename to vendor/github.com/vektah/gqlparser/v2/go.sum index 794906fa2..38f4ee3d6 100644 --- a/vendor/github.com/vektah/gqlparser/go.sum +++ b/vendor/github.com/vektah/gqlparser/v2/go.sum @@ -4,16 +4,27 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNg 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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 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= 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-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/vektah/gqlparser/gqlerror/error.go b/vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go similarity index 81% rename from vendor/github.com/vektah/gqlparser/gqlerror/error.go rename to vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go index c4c0847ad..390a7ab3f 100644 --- a/vendor/github.com/vektah/gqlparser/gqlerror/error.go +++ b/vendor/github.com/vektah/gqlparser/v2/gqlerror/error.go @@ -5,13 +5,13 @@ import ( "fmt" "strconv" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) // Error is the standard graphql error type described in https://facebook.github.io/graphql/draft/#sec-Errors type Error struct { Message string `json:"message"` - Path []interface{} `json:"path,omitempty"` + Path ast.Path `json:"path,omitempty"` Locations []Location `json:"locations,omitempty"` Extensions map[string]interface{} `json:"extensions,omitempty"` Rule string `json:"-"` @@ -63,20 +63,7 @@ func (err *Error) Error() string { } func (err Error) pathString() string { - var str bytes.Buffer - for i, v := range err.Path { - - switch v := v.(type) { - case int, int64: - str.WriteString(fmt.Sprintf("[%d]", v)) - default: - if i != 0 { - str.WriteByte('.') - } - str.WriteString(fmt.Sprint(v)) - } - } - return str.String() + return err.Path.String() } func (errs List) Error() string { @@ -88,7 +75,7 @@ func (errs List) Error() string { return buf.String() } -func WrapPath(path []interface{}, err error) *Error { +func WrapPath(path ast.Path, err error) *Error { return &Error{ Message: err.Error(), Path: path, @@ -101,7 +88,7 @@ func Errorf(message string, args ...interface{}) *Error { } } -func ErrorPathf(path []interface{}, message string, args ...interface{}) *Error { +func ErrorPathf(path ast.Path, message string, args ...interface{}) *Error { return &Error{ Message: fmt.Sprintf(message, args...), Path: path, diff --git a/vendor/github.com/vektah/gqlparser/gqlparser.go b/vendor/github.com/vektah/gqlparser/v2/gqlparser.go similarity index 79% rename from vendor/github.com/vektah/gqlparser/gqlparser.go rename to vendor/github.com/vektah/gqlparser/v2/gqlparser.go index 71e464072..ace63e14a 100644 --- a/vendor/github.com/vektah/gqlparser/gqlparser.go +++ b/vendor/github.com/vektah/gqlparser/v2/gqlparser.go @@ -1,11 +1,11 @@ package gqlparser import ( - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/parser" - "github.com/vektah/gqlparser/validator" - _ "github.com/vektah/gqlparser/validator/rules" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vektah/gqlparser/v2/parser" + "github.com/vektah/gqlparser/v2/validator" + _ "github.com/vektah/gqlparser/v2/validator/rules" ) func LoadSchema(str ...*ast.Source) (*ast.Schema, *gqlerror.Error) { diff --git a/vendor/github.com/vektah/gqlparser/lexer/blockstring.go b/vendor/github.com/vektah/gqlparser/v2/lexer/blockstring.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/lexer/blockstring.go rename to vendor/github.com/vektah/gqlparser/v2/lexer/blockstring.go diff --git a/vendor/github.com/vektah/gqlparser/lexer/lexer.go b/vendor/github.com/vektah/gqlparser/v2/lexer/lexer.go similarity index 99% rename from vendor/github.com/vektah/gqlparser/lexer/lexer.go rename to vendor/github.com/vektah/gqlparser/v2/lexer/lexer.go index 89687857b..720dd5b48 100644 --- a/vendor/github.com/vektah/gqlparser/lexer/lexer.go +++ b/vendor/github.com/vektah/gqlparser/v2/lexer/lexer.go @@ -4,8 +4,8 @@ import ( "bytes" "unicode/utf8" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" ) // Lexer turns graphql request and schema strings into tokens diff --git a/vendor/github.com/vektah/gqlparser/lexer/lexer_test.yml b/vendor/github.com/vektah/gqlparser/v2/lexer/lexer_test.yml similarity index 100% rename from vendor/github.com/vektah/gqlparser/lexer/lexer_test.yml rename to vendor/github.com/vektah/gqlparser/v2/lexer/lexer_test.yml diff --git a/vendor/github.com/vektah/gqlparser/lexer/token.go b/vendor/github.com/vektah/gqlparser/v2/lexer/token.go similarity index 98% rename from vendor/github.com/vektah/gqlparser/lexer/token.go rename to vendor/github.com/vektah/gqlparser/v2/lexer/token.go index aef8b7298..8985a7efb 100644 --- a/vendor/github.com/vektah/gqlparser/lexer/token.go +++ b/vendor/github.com/vektah/gqlparser/v2/lexer/token.go @@ -3,7 +3,7 @@ package lexer import ( "strconv" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) const ( diff --git a/vendor/github.com/vektah/gqlparser/parser/parser.go b/vendor/github.com/vektah/gqlparser/v2/parser/parser.go similarity index 94% rename from vendor/github.com/vektah/gqlparser/parser/parser.go rename to vendor/github.com/vektah/gqlparser/v2/parser/parser.go index 96e984022..52b8e6840 100644 --- a/vendor/github.com/vektah/gqlparser/parser/parser.go +++ b/vendor/github.com/vektah/gqlparser/v2/parser/parser.go @@ -3,9 +3,9 @@ package parser import ( "strconv" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/lexer" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vektah/gqlparser/v2/lexer" ) type parser struct { diff --git a/vendor/github.com/vektah/gqlparser/parser/query.go b/vendor/github.com/vektah/gqlparser/v2/parser/query.go similarity index 98% rename from vendor/github.com/vektah/gqlparser/parser/query.go rename to vendor/github.com/vektah/gqlparser/v2/parser/query.go index 89e1e2e33..87deeeeb3 100644 --- a/vendor/github.com/vektah/gqlparser/parser/query.go +++ b/vendor/github.com/vektah/gqlparser/v2/parser/query.go @@ -1,10 +1,10 @@ package parser import ( - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/lexer" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vektah/gqlparser/v2/lexer" - . "github.com/vektah/gqlparser/ast" + . "github.com/vektah/gqlparser/v2/ast" ) func ParseQuery(source *Source) (*QueryDocument, *gqlerror.Error) { diff --git a/vendor/github.com/vektah/gqlparser/parser/query_test.yml b/vendor/github.com/vektah/gqlparser/v2/parser/query_test.yml similarity index 100% rename from vendor/github.com/vektah/gqlparser/parser/query_test.yml rename to vendor/github.com/vektah/gqlparser/v2/parser/query_test.yml diff --git a/vendor/github.com/vektah/gqlparser/parser/schema.go b/vendor/github.com/vektah/gqlparser/v2/parser/schema.go similarity index 99% rename from vendor/github.com/vektah/gqlparser/parser/schema.go rename to vendor/github.com/vektah/gqlparser/v2/parser/schema.go index 5689e4334..7cfdd147e 100644 --- a/vendor/github.com/vektah/gqlparser/parser/schema.go +++ b/vendor/github.com/vektah/gqlparser/v2/parser/schema.go @@ -1,9 +1,9 @@ package parser import ( - . "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/lexer" + . "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vektah/gqlparser/v2/lexer" ) func ParseSchema(source *Source) (*SchemaDocument, *gqlerror.Error) { diff --git a/vendor/github.com/vektah/gqlparser/parser/schema_test.yml b/vendor/github.com/vektah/gqlparser/v2/parser/schema_test.yml similarity index 100% rename from vendor/github.com/vektah/gqlparser/parser/schema_test.yml rename to vendor/github.com/vektah/gqlparser/v2/parser/schema_test.yml diff --git a/vendor/github.com/vektah/gqlparser/readme.md b/vendor/github.com/vektah/gqlparser/v2/readme.md similarity index 85% rename from vendor/github.com/vektah/gqlparser/readme.md rename to vendor/github.com/vektah/gqlparser/v2/readme.md index 8d1362bbb..a7cb346b6 100644 --- a/vendor/github.com/vektah/gqlparser/readme.md +++ b/vendor/github.com/vektah/gqlparser/v2/readme.md @@ -1,4 +1,4 @@ -gqlparser [![CircleCI](https://badgen.net/circleci/github/vektah/gqlparser/master)](https://circleci.com/gh/vektah/gqlparser) [![Go Report Card](https://goreportcard.com/badge/github.com/vektah/gqlparser)](https://goreportcard.com/report/github.com/vektah/gqlparser) [![Coverage Status](https://badgen.net/coveralls/c/github/vektah/gqlparser)](https://coveralls.io/github/vektah/gqlparser?branch=master) +gqlparser [![CircleCI](https://badgen.net/circleci/github/vektah/gqlparser/master)](https://circleci.com/gh/vektah/gqlparser) [![Go Report Card](https://goreportcard.com/badge/github.com/vektah/gqlparser/v2)](https://goreportcard.com/report/github.com/vektah/gqlparser/v2) [![Coverage Status](https://badgen.net/coveralls/c/github/vektah/gqlparser)](https://coveralls.io/github/vektah/gqlparser?branch=master) === This is a parser for graphql, written to mirror the graphql-js reference implementation as closely while remaining idiomatic and easy to use. diff --git a/vendor/github.com/vektah/gqlparser/validator/error.go b/vendor/github.com/vektah/gqlparser/v2/validator/error.go similarity index 94% rename from vendor/github.com/vektah/gqlparser/validator/error.go rename to vendor/github.com/vektah/gqlparser/v2/validator/error.go index f354dee59..f8f76055a 100644 --- a/vendor/github.com/vektah/gqlparser/validator/error.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/error.go @@ -3,8 +3,8 @@ package validator import ( "fmt" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" ) type ErrorOption func(err *gqlerror.Error) diff --git a/vendor/github.com/vektah/gqlparser/validator/messaging.go b/vendor/github.com/vektah/gqlparser/v2/validator/messaging.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/validator/messaging.go rename to vendor/github.com/vektah/gqlparser/v2/validator/messaging.go diff --git a/vendor/github.com/vektah/gqlparser/validator/prelude.go b/vendor/github.com/vektah/gqlparser/v2/validator/prelude.go similarity index 98% rename from vendor/github.com/vektah/gqlparser/validator/prelude.go rename to vendor/github.com/vektah/gqlparser/v2/validator/prelude.go index 00ae78f74..0c7e9b2d5 100644 --- a/vendor/github.com/vektah/gqlparser/validator/prelude.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/prelude.go @@ -1,6 +1,6 @@ package validator -import "github.com/vektah/gqlparser/ast" +import "github.com/vektah/gqlparser/v2/ast" var Prelude = &ast.Source{ Name: "prelude.graphql", diff --git a/vendor/github.com/vektah/gqlparser/validator/prelude.graphql b/vendor/github.com/vektah/gqlparser/v2/validator/prelude.graphql similarity index 100% rename from vendor/github.com/vektah/gqlparser/validator/prelude.graphql rename to vendor/github.com/vektah/gqlparser/v2/validator/prelude.graphql diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/fields_on_correct_type.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/fields_on_correct_type.go similarity index 97% rename from vendor/github.com/vektah/gqlparser/validator/rules/fields_on_correct_type.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/fields_on_correct_type.go index 69148d526..8bfb8cc3d 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/fields_on_correct_type.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/fields_on_correct_type.go @@ -4,8 +4,8 @@ import ( "fmt" "sort" - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/fragments_on_composite_types.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/fragments_on_composite_types.go similarity index 92% rename from vendor/github.com/vektah/gqlparser/validator/rules/fragments_on_composite_types.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/fragments_on_composite_types.go index a4a482469..5215f697e 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/fragments_on_composite_types.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/fragments_on_composite_types.go @@ -3,8 +3,8 @@ package validator import ( "fmt" - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_argument_names.go similarity index 94% rename from vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/known_argument_names.go index 1a46431d8..9a53df172 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_argument_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/known_directives.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_directives.go similarity index 87% rename from vendor/github.com/vektah/gqlparser/validator/rules/known_directives.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/known_directives.go index dc4353efc..f3c0f80e4 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/known_directives.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_directives.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/known_fragment_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_fragment_names.go similarity index 82% rename from vendor/github.com/vektah/gqlparser/validator/rules/known_fragment_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/known_fragment_names.go index ec91588c3..b7427d0d0 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/known_fragment_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_fragment_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/known_type_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_type_names.go similarity index 94% rename from vendor/github.com/vektah/gqlparser/validator/rules/known_type_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/known_type_names.go index 223086b38..c228af704 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/known_type_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/known_type_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/lone_anonymous_operation.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/lone_anonymous_operation.go similarity index 83% rename from vendor/github.com/vektah/gqlparser/validator/rules/lone_anonymous_operation.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/lone_anonymous_operation.go index dd232142b..d27528542 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/lone_anonymous_operation.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/lone_anonymous_operation.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/no_fragment_cycles.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_fragment_cycles.go similarity index 96% rename from vendor/github.com/vektah/gqlparser/validator/rules/no_fragment_cycles.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/no_fragment_cycles.go index 7511529b7..81fffa578 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/no_fragment_cycles.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_fragment_cycles.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/no_undefined_variables.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_undefined_variables.go similarity index 88% rename from vendor/github.com/vektah/gqlparser/validator/rules/no_undefined_variables.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/no_undefined_variables.go index 505206bed..4f05f00a2 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/no_undefined_variables.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_undefined_variables.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/no_unused_fragments.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_unused_fragments.go similarity index 88% rename from vendor/github.com/vektah/gqlparser/validator/rules/no_unused_fragments.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/no_unused_fragments.go index 4aa835f5c..dfc896725 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/no_unused_fragments.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_unused_fragments.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/no_unused_variables.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_unused_variables.go similarity index 88% rename from vendor/github.com/vektah/gqlparser/validator/rules/no_unused_variables.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/no_unused_variables.go index 28cf77365..df2e5f4b7 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/no_unused_variables.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/no_unused_variables.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/overlapping_fields_can_be_merged.go similarity index 99% rename from vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/overlapping_fields_can_be_merged.go index bb2f18319..5cd028df8 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/overlapping_fields_can_be_merged.go @@ -5,8 +5,8 @@ import ( "fmt" "reflect" - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/possible_fragment_spreads.go similarity index 95% rename from vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/possible_fragment_spreads.go index 046118348..a3f795c97 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/possible_fragment_spreads.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/provided_required_arguments.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/provided_required_arguments.go similarity index 94% rename from vendor/github.com/vektah/gqlparser/validator/rules/provided_required_arguments.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/provided_required_arguments.go index 55791a6bf..4410288a8 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/provided_required_arguments.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/provided_required_arguments.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/scalar_leafs.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/scalar_leafs.go similarity index 91% rename from vendor/github.com/vektah/gqlparser/validator/rules/scalar_leafs.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/scalar_leafs.go index bb961f448..718bc6834 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/scalar_leafs.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/scalar_leafs.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/single_field_subscriptions.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/single_field_subscriptions.go similarity index 87% rename from vendor/github.com/vektah/gqlparser/validator/rules/single_field_subscriptions.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/single_field_subscriptions.go index 53003c112..206e3a6e2 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/single_field_subscriptions.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/single_field_subscriptions.go @@ -3,8 +3,8 @@ package validator import ( "strconv" - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/unique_argument_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_argument_names.go similarity index 89% rename from vendor/github.com/vektah/gqlparser/validator/rules/unique_argument_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_argument_names.go index 0ddcde724..fc2b639df 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/unique_argument_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_argument_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/unique_directives_per_location.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_directives_per_location.go similarity index 85% rename from vendor/github.com/vektah/gqlparser/validator/rules/unique_directives_per_location.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_directives_per_location.go index 077c4687e..2ea4f13d1 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/unique_directives_per_location.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_directives_per_location.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/unique_fragment_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_fragment_names.go similarity index 84% rename from vendor/github.com/vektah/gqlparser/validator/rules/unique_fragment_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_fragment_names.go index 46a8b7c7b..8c348aea0 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/unique_fragment_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_fragment_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/unique_input_field_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_input_field_names.go similarity index 85% rename from vendor/github.com/vektah/gqlparser/validator/rules/unique_input_field_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_input_field_names.go index f254d5888..092be671c 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/unique_input_field_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_input_field_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/unique_operation_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_operation_names.go similarity index 83% rename from vendor/github.com/vektah/gqlparser/validator/rules/unique_operation_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_operation_names.go index c1ab56be0..4d41b60ae 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/unique_operation_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_operation_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/unique_variable_names.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_variable_names.go similarity index 85% rename from vendor/github.com/vektah/gqlparser/validator/rules/unique_variable_names.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_variable_names.go index 70590a886..64ac5072d 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/unique_variable_names.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/unique_variable_names.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/values_of_correct_type.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/values_of_correct_type.go similarity index 97% rename from vendor/github.com/vektah/gqlparser/validator/rules/values_of_correct_type.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/values_of_correct_type.go index d64cc666d..40dc2194a 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/values_of_correct_type.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/values_of_correct_type.go @@ -3,8 +3,8 @@ package validator import ( "fmt" - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/variables_are_input_types.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/variables_are_input_types.go similarity index 86% rename from vendor/github.com/vektah/gqlparser/validator/rules/variables_are_input_types.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/variables_are_input_types.go index 9d58ae1c2..4ea94e5a8 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/variables_are_input_types.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/variables_are_input_types.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/variables_in_allowed_position.go b/vendor/github.com/vektah/gqlparser/v2/validator/rules/variables_in_allowed_position.go similarity index 91% rename from vendor/github.com/vektah/gqlparser/validator/rules/variables_in_allowed_position.go rename to vendor/github.com/vektah/gqlparser/v2/validator/rules/variables_in_allowed_position.go index e6d97c9f6..aba6eb621 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/variables_in_allowed_position.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/rules/variables_in_allowed_position.go @@ -1,8 +1,8 @@ package validator import ( - "github.com/vektah/gqlparser/ast" - . "github.com/vektah/gqlparser/validator" + "github.com/vektah/gqlparser/v2/ast" + . "github.com/vektah/gqlparser/v2/validator" ) func init() { diff --git a/vendor/github.com/vektah/gqlparser/validator/schema.go b/vendor/github.com/vektah/gqlparser/v2/validator/schema.go similarity index 95% rename from vendor/github.com/vektah/gqlparser/validator/schema.go rename to vendor/github.com/vektah/gqlparser/v2/validator/schema.go index 3242822fa..4c96c31a7 100644 --- a/vendor/github.com/vektah/gqlparser/validator/schema.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/schema.go @@ -6,9 +6,9 @@ import ( "strconv" "strings" - . "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" - "github.com/vektah/gqlparser/parser" + . "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vektah/gqlparser/v2/parser" ) func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { @@ -34,10 +34,18 @@ func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { schema.Types[def.Name] = ast.Definitions[i] } + defs := append(DefinitionList{}, ast.Definitions...) + for _, ext := range ast.Extensions { def := schema.Types[ext.Name] if def == nil { - return nil, gqlerror.ErrorPosf(ext.Position, "Cannot extend type %s because it does not exist.", ext.Name) + schema.Types[ext.Name] = &Definition{ + Kind: ext.Kind, + Name: ext.Name, + Position: ext.Position, + } + def = schema.Types[ext.Name] + defs = append(defs, def) } if def.Kind != ext.Kind { @@ -51,7 +59,7 @@ func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { def.EnumValues = append(def.EnumValues, ext.EnumValues...) } - for _, def := range ast.Definitions { + for _, def := range defs { switch def.Kind { case Union: for _, t := range def.Types { @@ -147,9 +155,9 @@ func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { }, &FieldDefinition{ Name: "__type", - Type: NonNullNamedType("__Type", nil), + Type: NamedType("__Type", nil), Arguments: ArgumentDefinitionList{ - {Name: "name", Type: NamedType("String", nil)}, + {Name: "name", Type: NonNullNamedType("String", nil)}, }, }, ) diff --git a/vendor/github.com/vektah/gqlparser/validator/schema_test.yml b/vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml similarity index 94% rename from vendor/github.com/vektah/gqlparser/validator/schema_test.yml rename to vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml index b1d85c448..a5d8bb491 100644 --- a/vendor/github.com/vektah/gqlparser/validator/schema_test.yml +++ b/vendor/github.com/vektah/gqlparser/v2/validator/schema_test.yml @@ -418,15 +418,43 @@ unions: message: "UNION type \"Baz\" must be OBJECT." locations: [{line: 1, column: 7}] + - name: unions of pure type extensions are valid + input: | + + type Review { + body: String! + author: User! @provides(fields: "username") + product: Product! + } + + extend type User @key(fields: "id") { + id: ID! @external + reviews: [Review] + } + + extend type Product @key(fields: "upc") { + upc: String! @external + reviews: [Review] + } + + union Foo = User | Product + scalar _Any + scalar _FieldSet + directive @external on FIELD_DEFINITION + directive @requires(fields: _FieldSet!) on FIELD_DEFINITION + directive @provides(fields: _FieldSet!) on FIELD_DEFINITION + directive @key(fields: _FieldSet!) on OBJECT | INTERFACE + directive @extends on OBJECT + + + type extensions: - - name: cannot extend non existant types + - name: can extend non existant types input: | extend type A { name: String } - error: - message: "Cannot extend type A because it does not exist." - locations: [{line: 1, column: 13}] + - name: cannot extend incorret type existant types input: | diff --git a/vendor/github.com/vektah/gqlparser/validator/suggestionList.go b/vendor/github.com/vektah/gqlparser/v2/validator/suggestionList.go similarity index 100% rename from vendor/github.com/vektah/gqlparser/validator/suggestionList.go rename to vendor/github.com/vektah/gqlparser/v2/validator/suggestionList.go diff --git a/vendor/github.com/vektah/gqlparser/validator/validator.go b/vendor/github.com/vektah/gqlparser/v2/validator/validator.go similarity index 90% rename from vendor/github.com/vektah/gqlparser/validator/validator.go rename to vendor/github.com/vektah/gqlparser/v2/validator/validator.go index bbacec6f2..34bf93db3 100644 --- a/vendor/github.com/vektah/gqlparser/validator/validator.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/validator.go @@ -1,8 +1,8 @@ package validator import ( - . "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" + . "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" ) type AddErrFunc func(options ...ErrorOption) diff --git a/vendor/github.com/vektah/gqlparser/validator/vars.go b/vendor/github.com/vektah/gqlparser/v2/validator/vars.go similarity index 81% rename from vendor/github.com/vektah/gqlparser/validator/vars.go rename to vendor/github.com/vektah/gqlparser/v2/validator/vars.go index aaf3a0d1a..9151fa8e9 100644 --- a/vendor/github.com/vektah/gqlparser/validator/vars.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/vars.go @@ -2,11 +2,12 @@ package validator import ( "reflect" + "strings" "fmt" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" ) var UnexpectedType = fmt.Errorf("Unexpected Type") @@ -16,12 +17,12 @@ func VariableValues(schema *ast.Schema, op *ast.OperationDefinition, variables m coercedVars := map[string]interface{}{} validator := varValidator{ - path: []interface{}{"variable"}, + path: ast.Path{ast.PathName("variable")}, schema: schema, } for _, v := range op.VariableDefinitions { - validator.path = append(validator.path, v.Variable) + validator.path = append(validator.path, ast.PathName(v.Variable)) if !v.Definition.IsInputType() { return nil, gqlerror.ErrorPathf(validator.path, "must an input type") @@ -68,7 +69,7 @@ func VariableValues(schema *ast.Schema, op *ast.OperationDefinition, variables m } type varValidator struct { - path []interface{} + path ast.Path schema *ast.Schema } @@ -86,7 +87,7 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr for i := 0; i < val.Len(); i++ { resetPath() - v.path = append(v.path, i) + v.path = append(v.path, ast.PathIndex(i)) field := val.Index(i) if field.Kind() == reflect.Ptr || field.Kind() == reflect.Interface { @@ -109,13 +110,27 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr panic(fmt.Errorf("missing def for %s", typ.NamedType)) } + if !typ.NonNull && !val.IsValid() { + // If the type is not null and we got a invalid value namely null/nil, then it's valid + return nil + } + switch def.Kind { case ast.Enum: kind := val.Type().Kind() - if kind == reflect.Int || kind == reflect.Int32 || kind == reflect.Int64 || kind == reflect.String { - return nil + if kind != reflect.Int && kind != reflect.Int32 && kind != reflect.Int64 && kind != reflect.String { + return gqlerror.ErrorPathf(v.path, "enums must be ints or strings") } - return gqlerror.ErrorPathf(v.path, "enums must be ints or strings") + isValidEnum := false + for _, enumVal := range def.EnumValues { + if strings.EqualFold(val.String(), enumVal.Name) { + isValidEnum = true + } + } + if !isValidEnum { + return gqlerror.ErrorPathf(v.path, "%s is not a valid %s", val.String(), def.Name) + } + return nil case ast.Scalar: kind := val.Type().Kind() switch typ.NamedType { @@ -156,7 +171,7 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr val.MapIndex(name) fieldDef := def.Fields.ForName(name.String()) resetPath() - v.path = append(v.path, name.String()) + v.path = append(v.path, ast.PathName(name.String())) if fieldDef == nil { return gqlerror.ErrorPathf(v.path, "unknown field") @@ -165,7 +180,7 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr for _, fieldDef := range def.Fields { resetPath() - v.path = append(v.path, fieldDef.Name) + v.path = append(v.path, ast.PathName(fieldDef.Name)) field := val.MapIndex(reflect.ValueOf(fieldDef.Name)) if !field.IsValid() { diff --git a/vendor/github.com/vektah/gqlparser/validator/walk.go b/vendor/github.com/vektah/gqlparser/v2/validator/walk.go similarity index 99% rename from vendor/github.com/vektah/gqlparser/validator/walk.go rename to vendor/github.com/vektah/gqlparser/v2/validator/walk.go index 751ba1f11..8f8abf108 100644 --- a/vendor/github.com/vektah/gqlparser/validator/walk.go +++ b/vendor/github.com/vektah/gqlparser/v2/validator/walk.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/vektah/gqlparser/ast" + "github.com/vektah/gqlparser/v2/ast" ) type Events struct { diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go index 2f04ee5b5..2ffb97bfb 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -7,6 +7,7 @@ package terminal import ( "bytes" "io" + "runtime" "strconv" "sync" "unicode/utf8" @@ -112,6 +113,7 @@ func NewTerminal(c io.ReadWriter, prompt string) *Terminal { } const ( + keyCtrlC = 3 keyCtrlD = 4 keyCtrlU = 21 keyEnter = '\r' @@ -150,8 +152,12 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { switch b[0] { case 1: // ^A return keyHome, b[1:] + case 2: // ^B + return keyLeft, b[1:] case 5: // ^E return keyEnd, b[1:] + case 6: // ^F + return keyRight, b[1:] case 8: // ^H return keyBackspace, b[1:] case 11: // ^K @@ -737,6 +743,9 @@ func (t *Terminal) readLine() (line string, err error) { return "", io.EOF } } + if key == keyCtrlC { + return "", io.EOF + } if key == keyPasteStart { t.pasteActive = true if len(t.line) == 0 { @@ -939,6 +948,8 @@ func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { // readPasswordLine reads from reader until it finds \n or io.EOF. // The slice returned does not include the \n. // readPasswordLine also ignores any \r it finds. +// Windows uses \r as end of line. So, on Windows, readPasswordLine +// reads until it finds \r and ignores any \n it finds during processing. func readPasswordLine(reader io.Reader) ([]byte, error) { var buf [1]byte var ret []byte @@ -947,10 +958,20 @@ func readPasswordLine(reader io.Reader) ([]byte, error) { n, err := reader.Read(buf[:]) if n > 0 { switch buf[0] { + case '\b': + if len(ret) > 0 { + ret = ret[:len(ret)-1] + } case '\n': - return ret, nil + if runtime.GOOS != "windows" { + return ret, nil + } + // otherwise ignore \n case '\r': - // remove \r from passwords on Windows + if runtime.GOOS == "windows" { + return ret, nil + } + // otherwise ignore \r default: ret = append(ret, buf[0]) } diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go index 5cfdf8f3f..f614e9cb6 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go @@ -85,8 +85,8 @@ func ReadPassword(fd int) ([]byte, error) { } old := st - st &^= (windows.ENABLE_ECHO_INPUT) - st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT) + st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT) if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { return nil, err } diff --git a/vendor/golang.org/x/net/publicsuffix/table.go b/vendor/golang.org/x/net/publicsuffix/table.go index 8e1c9d3dd..ec2bde8cb 100644 --- a/vendor/golang.org/x/net/publicsuffix/table.go +++ b/vendor/golang.org/x/net/publicsuffix/table.go @@ -2,7 +2,7 @@ package publicsuffix -const version = "publicsuffix.org's public_suffix_list.dat, git revision dbe9da0a8abeab1b6257c57668d1ecb584189951 (2020-05-27T00:50:31Z)" +const version = "publicsuffix.org's public_suffix_list.dat, git revision bdbe9dfd268d040fc826766b1d4e27dc4416fe73 (2020-08-10T09:26:55Z)" const ( nodesBitsChildren = 10 @@ -23,490 +23,492 @@ const ( ) // numTLD is the number of top level domains. -const numTLD = 1525 +const numTLD = 1518 // Text is the combined text of all labels. -const text = "9guacuiababia-goracleaningroks-theatree12hpalermomahachijoinvill" + - "eksvikaracoldwarszawabogadobeaemcloud66bjarkoyusuharabjerkreimdb" + - "altimore-og-romsdalipayokozebizenakanotoddenavuotnarashinobninsk" + - "aragandaustevoll-o-g-i-naval-d-aosta-valleyboltateshinanomachimk" + - "entateyamagrocerybnikeisenbahn4tatarantours3-ap-northeast-2ix443" + - "2-balsan-suedtirolkuszczytnoipirangamvik12bjugnieznord-frontierb" + - "lackfridayusuisservehumourbloombergbauernishiazaindielddanuorrin" + - "digenamsosnowiechernihivgubs3-website-sa-east-1bloxcms3-website-" + - "us-east-1bluedaemoneyuu2-localhostoregontrailroadrayddnsfreebox-" + - "osascoli-picenordre-landraydns3-website-us-west-1bmoattachments3" + - "-website-us-west-2bms5yuzawabmwedeploybnrwegroweibolognagasakind" + - "eroybomloabathsbchernivtsiciliabondrivefsnillfjordrobaknoluoktac" + - "hikawakuyabukievennodesadoes-itvedestrandrudupontariobranconakan" + - "iikawatanagurabonnishigoddabookinghostfoldnavyboomlair-traffic-c" + - "ontrolleyboschaefflerdalivornohtawaramotoineppueblockbustermezja" + - "mpagefrontapparachutinglobalashovhachinohedmarkarpaczeladzlglobo" + - "avistanbulsan-sudtirolombardynaliaskimitsubatamibugattiffanycher" + - "novtsymantechnologybostikaruizawabostonakijinsekikogentappsselfi" + - "paraglidinglogoweirbotanicalgardenishiharabotanicgardenishiizuna" + - "zukindustriabotanynysagaeroclubmedecincinnationwidealerbouncemer" + - "ckmsdnipropetrovskjervoyageometre-experts-comptablesakyotanabell" + - "unord-aurdalpha-myqnapcloudaccesscambridgeiseiyoichippubetsubets" + - "ugarugbydgoszczecinemagentositecnologiabounty-fullensakerryprope" + - "rtiesalangenishikatakinoueboutiquebechirurgiens-dentistes-en-fra" + - "ncebozen-sudtirolomzaporizhzhegurindustriesteamfamberkeleybozen-" + - "suedtirolondrinapleskarumaifarmsteadurbanamexhibitionishikatsura" + - "git-reposalondonetskasaokamiminersaltdalorenskogloppenzaolbia-te" + - "mpio-olbiatempioolbialystokkepnogatagajobojinfinitintelligencebp" + - "lacedogawarabikomaezakirunorddalotenkawabrandywinevalleybrasilia" + - "brindisibenikindlebtimnetzparisor-fronishikawazukamisunagawabris" + - "toloseyouriparliamentjomeloyalistoragebritishcolumbialowiezagani" + - "shimerabroadcastleclerchiryukyuragifuchungbukharavennagatorodoyb" + - "roadwaybroke-itjxfinitybrokerbronnoysundurhamburglugmbhartipscbg" + - "minakamichiharabrothermesaverdealstahaugesunderseaportsinfolldal" + - "ottebrowsersafetymarketsaludweberbrumunddalottokonamegatakazakin" + - "ternationalfirearmsalvadordalibabalena-devicesalzburgmodellingmx" + - "javald-aostarnbergretakanabeautysvardoesntexisteingeekashibataka" + - "tsukiyosatokamachintaifun-dnsdojolsterbrunelastxn--0trq7p7nnishi" + - "nomiyashironomutashinaintuitkmaxxn--11b4c3dynathomebuiltwithdark" + - "ashiharabrusselsamegawabruxellesamnangerbryansklepparmattelekomm" + - "unikationishinoomotegobrynewhollandyndns-at-homedepotenzamamidsu" + - "ndyndns-at-workisboringrimstadyndns-blogdnsampalacebuskerudinewj" + - "erseybuzentsujiiebuzzwellbeingzonebwfarsundyndns-freeboxosloftra" + - "nakanojoetsuwanouchikujogaszkolancashirecreationishinoshimatsuur" + - "abzhitomirumalatvuopmicrolightingripebzzcommunexus-2community-pr" + - "ochowicecomoarekecomparemarkerryhotelsantacruzsantafedjejuifmetl" + - "ifeinsurancecompute-1computerhistoryofscience-fictioncomsecurity" + - "tacticsantamariakecondoshichinohealth-carereformitakeharaconfere" + - "nceconstructionconsuladonnaharimalopolskanlandyndns-remotewdyndn" + - "s-serverisignconsultanthropologyconsultingrpartycontactozsdeltaj" + - "irittogliattis-a-caterercontagematsubaracontemporaryarteducation" + - "alchikugodontexistmein-iservebeercontractorskenconventureshinode" + - "arthruherecipescaravantaacookingchannelsdvrdnsfor-better-thanawa" + - "tchandclockasukabedzin-berlindasdaburcooluroycooperativano-frank" + - "ivskolefrakkestadyndns-webhopencraftrani-andria-barletta-trani-a" + - "ndriacopenhagencyclopedichofunatoriginstitutemasekashiwaracoprod" + - "uctionsantoandreamhostersanukis-a-celticsfancorsicagliaricoharuo" + - "vatraniandriabarlettatraniandriacorvettemp-dnsaobernardocosenzak" + - "opanecosidnshome-webserverdalutskasumigaurawa-mazowszexnetnedalu" + - "xurycostumedicinakaiwamizawatchesaogoncartoonartdecologiacouchpo" + - "tatofriesaotomeldaluzerncouklugsmilegallocus-3councilvivanovolda" + - "couponsapporocq-acranbrookuwanalyticsardegnarusawacrdyndns-wikir" + - "kenesardiniacreditcardyndns-workshopitsitexaskoyabearalvahkikuch" + - "ikuseikarugalsacecreditunioncremonashgabadaddjaguarqcxn--12cfi8i" + - "xb8lcrewildlifedorainfracloudfrontdoorcricketrzyncrimeast-kazakh" + - "stanangercrotonecrownipasadenaritakurashikis-a-chefashioncrsvpas" + - "sagensarlcruisesarpsborgruecryptonomichigangwoncuisinellajollame" + - "ricanexpressexyculturalcentertainmentranoycuneocupcakecuritiback" + - "yardsarufutsunomiyawakasaikaitakofuefukihaboromskoguidegreecurva" + - "lled-aostaverncymrussiacyonabaruminamidaitomanchestercyouthachio" + - "jiyahooguyfetsundynnsasayamafgujohanamakinoharafhvalerfidoomdnst" + - "racefieldynservebbsasebofagemologicallyngenfigueresinstagingulen" + - "filateliafilegear-audnedalnfilegear-deatnulvikatowicefilegear-gb" + - "izfilegear-iefilegear-jpmorganfilegear-sgunmanxn--1ck2e1bananare" + - "publicasertairaumalborkarasjohkamikoaniikappuboliviajessheimemor" + - "ialaziobserverevistaples3-external-1filminamifuranofinalfinancef" + - "ineartsavonarutomobellevuelosangelesjabbottransurlfinlandynufcfa" + - "nfinnoyfirebaseappatriafirenzefirestonefirmdalegoldpoint2thisami" + - "tsukefishingolffansaxofitjarvodkafjordynv6fitnessettlementrapani" + - "izafjalerflesberguovdageaidnunusualpersonflickragerogerschoenbru" + - "nnflightschokokekschokoladenflirfloginlinefloraflorencefloridats" + - "unanjoburgushikamifuranorth-kazakhstanfloripaderbornfloristanoha" + - "takaharunzenflorokunohealthcareerscholarshipschoolschulezajskats" + - "ushikabeeldengeluidynvpnplus-4flowerschulserverfltravelchannelfl" + - "ynnhosting-clusterfndyroyrvikinguitarsaskatchewanfor-ourfor-some" + - "dizinhistorischeschwarzgwangjuniperfor-theaterforexrothachirogat" + - "akanezawaforgotdnschweizforli-cesena-forlicesenaforlillehammerfe" + - "ste-ipaviancarrdforsaleikangerforsandasuologoipfizerfortalfortmi" + - "ssoulancasterfortworthadanorthwesternmutualfosnesciencecentersci" + - "encehistoryfotaruis-a-cubicle-slavellinodeobjectscientistordalfo" + - "xfordebianfozorafredrikstadtvscjohnsonfreeddnsgeekgalaxyfreedesk" + - "topocznore-og-uvdalfreemasonryfreesitextileirfjordfreetlscotland" + - "freiburgwiddleitungsenfreseniuscountryestateofdelawareggio-calab" + - "riafribourgxn--1ctwolominamatarnobrzegyptianfriuli-v-giuliafriul" + - "i-ve-giuliafriuli-vegiuliafriuli-venezia-giuliafriuli-veneziagiu" + - "liafriuli-vgiuliafriuliv-giuliafriulive-giuliafriulivegiuliafriu" + - "livenezia-giuliafriuliveneziagiuliafriulivgiuliafrlfroganscrappe" + - "r-sitefrognfrolandfrom-akrehamnfrom-alfrom-arfrom-azfrom-capetow" + - "nnews-stagingfrom-coffeedbackplaneapplinzis-a-democratravelersin" + - "surancefrom-ctrdfrom-dchonanbulsan-suedtirolowiczest-le-patronis" + - "hitosashimizunaminamibosogndalpusercontentoyotapartsandnessjoeni" + - "shiwakinvestmentsandoyfrom-dedyn-berlincolnfrom-flanderscrapping" + - "from-gaulardalfrom-hichisochildrensgardenfrom-iafrom-idfrom-ilfr" + - "om-in-brbanzaicloudcontrolledekagaminombresciaustraliamusementdl" + - "lpages3-ap-south-1kappchizip6116-b-dataiji234lima-cityeatselinog" + - "radult3l3p0rtatamotors3-ap-northeast-1337from-kscrysechoseiroumu" + - "enchenissandiegofrom-kyowariasahikawafrom-lanciafrom-mamurogawaf" + - "rom-mdfrom-meeresistancefrom-mifunefrom-mnfrom-modalenfrom-mserv" + - "eirchoshibuyachiyodapliernewspaperfrom-mtnfrom-nctulangevagrigen" + - "tomologyeonggiehtavuoatnagahamaroyerfrom-ndfrom-nefrom-nh-serveb" + - "logsiteleafamilycompanyanagawafflecellclaimserveminecraftrentin-" + - "sud-tirolfrom-njaworznoticiasnesoddenmarkhangelskjakdnepropetrov" + - "skiervaapsteiermarkatsuyamarugame-hostrowiechoyodobashichikashuk" + - "ujitawarafrom-nminamiiserniafrom-nvalledaostargetmyiphostrodawar" + - "afrom-nyfrom-ohkurafrom-oketogurafrom-orfrom-padovaksdalfrom-pra" + - "tohmandalfrom-ris-a-designerfrom-schmidtre-gauldalfrom-sdfrom-tn" + - "from-txn--1lqs03nfrom-utsiracusaikisarazurecontainerdpolicefrom-" + - "val-daostavalleyfrom-vtrentin-sudtirolfrom-wafrom-wielunnerfrom-" + - "wvallee-aosteroyfrom-wyfrosinonefrostalowa-wolawafroyahikobierzy" + - "cefstcgroupgfoggiafujiiderafujikawaguchikonefujiminokamoenairlin" + - "edre-eikerfujinomiyadattowebcampinashikiminohostre-totendofinter" + - "net-dnsaliasiafujiokayamangonohejis-a-doctorayfujisatoshonairpor" + - "tland-4-salernoboribetsuckservemp3fujisawafujishiroishidakabirat" + - "oridefenseljordfujitsurugashimangyshlakasamatsudovre-eikerfujixe" + - "roxn--1lqs71dfujiyoshidavvenjargap-northeast-3fukayabeatservep2p" + - "harmacienservepicservequakefukuchiyamadavvesiidappnodebalancerti" + - "ficationfukudominichristiansburgrondarfukuis-a-financialadvisor-" + - "aurdalfukumitsubishigakishiwadazaifudaigojomedio-campidano-medio" + - "campidanomediofukuokazakisofukushimaniwakuratefukuroishikarikatu" + - "rindalfukusakisosakitagawafukuyamagatakahatakaishimoichinosekiga" + - "harafunabashiriuchinadafunagatakamatsukawafunahashikamiamakusats" + - "umasendaisennangooglecodespotrentin-sued-tirolfundaciofuoiskujuk" + - "uriyamannorfolkebibleirvikaufenfuosskoczowilliamhillfurnitureggi" + - "o-emilia-romagnakatombetsumitakagiizefurubirafurudonostiaafuruka" + - "wairtelebitbridgestonekobayashikshacknetcimbarcelonagawalmartatt" + - "oolforgehimejiitatebayashijonawatempresashibetsukuiiyamanouchiku" + - "hokuryugasakitaurayasudaustrheimatunduhrennesoyokosukanumazuryok" + - "oteastcoastaldefenceatonsbergjerdrumemergencyachts3-ca-central-1" + - "fusodegaurafussaintlouis-a-anarchistoireggiocalabriafutabayamagu" + - "chinomigawafutboldlygoingnowhere-for-morenakatsugawafuttsurugimp" + - "eriafuturecmservesarcasmatartanddesignfuturehostingfuturemailing" + - "fvgfylkesbiblackbaudcdn77-securebungoonord-odalfyresdalhangoutsy" + - "stemscloudhannanmokuizumodenaklodzkochikushinonsenergyhannosegaw" + - "ahanyuzenhapmircloudharstadharvestcelebrationhasamarburghasamina" + - "mi-alpsharis-a-hunterhashbanghasudahasura-appharmacysharphdfcban" + - "kazoologyhasvikazunow-dnshawaiijimaritimoduminamimakis-a-knightp" + - "ointtohobby-sitehatogayaitakaokalmykiahatoyamazakitakamiizumisan" + - "ofidelityhatsukaichikaiseiheijis-a-landscaperugiahattfjelldalhay" + - "ashimamotobungotakadagestangeorgeorgiahazuminobusells-for-usrcfa" + - "stlylbamblebesbyglandroverhalla-speziaustinnavigationavoizumizak" + - "ibigawajudaicable-modemocraciabruzzoologicalvinklein-addrammenuo" + - "rochesterimo-i-ranaamesjevuemielno-ipifonyaaarborteaches-yogasaw" + - "aracingdyniaetnabudapest-a-la-masion-riopretobamaceratabuseating" + - "-organic66helsinkitakatakarazukaluganskygearapphiladelphiaareadm" + - "yblogspotrentino-a-adigehembygdsforbundhemneshellaspeziahemsedal" + - "hepforgeherokussldheroyhgtvallee-d-aosteigenhidorahigashiagatsum" + - "agoianiahigashichichibunkyonanaoshimageandsoundandvisionthewifia" + - "tmallorcadaqueshimokawahigashihiroshimanehigashiizumozakitakyush" + - "uaiahigashikagawahigashikagurasoedahigashikawakitaaikitamihamada" + - "higashikurumeetrentino-aadigehigashimatsushimarcheapigeelvinckdd" + - "iethnologyhigashimatsuyamakitaakitadaitoigawahigashimurayamamoto" + - "rcycleshimokitayamahigashinarusells-itrentino-alto-adigehigashin" + - "ehigashiomihachimanagementrentino-altoadigehigashiosakasayamanak" + - "akogawahigashishirakawamatakasagoppdalhigashisumiyoshikawaminami" + - "aikitamotosumy-gatewayhigashitsunoshiroomurahigashiurausukitanak" + - "agusukumodernhigashiyamatokoriyamanashiibahccavuotnagareyamainte" + - "nancehigashiyodogawahigashiyoshinogaris-a-lawyerhiraizumisatohno" + - "shoooshikamaishimofusartshimonitayanagithubusercontentrentino-s-" + - "tirolhirakatashinagawahiranairtrafficplexus-1hirarahiratsukagawa" + - "hirayaizuwakamatsubushikusakadogawahistorichouseshimonosekikawah" + - "itachiomiyagildeskaliszhitachiotagotembaixadahitraeumtgeradelmen" + - "horstalbanshimosuwalkis-a-liberalhjartdalhjelmelandholeckodairah" + - "olidayhomeiphilatelyhomelinkitoolsztynsettlershimotsukehomelinux" + - "n--1qqw23ahomeofficehomesecuritymacaparecidahomesecuritypchristm" + - "aseratiresandvikcoromantovalle-d-aostatic-accessanfranciscofreak" + - "unemurorangehirnrtoyotomiyazakinzais-a-candidatehomesenseeringho" + - "meunixn--2m4a15ehondahongotpantheonsitehonjyoitakasakitashiobara" + - "hornindalhorsellsyourhomegoodshimotsumahorteneis-a-libertarianho" + - "spitalhoteleshinichinanhotmailhoyangerhoylandetroitskypehumaniti" + - "eshinjournalismailillesandefjordhurdalhurumajis-a-linux-useranis" + - "hiaritabashikaoirminamiminowahyllestadhyogoris-a-llamarriottrent" + - "ino-stirolhyugawarahyundaiwafuneis-very-badajozis-very-evillagei" + - "s-very-goodyearis-very-niceis-very-sweetpepperis-with-thebandois" + - "leofmanaustdaljevnakershuscultureggioemiliaromagnamsskoganeis-a-" + - "nascarfanjewelryjewishartgalleryjfkharkivalleedaostejgorajlljls-" + - "sto1jmphotographysiojnjcphonefosshintomikasaharajoyentrentino-su" + - "edtiroljoyokaichibajddarchitecturealtorlandjpnjprshiojirishirifu" + - "jiedajurkosherbrookegawakoshimizumakizunokunimimatakayamarylandk" + - "oshunantankhersonkosugekotohiradomainsurehabmerkotourakouhokutam" + - "akis-a-patsfankounosupplieshirakokaminokawanishiaizubangekouyama" + - "shikekouzushimashikis-a-personaltrainerkozagawakozakis-a-photogr" + - "apherokuapphilipsyno-dshinjukumanowtvalleeaosteinkjerusalembroid" + - "erykozowindmillkpnkppspdnshiranukamitsuekrasnikahokutokashikis-a" + - "-playershifteditchyouriphoenixn--2scrj9chromedicaltanissettaishi" + - "nomakinkobeardubaiduckdnsangokrasnodarkredstonekristiansandcatsh" + - "iraois-a-republicancerresearchaeologicaliforniakristiansundkrods" + - "heradkrokstadelvaldaostarostwodzislawindowskrakowinnershiraokamo" + - "gawakryminamioguni5kumatorinokumejimasoykumenantokigawakunisakis" + - "-a-rockstarachowicekunitachiarailwaykunitomigusukumamotoyamashik" + - "okuchuokunneppubtlshiratakahagitlaborkunstsammlungkunstunddesign" + - "kuokgroupilotshishikuis-a-socialistdlibestadkureisenkurgankurobe" + - "laudibleasingleshisognekurogiminamiashigarakuroisoftwarezzokurom" + - "atsunais-a-soxfankurotakikawasakis-a-studentalkushirogawakustana" + - "is-a-teacherkassyncloudkusupplykutchanelkutnokuzumakis-a-techiet" + - "is-a-musiciankvafjordkvalsundkvamlidlugolekadenagaivuotnagaokaky" + - "otambabyenebakkeshibechambagriculturennebudejjuedischesapeakebay" + - "ernukvanangenkvinesdalkvinnheradkviteseidatingkvitsoykwpspectrum" + - "inamisanrikubetsurfastvps-serveronakasatsunairguardiannakadomari" + - "nebraskauniversitychyattorneyagawakembuchikumagayagawakkanaibets" + - "ubamericanfamilydsclouderackmazerbaijan-mayen-rootaribeiraogashi" + - "madachicagoboatsassaris-a-conservativegarsheis-a-cpadualstackher" + - "o-networkinggroupassenger-associationkzmissileluxembourgmisugito" + - "kuyamatsumotofukemitourismolanxesshitaramamitoyoakemiuramiyazure" + - "websiteshikagamiishibukawamiyotamanomjondalenmlbfanmontrealestat" + - "efarmequipmentrentinoa-adigemonza-brianzapposhizukuishimogosenmo" + - "nza-e-della-brianzaptokyotangotsukitahatakamoriokakegawamonzabri" + - "anzaramonzaebrianzamonzaedellabrianzamoonscaleforcemordoviamoriy" + - "amatsunomoriyoshiminamiawajikis-an-actormormonstermoroyamatsusak" + - "ahoginankokubunjis-an-actresshinshinotsurgerymortgagemoscowioshi" + - "zuokanagawamoseushistorymosjoenmoskeneshoppingmosshopwarendalenu" + - "gmosvikhmelnytskyivaomoteginowaniihamatamakawajimansionshoujis-a" + - "n-anarchistoricalsocietymoviemovimientolgamozilla-iotrentinoaadi" + - "gemtranbymuenstermuginozawaonsenmuikamisatokaizukamikitayamatsur" + - "is-an-artistgorymukoebenhavnmulhouseoullensvanguardmunakatanemun" + - "cienciamuosattemupimientakkoelnmurmanskhplaystation-cloudmurotor" + - "craftrentinoalto-adigemusashimurayamatsushigemusashinoharamuseet" + - "rentinoaltoadigemuseumverenigingmusicargodaddyn-vpndnshowamutsuz" + - "awamy-vigorgemy-wanggouvichungnamdalseidfjordyndns-mailubindalub" + - "lindesnesanjotoyotsukaidomyactivedirectorymyasustor-elvdalmycdn7" + - "7-sslattuminamitanemydattolocalhistorymyddnskingmydissentrentino" + - "s-tirolmydobisshikis-an-engineeringmydroboehringerikemydshowtime" + - "lhusdecorativeartshriramsterdamnserverbaniamyeffectrentinostirol" + - "myfastly-terrariuminamiuonumasudamyfirewallonieruchomoscienceand" + - "industrynmyforuminamiyamashirokawanabelembetsukubankhmelnitskiya" + - "marumorimachidamyfritzmyftpaccesshwitdklabudhabikinokawabarthads" + - "electrentin-suedtirolmyhome-servermyjinomykolaivaporcloudmymaile" + - "rmymediapchurcharternidyndns-office-on-the-webhareidsbergentingr" + - "ongausdalucaniamyokohamamatsudamypepinkmpspbarclays3-sa-east-1my" + - "petsienarviikamishihoronobeauxartsandcraftsigdalmyphotoshibalati" + - "nogiftsilknx-serversailleshioyandexcloudmypictetrentinosud-tirol" + - "mypsxn--32vp30haebaruericssongdalenviknakayamaoris-a-geekautokei" + - "notteroymysecuritycamerakermyshopblocksimple-urlmytis-a-bookkeep" + - "erspectakasugais-an-entertainermytuleaprendemasakikonaikawachina" + - "ganoharamcoachampionshiphoptobishimadridvagsoygardendoftheintern" + - "etlifyis-bytomaritimekeepingmyvncircustomer-ociprianiigataitogit" + - "suldaluccarbonia-iglesias-carboniaiglesiascarboniamywirepbodynam" + - "ic-dnsirdalplatformshangrilapyplatter-appioneerplatterpippugliap" + - "lazaplcube-serversicherungplumbingoplurinacionalpodhalevangerpod" + - "lasiellaktyubinskiptveterinaireadthedocscappgafannefrankfurtrent" + - "inosudtirolpodzonepohlpoivronpokerpokrovskomakiyosunndalpolitica" + - "rrierpolitiendapolkowicepoltavalle-aostathellewismillerpomorzesz" + - "owithgoogleapiszponpesaro-urbino-pesarourbinopesaromasvuotnaroyp" + - "onypordenonepornporsangerporsangugeporsgrunnanyokoshibahikariwan" + - "umatamayufuelveruminanopoznanpraxis-a-bruinsfanprdpreservationpr" + - "esidioprgmrprimelbourneprincipeprivatizehealthinsuranceprofesion" + - "alprogressivenneslaskerrylogisticslupskomatsushimarylhurstjordal" + - "shalsenpromombetsurgeonshalloffameiwamassa-carrara-massacarraram" + - "assabusinessebyklecznagasukepropertyprotectionprotonetrentinosue" + - "d-tirolprudentialpruszkowithyoutuberspacekitagatargivestbytemark" + - "omforbarefootballooningjerstadotsuruokakamigaharauthordalandds3-" + - "eu-central-1prvcyberlevagangaviikanonjis-certifieducatorahimeshi" + - "mamateramobaraprzeworskogptplusgardenpulawypupittsburghofficialp" + - "vhagakhanamigawapvtrentinosuedtirolpwcistrondheimmobilienissayok" + - "kaichiropractichitachinakagawassamukawatarightathomeftparocherni" + - "governmentksatxn--12c1fe0bradescorporationrenderpzqhagebostadqld" + - "qponiatowadaqslingqualifioappiwatequickconnectrentinsud-tirolqui" + - "cksytestingquipelementslzqvcitadeliveryggeesusonosuzakanazawasuz" + - "ukaneyamazoesuzukis-into-animegurownprovidersvalbardunloppacific" + - "ivilaviationissedalucernesveiosvelvikomorotsukaminoyamaxunjargas" + - "vizzerasvn-reposologneswidnicasacamdvrcampinagrandebuilderschles" + - "ischesolundbeckommunalforbundswidnikkokonoeswiebodzin-butterswif" + - "tcoverswinoujscienceandhistoryswissmarterthanyousynology-disksta" + - "tionsynology-dsolutionsnoasakakinokiaturystykanmakiwientuscanytu" + - "shuissier-justicetuvalle-daostaticsootuxfamilytwmailvestnesopotr" + - "entinsudtirolvestre-slidreviewsaitoshimayfirstockholmestrandvest" + +const text = "9guacuiababia-goracleaningroks-theatree12hpalermomahachijolstere" + + "trosnubalsfjorddnslivelanddnss3-ap-south-1kappchizip6116-b-datai" + + "ji234lima-cityeatselinogradult3l3p0rtatamotors3-ap-northeast-133" + + "7birkenesoddtangenovaranzaninohekinannestadivttasvuotnakamuratak" + + "ahamalselvendrellimitediyukuhashimojindianapolis-a-bloggerbirthp" + + "lacebjarkoyurihonjournalistjohninomiyakonojorpelandnpanamatta-va" + + "rjjatjeldsundrangedalimoliseminebjerkreimdbamblebesbyglandroverh" + + "alla-speziaustevollaziobihirosakikamijimatsuzakibigawagrocerybni" + + "keisenbahnatuurwetenschappenaumburgdyniabogadobeaemcloud66bjugni" + + "eznord-frontierblackfridayusuharabloombergbauernirasakindianmark" + + "etingjesdalinkyard-cloudyclusterbloxcms3-website-us-west-2blueda" + + "gestangeologyusuisservehumourbmoattachments5yuulmemorialivornoce" + + "anographiquebmsakyotanabellunord-aurdalpha-myqnapcloudaccesscamb" + + "ridgeiseiyoichippubetsubetsugarugbydgoszczecinemagentositechnolo" + + "gyuzawabmweddingjovikariyameinforumzjampagexlombardynaliaskimits" + + "ubatamibugattiffanycateringebuildingladefinimakanegasakirabnrwed" + + "eploybomloabathsbcatholicaxiashorokanaiebondray-dnstracebonnishi" + + "azaindielddanuorrindigenaklodzkodairabookinghostedpictethnologyb" + + "oomlair-traffic-controlleyboschaefflerdalomzaporizhzhegurindustr" + + "iabostikarlsoybostonakijinsekikogentappsselfipanasonichernihivgu" + + "bsalangenishigocelotenkawabotanicalgardenishiharabotanicgardenis" + + "hiizunazukindustriesteamsterdamnserverbaniabotanynysagaeroclubme" + + "decincinnationwidealerbouncemerckmsdnipropetrovskjervoyagets-itj" + + "maxxxboxenapponazure-mobilebounty-fullensakerrypropertiesalondon" + + "etskarmoyboutiquebechernivtsiciliabozen-sudtirolondrinamsskogane" + + "infinitintelligencebozen-suedtirolorenskoglassassinationalherita" + + "gebplacedogawarabikomaezakirunorddalottebrandywinevalleybrasilia" + + "brindisibenikinderoybristoloseyouriparachutingleezebritishcolumb" + + "ialowiezaganishikatakinouebroadcastlebtimnetzlglitchattanooganor" + + "dlandrayddnsfreebox-osascoli-picenordre-landraydnsupdaternopilaw" + + "atchesaltdalottokonamegatakazakinternationalfirearmsaludrivefsni" + + "llfjordrobaknoluoktachikawakuyabukievennodesadoes-itvedestrandru" + + "dupontariobranconakaniikawatanagurabroadwaybroke-itjomeloyalisto" + + "ragebrokerbronnoysundurbanamexhibitionishikatsuragit-reposalvado" + + "rdalibabalena-devicesalzburgliwicebrothermesaverdealstahaugesund" + + "erseaportsinfolldalouvreisenishikawazukamisunagawabrowsersafetym" + + "arketsamegawabrumunddalowiczest-le-patronishimerabrunelastxfinit" + + "ybrusselsamnangerbruxellesampalacebryansklepparaglidinglobalasho" + + "vhachinohedmarkarpaczeladzparisor-fronishinomiyashironocparliame" + + "ntjxjavald-aostarnbergloboavistanbulsan-sudtirolpusercontentkmax" + + "xn--0trq7p7nnishinoomotegoddabrynewhollandurhamburglogowegroweib" + + "olognagareyamakeupowiathletajimabaridagawalbrzycharitydalaskanit" + + "tedallasalleangaviikaascolipicenodumemsettsupportksatxn--11b4c3d" + + "ynathomebuiltwithdarkaruizawabuskerudinewjerseybuzentsujiiebuzzw" + + "eirbwellbeingzonebzhitomirumalatvuopmicrolightingloppenzaolbia-t" + + "empio-olbiatempioolbialystokkepnogatagajobojintuitmparmattelekom" + + "munikationishinoshimatsuurabzzcolumbusheycommunexus-2community-p" + + "rochowicecomoarekecomparemarkerryhotelsaobernardocompute-1comput" + + "erhistoryofscience-fictioncomsecuritytacticsxn--12cfi8ixb8luxury" + + "condoshichinohealth-carereformitakeharaconferenceconstructioncon" + + "suladonnagatorodoyconsultanthropologyconsultingrondarcontactozsd" + + "eltajirittogliattis-a-chefashioncontagematsubaracontemporaryarte" + + "ducationalchikugodontexistmein-iservebeercontractorskenconventur" + + "eshinodearthruherecipescaravantaacookingchannelsdvrdnsdojoburgro" + + "ngausdaluzerncoolvivanovoldacooperativano-frankivskolefrakkestad" + + "yndns1copenhagencyclopedichitosetogakushimotoganewspapercoproduc" + + "tionsaogoncartoonartdecologiacorporationcorsicagliaricoharuovatm" + + "allorcadaquesaotomeldalcorvettemasekashiwazakiyosemitecosenzakop" + + "anelblagrarchaeologyeongbuk0cosidnsfor-better-thanawassamukawata" + + "rikuzentakatajimidorissagamiharacostumedicinaharimalopolskanland" + + "ynnsapporocouchpotatofriesardegnaroycouklugsmilegallocus-3counci" + + "lcouponsardiniacozoracq-acranbrookuwanalyticsarlcrdynservebbsarp" + + "sborgrossetouchihayaakasakawaharacreditcardynulvikasserversaille" + + "sarufutsunomiyawakasaikaitakofuefukihaboromskogroundhandlingrozn" + + "ycreditunioncremonashgabadaddjaguarqcxn--12co0c3b4evalleaostavan" + + "gercrewiencricketrzyncrimeast-kazakhstanangercrotonecrownipartsa" + + "sayamacrsvpartycruisesasebofageometre-experts-comptablesaskatche" + + "wancryptonomichigangwoncuisinellajollamericanexpressexyculturalc" + + "entertainmentrani-andria-barletta-trani-andriacuneocupcakecuriti" + + "backyardsassaris-a-conservativegarsheis-a-cpadualstackhero-netwo" + + "rkinggroupasadenarashinocurvalled-aostaverncymrussiacyonabarumet" + + "lifeinsurancecyouthachiojiyaitakanezawafetsundyroyrvikingrpassag" + + "ensaudafguidegreefhvalerfidoomdnsiskinkyotobetsulikes-piedmontic" + + "ellodingenfieldfigueresinstaginguitarsavonarusawafilateliafilege" + + "ar-audnedalnfilegear-deatnunusualpersonfilegear-gbizfilegear-ief" + + "ilegear-jpmorganfilegear-sgujoinvilleitungsenfilminamiechizenfin" + + "alfinancefineartsaxofinlandfinnoyfirebaseappassenger-association" + + "firenetranoyfirenzefirestonefirmdalegoldpoint2thisamitsukefishin" + + "golffanschoenbrunnfitjarvodkafjordvalledaostargetmyiphostre-tote" + + "ndofinternet-dnschokokekschokoladenfitnessettlementransportefjal" + + "erflesbergulenflickragerogerscholarshipschoolschulezajskasuyanai" + + "zunzenflightschulserverflirfloginlinefloraflorencefloridatsunanj" + + "oetsuwanouchikujogaszkolancashirecreationfloripaderbornfloristan" + + "ohatakaharuslivinghistoryflorokunohealthcareerschwarzgwangjunipe" + + "rflowerschweizfltransurlflynnhosting-clusterfndfor-ourfor-somedi" + + "zinhistorischesciencecentersciencehistoryfor-theaterforexrothach" + + "irogatakaokalmykiaforgotdnscientistordalforli-cesena-forlicesena" + + "forlillehammerfeste-ipatriaforsaleikangerforsandasuologoipavianc" + + "arrdfortalfortmissoulancasterfortworthadanorthwesternmutualfosne" + + "scjohnsonfotaruis-a-democratrapaniizafoxfordebianfozfredrikstadt" + + "vscrapper-sitefreeddnsgeekgalaxyfreedesktopensocialfreemasonryfr" + + "eesitexaskoyabearalvahkikuchikuseikarugalsaceofreetlscrappingunm" + + "anxn--1ctwolominamatarnobrzegyptianfreiburguovdageaidnusrcfastly" + + "lbananarepublicaseihicampobassociatest-iservecounterstrikehimeji" + + "itatebayashijonawatempresashibetsukuiiyamanouchikuhokuryugasakit" + + "auraustinnaval-d-aosta-valleyokosukanumazuryokoteastcoastaldefen" + + "ceatonsbergivingjemnes3-eu-central-1freseniuscountryestateofdela" + + "wareggio-calabriafribourgushikamifuranorth-kazakhstanfriuli-v-gi" + + "uliafriuli-ve-giuliafriuli-vegiuliafriuli-venezia-giuliafriuli-v" + + "eneziagiuliafriuli-vgiuliafriuliv-giuliafriulive-giuliafriuliveg" + + "iuliafriulivenezia-giuliafriuliveneziagiuliafriulivgiuliafrlfrog" + + "anscrysechocolatelemarkarumaifarsundyndns-homednsamsungmodelling" + + "mxn--12c1fe0bradescotlandyndns-iparochernigovernmentoyotaparsand" + + "nessjoenishiokoppegardyndns-mailubindalublindesnesandoyfrognfrol" + + "andfrom-akrehamnfrom-alfrom-arfrom-azfrom-capetownnews-stagingwi" + + "ddleksvikaszubyfrom-coffeedbackplaneapplinzis-a-designerfrom-ctr" + + "avelchannelfrom-dchofunatoriginstitutelevisionthewifiatoyotomiya" + + "zakinuyamashinatsukigatakashimarnardalucaniafrom-dedyn-berlincol" + + "nfrom-flanderserveirchonanbulsan-suedtiroluccarbonia-iglesias-ca" + + "rboniaiglesiascarboniafrom-gaulardalfrom-hichisochildrensgardenf" + + "rom-iafrom-idfrom-ilfrom-in-brbar0emmafann-arboretumbriamallamac" + + "eiobbcg12038from-kserveminecraftravelersinsurancefrom-kyowariasa" + + "hikawawiiheyakumoduminamifuranofrom-lanciafrom-mamurogawafrom-md" + + "from-meeresistancefrom-mifunefrom-mnfrom-modalenfrom-mservemp3fr" + + "om-mtnfrom-nctulangevagrigentomologyeonggiehtavuoatnabudapest-a-" + + "la-masion-riopretobamaceratabuseating-organichoseiroumuenchenish" + + "itosashimizunaminamibosogndalucernefrom-ndfrom-nefrom-nh-servebl" + + "ogsiteleafamilycompanyanagawafflecellclaimservep2pfizerfrom-njaw" + + "orznoticiasnesoddenmarkhangelskjakdnepropetrovskiervaapsteiermar" + + "katowicefrom-nminamiiserniafrom-nvallee-aosteroyfrom-nyfrom-ohku" + + "rafrom-oketogurafrom-orfrom-padovaksdalfrom-pratohmandalfrom-ris" + + "-a-doctorayfrom-schmidtre-gauldalfrom-sdfrom-tnfrom-txn--1lqs03n" + + "from-utsiracusaikisarazurecontainerdpolicefrom-val-daostavalleyf" + + "rom-vtrdfrom-wafrom-wiardwebhostingxn--1lqs71dfrom-wvallee-d-aos" + + "teigenfrom-wyfrosinonefrostalowa-wolawafroyahooguyfstcgroupgfogg" + + "iafujiiderafujikawaguchikonefujiminokamoenairguardiannakadomarin" + + "ebraskauniversitychyattorneyagawakembuchikumagayagawakkanaibetsu" + + "bamericanfamilydsclouderackmazerbaijan-mayen-rootaribeiraogashim" + + "adachicagoboatservepicservequakefujinomiyadattowebcampinashikimi" + + "nohostfoldnavyfujiokayamangonohejis-a-financialadvisor-aurdalfuj" + + "isatoshonairlinedre-eikerfujisawafujishiroishidakabiratoridefens" + + "eljordfujitsurugashimangyshlakasamatsudopaasiafujixeroxn--1qqw23" + + "afujiyoshidavvenjargap-northeast-3fukayabeatservesarcasmatartand" + + "designfukuchiyamadavvesiidappnodebalancertificationfukudomigawaf" + + "ukuis-a-geekatsushikabeeldengeluidfukumitsubishigakishiwadazaifu" + + "daigojomedio-campidano-mediocampidanomediofukuokazakisofukushima" + + "niwakuratextileirfjordfukuroishikarikaturindalfukusakisosakitaga" + + "wafukuyamagatakahatakaishimoichinosekigaharafunabashiriuchinadaf" + + "unagatakamatsukawafunahashikamiamakusatsumasendaisennangooglecod" + + "espotrentin-sud-tirolfundaciofunkfeuerfuoiskujukuriyamannore-og-" + + "uvdalfuosskoczowildlifedorainfracloudfrontdoorfurnitureggio-emil" + + "ia-romagnakasatsunairportland-4-salernoboribetsuckservicesevasto" + + "polefurubirafurudonostiaafurukawairtelebitbridgestonekobayashiks" + + "hacknetcimbar1fusodegaurafussaintlouis-a-anarchistoireggiocalabr" + + "iafutabayamaguchinomihachimanagementrentin-sudtirolfutboldlygoin" + + "gnowhere-for-morenakatombetsumitakagiizefuttsurugimperiafuturecm" + + "sevenassisicilyfuturehostingfuturemailingfvgfyresdalhangoutsyste" + + "mscloudhannanmokuizumodenakayamapartmentsharpharmacienshawaiijim" + + "aritimoldeloittemp-dnshellaspeziahannosegawahanyuzenhapmircloudh" + + "arstadharvestcelebrationhasamarburghasaminami-alpshimokawahashba" + + "nghasudahasura-appharmacyshimokitayamahasvikatsuyamarugame-hosty" + + "hostinghatogayaizuwakamatsubushikusakadogawahatoyamazakitakamiiz" + + "umisanofidelityhatsukaichikaiseiheijis-a-landscaperugiahattfjell" + + "dalhayashimamotobungotakadancehazuminobusells-for-utwentehelsink" + + "itakatakarazukaluganskygearapphdfcbankaufenhembygdsforbundhemnes" + + "himonitayanagithubusercontentrentin-suedtirolhemsedalhepforgeher" + + "okusslattuminamiizukaminoyamaxunjargaheroyhgtvalleeaosteinkjerus" + + "alembroideryhidorahigashiagatsumagoianiahigashichichibunkyonanao" + + "shimageandsoundandvisionrenderhigashihiroshimanehigashiizumozaki" + + "takyushuaiahigashikagawahigashikagurasoedahigashikawakitaaikitam" + + "ihamadahigashikurumeetrentino-a-adigehigashimatsushimarcheapigee" + + "lvinckautokeinotteroyhigashimatsuyamakitaakitadaitoigawahigashim" + + "urayamamotorcycleshimonosekikawahigashinarusells-itrentino-aadig" + + "ehigashinehigashiomitamamurausukitamotosumy-gatewayhigashiosakas" + + "ayamanakakogawahigashishirakawamatakasagopocznorfolkebibleirvika" + + "zoologyhigashisumiyoshikawaminamiaikitanakagusukumodernhigashits" + + "unoshiroomurahigashiurawa-mazowszexnetrentino-alto-adigehigashiy" + + "amatokoriyamanashiibahccavuotnagaraholtaleniwaizumiotsukumiyamaz" + + "onawsmpplanetariuminamimakis-a-lawyerhigashiyodogawahigashiyoshi" + + "nogaris-a-liberalhiraizumisatohnoshoooshikamaishimofusartshimosu" + + "walkis-a-libertarianhirakatashinagawahiranairtrafficplexus-1hira" + + "rahiratsukagawahirayakagehistorichouseshimotsukehitachiomiyagild" + + "eskaliszhitachiotagotembaixadahitraeumtgeradelmenhorstalbanshimo" + + "tsumahjartdalhjelmelandholeckochikushinonsenergyholidayhomegoods" + + "hinichinanhomeiphiladelphiaareadmyblogspotrentino-altoadigehomel" + + "inkitoolsztynsettlershinjournalismailillesandefjordhomelinuxn--2" + + "m4a15ehomeofficehomesecuritymacaparecidahomesecuritypchoshibuyac" + + "htsandvikcoromantovalle-d-aostatic-accessanfranciscofreakunemuro" + + "rangehirnrtoyotsukaidohtawaramotoineppueblockbustermezhomesensee" + + "ringhomeunixn--2scrj9choyodobashichikashukujitawarahondahongotpa" + + "ntheonsitehonjyoitakasakitashiobarahornindalhorsellsyourhomeftph" + + "ilatelyhorteneis-a-linux-useranishiaritabashikaoirminamiminowaho" + + "spitalhoteleshinjukumanowtvalleedaostehotmailhoyangerhoylandetro" + + "itskypehumanitieshinkamigotoyohashimototalhurdalhurumajis-a-llam" + + "arriottrentino-s-tirolhyllestadhyogoris-a-musicianhyugawarahyund" + + "aiwafuneis-very-evillageis-very-goodyearis-very-niceis-very-swee" + + "tpepperis-with-thebandownloadisleofmanaustdaljetztrentino-sudtir" + + "oljevnakershuscultureggioemiliaromagnamsosnowiechristiansburgret" + + "akanabeautysvardoesntexisteingeekasaokamikoaniikappuboliviajessh" + + "eimpertrixcdn77-ssldyndns-office-on-the-weberjewelryjewishartgal" + + "leryjfkfhappoujgorajlljls-sto1jmphotographysiojnjcloudjiffylkesb" + + "iblackbaudcdn77-securebungoonord-odaljoyentrentino-sued-tiroljoy" + + "okaichibajddarchitecturealtorlandjpnjprshirakokamiminershiranuka" + + "mitsuejurkosakaerodromegallupinbarclaycards3-sa-east-1koseis-a-p" + + "ainteractivegaskvollkosherbrookegawakoshimizumakizunokunimimatak" + + "ayamarylandkoshunantankharkivanylvenicekosugekotohiradomainsureg" + + "ruhostingkotourakouhokutamakis-a-patsfankounosupplieshiraois-a-p" + + "ersonaltrainerkouyamashikekouzushimashikis-a-photographerokuapph" + + "ilipsynology-diskstationkozagawakozakis-a-playershifteditchyouri" + + "phoenixn--30rr7ykozowinbarclays3-us-east-2kpnkppspdnshiraokamoga" + + "wakrasnikahokutokashikis-a-republicancerresearchaeologicaliforni" + + "akrasnodarkredstonekristiansandcatshiratakahagitlaborkristiansun" + + "dkrodsheradkrokstadelvaldaostarostwodzislawindmillkryminamioguni" + + "5kumatorinokumejimasoykumenantokigawakunisakis-a-rockstarachowic" + + "ekunitachiarailwaykunitomigusukumamotoyamashikokuchuokunneppubtl" + + "shishikuis-a-socialistdlibestadkunstsammlungkunstunddesignkuokgr" + + "oupilotshisognekurehabmerkurgankurobelaudibleasingleshisuifuette" + + "rtdasnetzkurogiminamiashigarakuroisoftwarezzokuromatsunais-a-sox" + + "fankurotakikawasakis-a-studentalkushirogawakustanais-a-teacherka" + + "ssyno-dshinshinotsurgerykusupplynxn--3bst00minamisanrikubetsurfa" + + "uskedsmokorsetagayaseralingenoamishirasatogokasells-for-lessauhe" + + "radynv6kutchanelkutnokuzumakis-a-techietis-a-nascarfankvafjordkv" + + "alsundkvamfamberkeleykvanangenkvinesdalkvinnheradkviteseidatingk" + + "vitsoykwpspectruminamitanekzmishimatsumaebashimodatemissileluxem" + + "bourgmisugitokuyamatsumotofukemitourismolanxesshitaramamitoyoake" + + "miuramiyazurewebsiteshikagamiishibukawamiyotamanomjondalenmlbfan" + + "montrealestatefarmequipmentrentinoa-adigemonza-brianzapposhizuku" + + "ishimogosenmonza-e-della-brianzaptokyotangotsukitahatakamoriokak" + + "egawamonzabrianzaramonzaebrianzamonzaedellabrianzamoonscaleforce" + + "mordoviamoriyamatsunomoriyoshiminamiawajikis-an-actormormonsterm" + + "oroyamatsusakahoginankokubunjis-an-actresshintokushimamortgagemo" + + "scowindowskrakowinnershizuokanagawamoseushistorymosjoenmoskenesh" + + "oppingmosshopwarendalenugmosvikhersonmoteginowaniihamatamakawaji" + + "mansionshoujis-an-anarchistoricalsocietymoviemovimientolgamozill" + + "a-iotrentinoaadigemtranbymuenstermuginozawaonsenmuikamiokameokam" + + "akurazakiwakunigamiharumukoebenhavnmulhouseoullensvanguardmunaka" + + "tanemuncienciamuosattemupimientakkoelnmurmanskhmelnitskiyamarumo" + + "rimachidamurotorcraftrentinoalto-adigemusashimurayamatsushigemus" + + "ashinoharamuseetrentinoaltoadigemuseumverenigingmusicargodaddyn-" + + "vpndnshowamutsuzawamy-vigorgemy-wanggouvichristmaseratiresangomu" + + "tashinainvestmentsanjotoyouramyactivedirectorymyasustor-elvdalmy" + + "cdmydattolocalhistorymyddnskingmydissentrentinos-tirolmydobisshi" + + "kis-an-artistgorymydroboehringerikemydshowtimelhusdecorativearts" + + "hriramlidlugolekadenagahamaroygardendoftheinternetlifyis-an-engi" + + "neeringmyeffectrentinostirolmyfastly-terrariuminamiuonumasudamyf" + + "irewallonieruchomoscienceandindustrynmyforuminamiyamashirokawana" + + "belembetsukubankharkovaomyfritzmyftpaccesshwiosienarutomobellevu" + + "elosangelesjabbottrentinosud-tirolmyhome-servermyjinomykolaivare" + + "servehalflifestylemymailermymediapchromedicaltanissettaishinomak" + + "inkobeardubaiduckdnsannanishiwakinzais-a-candidatemyokohamamatsu" + + "damypepinkhmelnytskyivaporcloudmypetsigdalmyphotoshibalatinogift" + + "silkhplaystation-cloudmypicturesimple-urlmypsxn--3ds443gmysecuri" + + "tycamerakermyshopblocksirdalmythic-beastsjcbnpparibaselburgmytis" + + "-a-bookkeeperspectakasugais-an-entertainermytuleaprendemasakikon" + + "aikawachinaganoharamcoachampionshiphoptobishimadridvagsoyermyvnc" + + "hungnamdalseidfjordyndns-picsannohelplfinancialukowhalingrimstad" + + "yndns-remotewdyndns-serverisignissandiegomywirepaircraftingvollo" + + "mbardiamondslupsklabudhabikinokawabarthadselectrentin-sued-tirol" + + "platformshangrilapyplatter-appioneerplatterpippugliaplazaplcube-" + + "serverplumbingoplurinacionalpodhalevangerpodlasiellaktyubinskipt" + + "veterinaireadthedocscappgafannefrankfurtrentinosudtirolpodzonepo" + + "hlpoivronpokerpokrovsknx-serversicherungpoliticarrierpolitiendap" + + "olkowicepoltavalle-aostathellewismillerpomorzeszowitdkomaganepon" + + "pesaro-urbino-pesarourbinopesaromasvuotnaritakurashikis-bytomari" + + "timekeepingponypordenonepornporsangerporsangugeporsgrunnanyokosh" + + "ibahikariwanumatamayufuelveruminanopoznanpraxis-a-bruinsfanprdpr" + + "eservationpresidioprgmrprimelbourneprincipeprivatizehealthinsura" + + "nceprofesionalprogressivenneslaskerrylogisticsnoasakakinokiaprom" + + "ombetsurgeonshalloffameiwamassa-carrara-massacarraramassabusines" + + "sebykleclerchurcharternidyndns-webhareidsbergentingripepropertyp" + + "rotectionprotonetrentinosued-tirolprudentialpruszkowithgoogleapi" + + "szprvcyberlevagangaviikanonjis-certifieducatorahimeshimamateramo" + + "baraprzeworskogptplusgardenpulawypupittsburghofficialpvhagakhana" + + "migawapvtrentinosuedtirolpwcircustomer-ociprianiigataitogitsulda" + + "luroypzqhagebostadqldqponiatowadaqslingqualifioappiwatequickconn" + + "ectrentinsud-tirolquicksytestingquipelementsokananiimihoboleslaw" + + "iecistrondheimmobilienissayokkaichiropractichernovtsyncloudyndns" + + "-at-homedepotenzamamidsundyndns-at-workisboringlugmbhartipscbgmi" + + "nakamichiharaqvcitadeliveryggeesusonosuzakanazawasuzukaneyamazoe" + + "suzukis-into-animegurownprovidersvalbardunloppacificitichirurgie" + + "ns-dentistes-en-francesvcivilaviationissedalutskashibatakatsukiy" + + "osatokamachintaifun-dnsaliasanokashiharasveiosvelvikommunalforbu" + + "ndsvizzerasvn-reposolutionsokndalswidnicasacamdvrcampinagrandebu" + + "ilderschlesischesomaswidnikkokonoeswiebodzin-butterswiftcoverswi" + + "noujscienceandhistoryswissmarterthanyousynology-dsomnarviikamisa" + + "tokaizukameyamatotakadatuscanytushuissier-justicetuvalle-daostat" + + "icsor-varangertuxfamilytwmailvestre-slidreportrevisohughesoovest" + "re-totennishiawakuravestvagoyvevelstadvibo-valentiavibovalentiav" + - "ideovillasor-odalvinnicasadelamonedancevinnytsiavipsinaappixolin" + - "ovirginiavirtual-userveftpizzavirtualservervirtualuservegame-ser" + - "vervirtueeldomein-vigorlicevirtuelvisakegawaviterboknowsitallviv" + - "olkenkundenvixn--3bst00miniservervlaanderenvladikavkazimierz-dol" + - "nyvladimirvlogintoyonezawavminnesotaketaketomisatokorozawavologd" + - "anskongsbergvolvolkswagentsor-varangervolyngdalvoorloperaunitero" + - "is-into-carshinshirovossevangenvotevotingvotoyonowmflabsorfoldwn" + - "extdirectroandinosaureplantationworldworse-thandawowiwatsukiyono" + - "tairestaurantritonwpdevcloudwritesthisblogsytewroclawloclawekong" + - "svingerwtcminterepaircraftingvollombardiamondshisuifuettertdasne" + - "tzwtfauskedsmokorsetagayaseralingenoamishirasatogokasells-for-le" + - "ssaudawuozuwzmiuwajimaxn--42c2d9axn--45br5cylxn--45brj9civilizat" + - "ionxn--45q11civilwarmiastagets-itoyouraxn--4gbriminingxn--4it168" + - "dxn--4it797konskowolayangroupictureshirahamatonbetsurnadalxn--4p" + - "vxs4allxn--54b7fta0cclanbibaidarmeniaxn--55qw42gxn--55qx5dxn--5j" + - "s045dxn--5rtp49cldmailovecollegefantasyleaguernseyxn--5rtq34kons" + - "ulatrobeepilepsykkylvenetodayxn--5su34j936bgsgxn--5tzm5gxn--6btw" + - "5axn--6frz82gxn--6orx2rxn--6qq986b3xlxn--7t0a264clic20001wwwhosw" + - "hokksundyndns-picsannohelplfinancialukowiiheyakagexn--80adxhksor" + - "ocabalestrandabergamo-siemensncfdxn--80ao21axn--80aqecdr1axn--80" + - "asehdbarreauction-webhostingjesdalillyolasitemrxn--80aswgxn--80a" + - "ugustowmcloudxn--8ltr62konyvelolipopiemontexn--8pvr4uxn--8y0a063" + - "axn--90a3academiamicaarpkomaganexn--90aeroportalabamagasakishima" + - "baraogakibichuoxn--90aishobarakawagoexn--90azhytomyravendbarrel-" + - "of-knowledgeapplicationcloudappspotagerxn--9dbhblg6digitalxn--9d" + - "bq2axn--9et52uxn--9krt00axn--andy-iraxn--aroport-byaotsurreyxn--" + - "asky-iraxn--aurskog-hland-jnbarrell-of-knowledgestackarasjokaras" + - "uyamarshallstatebankarateu-1xn--avery-yuasakuhokkaidownloadxn--b" + - "-5gaxn--b4w605ferdxn--balsan-sdtirol-nsbsorreisahayakawakamiichi" + - "kawamisatottoris-foundationxn--bck1b9a5dre4clickashiwazakiyosemi" + - "texn--bdddj-mrabdxn--bearalvhki-y4axn--berlevg-jxaxn--bhcavuotna" + - "-s4axn--bhccavuotna-k7axn--bidr-5nachikatsuuraxn--bievt-0qa2xn--" + - "bjarky-fyasakaiminatoyookaniepcexn--bjddar-ptarumizusawaxn--blt-" + - "elabourxn--bmlo-graingerxn--bod-2nativeamericanantiquesortlandxn" + - "--bozen-sdtirol-2obanazawaxn--brnny-wuacademy-firewall-gatewayxn" + - "--brnnysund-m8accident-investigation-aptibleadpagest-mon-blogueu" + - "rovision-k3sorumincomcastresindevicenzaporizhzhiaxn--brum-voagat" + - "rogstadxn--btsfjord-9zaxn--bulsan-sdtirol-nsbarsycenterprisesaki" + - "kugawaltervistaikimobetsuitainaioirasebastopologyeongnamegawakay" + - "amagazineat-urlimanowarudautomotiveconomiasakuchinotsuchiurakawa" + - "lesundeportevadsobetsumidatlanticaseihicampobassociatest-iservec" + - "ounterstrikebinagisoccertmgrazimutheworkpccwebredirectmembers3-e" + - "u-west-1xn--c1avgxn--c2br7gxn--c3s14misakis-a-therapistoiaxn--cc" + - "k2b3barsyonlinewhampshirealtysnes3-us-gov-west-1xn--cckwcxetdxn-" + - "-cesena-forl-mcbremangerxn--cesenaforl-i8axn--cg4bkis-into-carto" + - "onshintokushimaxn--ciqpnxn--clchc0ea0b2g2a9gcdxn--comunicaes-v6a" + - "2oxn--correios-e-telecomunicaes-ghc29axn--czr694bashkiriautoscan" + - "adaeguambulanceobihirosakikamijimatsuzakibmdevelopmentatsunobira" + - "ukraanghkeymachineustargardd-dnsiskinkyotobetsulikes-piedmontice" + - "llodingenatuurwetenschappenaumburggfarmerseine164-balsfjorddnsli" + - "velanddnss3-ap-southeast-1xn--czrs0tromsakataobaomoriguchiharahk" + - "keravjuegoshikijobservableusercontentrentinsuedtirolxn--czru2dxn" + - "--czrw28basicservercelliguriaveroykenglandgcahcesuoloans3-eu-wes" + - "t-2xn--d1acj3basilicataniavocatanzarowebspacebinordreisa-hockeyn" + - "utazuerichardlikescandyn53utilitiesquare7xn--d1alfaromeoxn--d1at" + - "romsojamisonxn--d5qv7z876clinichocolatelevisionishiokoppegardynd" + - "ns-ipartinuyamashinatsukigatakashimarnardalouvreitoyosatoyokawax" + - "n--davvenjrga-y4axn--djrs72d6uyxn--djty4kooris-a-nursembokukitch" + - "enxn--dnna-grajewolterskluwerxn--drbak-wuaxn--dyry-iraxn--e1a4cl" + - "iniquenoharaxn--eckvdtc9dxn--efvn9soundcastronomy-routerxn--efvy" + - "88haibarakitahiroshimapartmentservicesevastopolexn--ehqz56nxn--e" + - "lqq16hair-surveillancexn--eveni-0qa01gaxn--f6qx53axn--fct429kope" + - "rvikharkovanylvenicexn--fhbeiarnxn--finny-yuaxn--fiq228c5hsouthc" + - "arolinatalxn--fiq64basketballfinanzgoravoues3-eu-west-3xn--fiqs8" + - "southwestfalenxn--fiqz9sowaxn--fjord-lraxn--fjq720axn--fl-ziaxn-" + - "-flor-jraxn--flw351exn--forl-cesena-fcbsspeedpartnersokananiimih" + - "oboleslawiecitichitosetogakushimotoganewportlligatmparsamsclubar" + - "towhalingriwataraidyndns-homednsamsungroks-thisayamanobeokakudam" + - "atsuexn--forlcesena-c8axn--fpcrj9c3dxn--frde-grandrapidspjelkavi" + - "komonowruzhgorodeoxn--frna-woaraisaijosoyrorospreadbettingxn--fr" + - "ya-hraxn--fzc2c9e2clintonoshoesanokasserverrankoshigayameinforum" + - "zxn--fzys8d69uvgmailxn--g2xx48clothingdustdataiwanairforcebetsui" + - "kidsmynasushiobaragusabaejrietisalatinabenonicbcn-north-1xn--gck" + - "r3f0fbsbxn--12co0c3b4evalleaostavangerxn--gecrj9cn-northwest-1xn" + - "--ggaviika-8ya47hakatanortonxn--gildeskl-g0axn--givuotna-8yasugi" + - "vingxn--gjvik-wuaxn--gk3at1exn--gls-elacaixaxn--gmq050is-into-ga" + - "messinazawaxn--gmqw5axn--h-2failxn--h1aeghakodatexn--h2breg3even" + - "espydebergxn--h2brj9c8cngrossetouchihayaakasakawaharaxn--h3cuzk1" + - "discountyxn--hbmer-xqaxn--hcesuolo-7ya35batochiokinoshimakeupowi" + - "at-band-campaniaxaurskog-holandingjemnes3-ap-southeast-2xn--hery" + - "-iraxn--hgebostad-g3axn--hkkinen-5waxn--hmmrfeasta-s4accident-pr" + - "evention-rancherkasydneyxn--hnefoss-q1axn--hobl-iraxn--holtlen-h" + - "xaxn--hpmir-xqaxn--hxt814exn--hyanger-q1axn--hylandet-54axn--i1b" + - "6b1a6a2exn--imr513nxn--indery-fyasuokanoyakumoldeloittenrikuzent" + - "akatajimidorissagamiharaxn--io0a7is-leetrentino-sud-tirolxn--j1a" + - "efbx-osauheradyndns1xn--j1amhakonexn--j6w193gxn--jlq480n2rgxn--j" + - "lq61u9w7batsfjordiscoveryombolzano-altoadigeologyomitanoceanogra" + - "phics3-us-west-1xn--jlster-byatomitamamuraxn--jrpeland-54axn--jv" + - "r189misasaguris-an-accountantshinkamigotoyohashimototalxn--k7yn9" + - "5exn--karmy-yuaxn--kbrq7oxn--kcrx77d1x4axn--kfjord-iuaxn--klbu-w" + - "oaxn--klt787dxn--kltp7dxn--kltx9axn--klty5xn--3ds443gxn--koluokt" + - "a-7ya57hakubahcavuotnagaraholtaleniwaizumiotsukumiyamazonawsmppl" + - "anetariuminamiizukamiokameokameyamatotakadaxn--kprw13dxn--kpry57" + - "dxn--kpu716fbxosavannahgaxn--kput3is-lostrolekamakurazakiwakunig" + - "amiharustkannamilanotogawaxn--krager-gyatsukanraxn--kranghke-b0a" + - "xn--krdsherad-m8axn--krehamn-dxaxn--krjohka-hwab49jdfastpanelbla" + - "grarchaeologyeongbuk0emmafann-arboretumbriamallamaceiobbcg12038x" + - "n--ksnes-uuaxn--kvfjord-nxaxn--kvitsy-fyatsushiroxn--kvnangen-k0" + - "axn--l-1fairwindsrlxn--l1accentureklamborghinikolaeventsrvareser" + - "vehalflifestylexn--laheadju-7yawaraxn--langevg-jxaxn--lcvr32dxn-" + - "-ldingen-q1axn--leagaviika-52bauhausposts-and-telecommunications" + - "3-us-west-2xn--lesund-huaxn--lgbbat1ad8jelasticbeanstalkhakassia" + - "xn--lgrd-poacctrusteexn--lhppi-xqaxn--linds-pramericanartrvargga" + - "trentoyonakagyokutoyakolobrzegersundxn--lns-qlaquilanstorfjordxn" + - "--loabt-0qaxn--lrdal-sraxn--lrenskog-54axn--lt-liacnpyatigorskod" + - "jeffersonxn--lten-granexn--lury-iraxn--m3ch0j3axn--mely-iraxn--m" + - "erker-kuaxn--mgb2ddestorjdevcloudnshinyoshitomiokamitondabayashi" + - "ogamagoriziaxn--mgb9awbfedorapeoplegnicapebretonamicrosoftbankas" + - "uyanaizulminamiechizenxn--mgba3a3ejtrycloudflareportrevisohughes" + - "omaxn--mgba3a4f16axn--mgba3a4franamizuholdingstpetersburgxn--mgb" + - "a7c0bbn0axn--mgbaakc7dvfedoraprojectransportexn--mgbaam7a8hakuis" + - "-a-greenxn--mgbab2bdxn--mgbah1a3hjkrdxn--mgbai9a5eva00beneventoe" + - "idskoguchikuzenayorovigovtaxihuanflfanfshostrowwlkpmgjovikaratsu" + - "ginamikatagamilitaryonagoyaxn--mgbai9azgqp6jelenia-goraxn--mgbay" + - "h7gpaleoxn--mgbbh1a71exn--mgbc0a9azcgxn--mgbca7dzdoxn--mgberp4a5" + - "d4a87gxn--mgberp4a5d4arxn--mgbgu82axn--mgbi4ecexposedxn--mgbpl2f" + - "hskydivingxn--mgbqly7c0a67fbcnsantabarbaraxn--mgbqly7cvafranzisk" + - "anerimaringatlantakahashimamakiryuohdattorelayxn--mgbt3dhdxn--mg" + - "btf8flatangerxn--mgbtx2bentleyonagunicommbankarelianceu-2xn--mgb" + - "x4cd0abbvieeexn--mix082feiraquarelleaseeklogesaves-the-whalessan" + - "dria-trani-barletta-andriatranibarlettaandriaxn--mix891fermochiz" + - "ukirovogradoyxn--mjndalen-64axn--mk0axin-dslgbtrysiljanxn--mk1bu" + - "44cntoystre-slidrettozawaxn--mkru45is-not-certifiedugit-pagespee" + - "dmobilizeroticanonoichinomiyakexn--mlatvuopmi-s4axn--mli-tlarvik" + - "oryokamikawanehonbetsurutaharaxn--mlselv-iuaxn--moreke-juaxn--mo" + - "ri-qsakuragawaxn--mosjen-eyawatahamaxn--mot-tlavagiskexn--mre-og" + - "-romsdal-qqbuserveexchangexn--msy-ula0hakusanagochijiwadell-ogli" + - "astraderxn--mtta-vrjjat-k7aflakstadaokagakicks-assnasaarlandxn--" + - "muost-0qaxn--mxtq1misawaxn--ngbc5azdxn--ngbe9e0axn--ngbrxn--3e0b" + - "707exn--nit225kosaigawaxn--nmesjevuemie-tcbalsan-sudtirollagdene" + - "snaaseinet-freakstreamswatch-and-clockerxn--nnx388axn--nodessaku" + - "rais-savedunetflixilxn--nqv7fs00emaxn--nry-yla5gxn--ntso0iqx3axn" + - "--ntsq17gxn--nttery-byaeservehttplantsjcbnpparibaselburgxn--nvuo" + - "tna-hwaxn--nyqy26axn--o1acheltenham-radio-openairbusantiquest-a-" + - "la-maisondre-landroidxn--o3cw4haldenxn--o3cyx2axn--od0algxn--od0" + - "aq3beppublishproxyzgorzeleccogladefinimakanegasakiraxn--ogbpf8fl" + - "ekkefjordxn--oppegrd-ixaxn--ostery-fyaxn--osyro-wuaxn--otu796dxn" + - "--p1acferraraxn--p1ais-slickfhappoutwentexn--pbt977collectionxn-" + - "-pgbs0dhlxn--porsgu-sta26ferrarivnexn--pssu33lxn--pssy2uxn--q9jy" + - "b4colognewyorkshirecifedexeterxn--qcka1pmckinseyxn--qqqt11miscon" + - "fusedxn--qxa6axn--qxamuneuestudioxn--rady-iraxn--rdal-poaxn--rde" + - "-ulavangenxn--rdy-0nabaris-uberleetrentino-sudtirolxn--rennesy-v" + - "1axn--rhkkervju-01aferrerotikagoshimalvikaszubyxn--rholt-mragowo" + - "odsidemonmouthalsaitamatsukuris-a-guruslivinghistoryxn--rhqv96gx" + - "n--rht27zxn--rht3dxn--rht61exn--risa-5naturalhistorymuseumcenter" + - "xn--risr-iraxn--rland-uuaxn--rlingen-mxaxn--rmskog-byaxn--rny31h" + - "ammarfeastafricapitalonewmexicodyn-o-saurlandesevenassisicilyxn-" + - "-rovu88beskidyn-ip24xn--rros-granvindafjordxn--rskog-uuaxn--rst-" + - "0naturalsciencesnaturellestudynamisches-dnsokndalxn--rsta-franca" + - "iseharaxn--rvc1e0am3exn--ryken-vuaxn--ryrvik-byaxn--s-1faithamur" + - "akamigoris-a-hard-workersewinbarclaycards3-fips-us-gov-west-1xn-" + - "-s9brj9colonialwilliamsburgroundhandlingroznyxn--sandnessjen-ogb" + - "estbuyshouses3-website-ap-northeast-1xn--sandy-yuaxn--sdtirol-n2" + - "axn--seral-lraxn--ses554gxn--sgne-graphoxn--3hcrj9civilisationis" + - "shinguccircleverappsannaniyodogawaxn--skierv-utazastuff-4-salexn" + - "--skjervy-v1axn--skjk-soaxn--sknit-yqaxn--sknland-fxaxn--slat-5n" + - "aturbruksgymnxn--slt-elabcieszynxn--smla-hraxn--smna-gratangentl" + - "entapisa-geekosakaerodromegallupinbargainstantcloudfunctionswede" + - "nvironmentalconservationfabricafederationionjukudoyamaizuruhrhcl" + - "oudiscourses3-us-east-2xn--snase-nraxn--sndre-land-0cbetainaboxf" + - "usejnymemsettsupportcp4xn--snes-poaxn--snsa-roaxn--sr-aurdal-l8a" + - "xn--sr-fron-q1axn--sr-odal-q1axn--sr-varanger-ggbhzcasinordkappa" + - "lmasfjordenhktjeldsundishakotanhlfanhs3-website-ap-southeast-1xn" + - "--srfold-byaxn--srreisa-q1axn--srum-gratis-a-bulls-fanxn--stfold" + - "-9xaxn--stjrdal-s1axn--stjrdalshalsen-sqbieidsvollimitediskussio" + - "nsbereichaseljeepsondriodejaneirockartuzyoriikariyaltakatorin-th" + - "e-bandain-vpncateringebuildinglassassinationalheritageu-3xn--str" + - "e-toten-zcbielawashingtondclkarlsoyoshiokanzakiyokawaraxn--t60b5" + - "6axn--tckweatherchannelxn--tiq49xqyjeonnamerikawauexn--tjme-hrax" + - "n--tn0agrinetbankoseis-a-painteractivegaskvollxn--tnsberg-q1axn-" + - "-tor131oxn--trany-yuaxn--trentin-sd-tirol-rzbiellaakesvuemielecc" + - "eu-4xn--trentin-sdtirol-7vbrplsbxn--3oq18vl8pn36axn--trentino-sd" + - "-tirol-c3bieszczadygeyachimataipeigersundisrechtrainingleezevje-" + - "og-hornnes3-website-ap-southeast-2xn--trentino-sdtirol-szbievath" + - "letajimabaridagawalbrzycharitydalcesurancechirealmpmnikonanporov" + - "noceanographiquextraspace-to-rentalstomakomaibaraxn--trentinosd-" + - "tirol-rzbifukagawashtenawdev-myqnapcloudeitysfjordivtasvuodnakam" + - "agayahabaghdadivttasvuotnakamuratakahamalselvendrellimoliseminex" + - "n--trentinosdtirol-7vbigv-infoodnetworkangerxn--trentinsd-tirol-" + - "6vbihorologyukincheoninohekinannestadiyukuhashimojindianapolis-a" + - "-bloggerxn--trentinsdtirol-nsbikedaejeonbukcoalvdalaheadjudygarl" + - "andnpalmspringsakerxn--trgstad-r1axn--trna-woaxn--troms-zuaxn--t" + - "ysvr-vraxn--uc0atvaroyxn--uc0ay4axn--uist22handsonyoursidellogli" + - "astradingxn--uisz3gxn--unjrga-rtashkentunesomnarvikommunexn--unu" + - "p4yxn--uuwu58axn--vads-jraxn--valle-aoste-ebbtunkomvuxn--30rr7yx" + - "n--valle-d-aoste-ehbodollstufftoread-booksnesolarssonxn--valleao" + - "ste-e7axn--valledaoste-ebbvacationstuttgartrentinsued-tirolxn--v" + - "ard-jraxn--vegrshei-c0axn--vermgensberater-ctbilbaokinawashirosa" + - "tochigiessensiositelemarkarmoyurihonjournalistjohninomiyakonojor" + - "pelandrangedalinkyard-cloudyclusterxn--vermgensberatung-pwbillus" + - "trationredumbrellahppiacenzachpomorskienirasakindianmarketinglit" + - "chattanooganordlandray-dnsupdaternopilawaweddingliwicexn--vestvg" + - "y-ixa6oxn--vg-yiabkhaziaxn--vgan-qoaxn--vgsy-qoa0jetztrentino-su" + - "ed-tirolxn--vgu402coloradoplateaudioxn--vhquvestfoldxn--vler-qoa" + - "xn--vre-eiker-k8axn--vrggt-xqadxn--vry-yla5gxn--vuq861biocpanama" + - "tta-varjjatjmaxxxboxenapponazure-mobilexn--w4r85el8fhu5dnraxn--w" + - "4rs40lxn--wcvs22dxn--wgbh1columbusheyxn--wgbl6axn--xhq521birdart" + - "centerprisecloudcontrolappleborkdalwaysdatabaseballangenkainanae" + - "robatickets3-website-eu-west-1xn--xkc2al3hye2axn--xkc2dl3a5ee0ha" + - "ngglidingxn--y9a3aquariumishimatsumaebashimodatexn--yer-znaturhi" + - "storischesusakis-gonexn--yfro4i67oxn--ygarden-p1axn--ygbi2ammxn-" + - "-3pxu8koninjambylxn--ystre-slidre-ujbirkenesoddtangenovaranzanqu" + - "anpachigasakihokumakogengerdalaskanittedallasalleangaviikaascoli" + - "picenodumetacentrumeteorappanasonicatholicaxiashorokanaiexn--zbx" + - "025dxn--zf0ao64axn--zf0avxlxn--zfr164birthplacexnbayxz" + "ideovillasorocabalestrandabergamo-siemensncfdvinnicasadelamoneda" + + "pliernewportlligatritonvinnytsiavipsinaappixolinovirginiavirtual" + + "-userveftpizzavirtualservervirtualuservegame-servervirtueeldomei" + + "n-vigorlicevirtuelvisakegawaviterboknowsitallvivolkenkundenvixn-" + + "-3hcrj9civilisationisshinguccircleverappsantabarbaravlaanderenvl" + + "adikavkazimierz-dolnyvladimirvlogintoyonezawavminiservervologdan" + + "skomonowruzhgorodeovolvolkswagentsorreisahayakawakamiichikawamis" + + "atottoris-foundationvolyngdalvoorloperauniterois-into-carshintom" + + "ikasaharavossevangenvotevotingvotoyonowmcloudwmflabsortlandwnext" + + "directrogstadworldworse-thandawowithyoutuberspacekitagatargitpag" + + "efrontappkmpspbar2wpdevcloudwpenginepoweredwritesthisblogsytewro" + + "clawiwatsukiyonotairestaurantroandinosaurepbodynamic-dnsopotrent" + + "insudtirolwtcminnesotaketaketomisatokorozawawtfbsbxn--1ck2e1banz" + + "aicloudcontrolledekagaminombresciaustraliajudaicable-modemocraci" + + "abruzzoologicalvinklein-addrammenuorochesterimo-i-rana4u2-localh" + + "ostrowiec66wuozuwzmiuwajimaxn--45q11civilwarmiaxn--4gbriminingxn" + + "--4it168dxn--4it797kongsbergxn--4pvxs4allxn--54b7fta0cclanbibaid" + + "armeniaxn--55qw42gxn--55qx5dxn--5js045dxn--5rtp49cldmailovecolle" + + "gefantasyleaguernseyxn--5rtq34kongsvingerxn--5su34j936bgsgxn--5t" + + "zm5gxn--6btw5axn--6frz82gxn--6orx2rxn--6qq986b3xlxn--7t0a264clic" + + "20001wwwhoswhokksundyndns-wikirkenesantacruzsantafedjejuifmetace" + + "ntrumeteorappartis-a-catererxn--80adxhksorumincomcastresindevice" + + "nzaporizhzhiaxn--80ao21axn--80aqecdr1axn--80asehdbarefootballoon" + + "ingjerdrumckinseyolasiteu-1xn--80aswgxn--80augustowloclawekomoro" + + "tsukaminokawanishiaizubangexn--8ltr62koninjambylxn--8pvr4uxn--8y" + + "0a063axn--90a3academiamicaaarborteaches-yogasawaracingxn--90aero" + + "portalabamagasakishimabaraogakibichuoxn--90aishobarakawagoexn--9" + + "0azhytomyravendbargainstantcloudfunctionswedenvironmentalconserv" + + "ationfabricafederationionjukudoyamaintenanceu-2xn--9dbhblg6digit" + + "alxn--9dbq2axn--9et52uxn--9krt00axn--andy-iraxn--aroport-byaotsu" + + "rreyxn--asky-iraxn--aurskog-hland-jnbarreauction-webhopenairbusa" + + "ntiquest-a-la-maisondre-landroidiscourses3-us-gov-west-1xn--aver" + + "y-yuasakuhokkaidovre-eikerxn--b-5gaxn--b4w605ferdxn--balsan-sdti" + + "rol-nsbsoundcastronomy-routerxn--bck1b9a5dre4clickashiwaraxn--bd" + + "ddj-mrabdxn--bearalvhki-y4axn--berlevg-jxaxn--bhcavuotna-s4axn--" + + "bhccavuotna-k7axn--bidr-5nachikatsuuraxn--bievt-0qa2xn--bjarky-f" + + "yasakaiminatoyookaniepcexn--bjddar-ptarumizusawaxn--blt-elabourx" + + "n--bmlo-graingerxn--bod-2natalxn--bozen-sdtirol-2obanazawaxn--br" + + "nny-wuacademy-firewall-gatewayxn--brnnysund-m8accident-investiga" + + "tion-aptibleadpagest-mon-blogueurovision-k3southcarolinarvikomat" + + "sushimarylhurstjordalshalsenxn--brum-voagatromsakataobaomoriguch" + + "iharahkkeravjuegoshikijobservableusercontentrentoyonakagyokutoya" + + "kolobrzegersundxn--btsfjord-9zaxn--bulsan-sdtirol-nsbarrel-of-kn" + + "owledgeapplicationcloudappspotagerevistaples3-us-west-1xn--c1avg" + + "xn--c2br7gxn--c3s14mintereitrentino-suedtirolxn--cck2b3barrell-o" + + "f-knowledgestack12xn--cckwcxetdxn--cesena-forl-mcbremangerxn--ce" + + "senaforl-i8axn--cg4bkis-into-cartoonshinyoshitomiokamitondabayas" + + "hiogamagoriziaxn--ciqpnxn--clchc0ea0b2g2a9gcdxn--comunicaes-v6a2" + + "oxn--correios-e-telecomunicaes-ghc29axn--czr694barsycenterprises" + + "akimobetsuitainaioirasebastopologyeongnamegawakayamagazineat-url" + + "illyombolzano-altoadigeorgeorgiaustrheimatunduhrennesoyokozebina" + + "gisoccertmgrazimutheworkpccwebredirectmembers3-eu-west-1xn--czrs" + + "0tromsojamisonxn--czru2dxn--czrw28barsyonlinewhampshirealtysnes3" + + "-us-west-2xn--d1acj3bashkiriauthordalandeportenrivnebinordreisa-" + + "hockeynutazuerichardlikescandyn53utilitiesquare7xn--d1alfaromeox" + + "n--d1atrusteexn--d5qv7z876clinichiryukyuragifuchungbukharavennag" + + "asakindlecznagasukexn--davvenjrga-y4axn--djrs72d6uyxn--djty4kons" + + "kowolayangroupiemontexn--dnna-grajewolterskluwerxn--drbak-wuaxn-" + + "-dyry-iraxn--e1a4cliniquenoharaxn--eckvdtc9dxn--efvn9southwestfa" + + "lenxn--efvy88haibarakitahiroshimaoris-a-greenxn--ehqz56nxn--elqq" + + "16hair-surveillancexn--eveni-0qa01gaxn--f6qx53axn--fct429konsula" + + "trobeepilepsykkylvenetodayxn--fhbeiarnxn--finny-yuaxn--fiq228c5h" + + "sowaxn--fiq64basicservercelliguriautomotiveconomiastagemological" + + "lyngenflfanquanpachigasakihokumakogenebakkeshibechambagriculture" + + "nnebudejjuedischesapeakebayernufcfanavigationavoizumizakibmdevel" + + "opmentatsunobiramusementdllpages3-ap-southeast-2ix4432-balsan-su" + + "edtirolkuszczytnoipirangamvik-serverrankoshigayachimataikikugawa" + + "lesundd-dnshome-webserverdal-o-g-i-n4tatarantours3-ap-northeast-" + + "2xn--fiqs8speedpartnersolarssonxn--fiqz9sphinxn--3e0b707exn--fjo" + + "rd-lraxn--fjq720axn--fl-ziaxn--flor-jraxn--flw351exn--forl-cesen" + + "a-fcbsspjelkavikomforbarcelonagawalmartattoolforgemreviewsaitosh" + + "imayfirstockholmestrandgcahcesuoloans3-fips-us-gov-west-1xn--for" + + "lcesena-c8axn--fpcrj9c3dxn--frde-grandrapidspreadbettingxn--frna" + + "-woaraisaijosoyrorospydebergxn--frya-hraxn--fzc2c9e2clintonoshoe" + + "santamariakexn--fzys8d69uvgmailxn--g2xx48clothingdustdataiwanair" + + "forcebetsuikidsmynasushiobaragusabaejrietisalatinabenonicbcn-nor" + + "th-1xn--gckr3f0fbx-ostrowwlkpmgruexn--gecrj9cn-northwest-1xn--gg" + + "aviika-8ya47hakatanortonxn--gildeskl-g0axn--givuotna-8yasugivest" + + "bytemarkonyvelolipoppdalxn--gjvik-wuaxn--gk3at1exn--gls-elacaixa" + + "xn--gmq050is-into-gamessinazawaxn--gmqw5axn--h-2failxn--h1aeghak" + + "odatexn--h2breg3evenesrlxn--h2brj9c8cngriwataraidyndns-workshopi" + + "tsitevadsobetsumidatlantichitachinakagawashtenawdev-myqnapcloude" + + "itysfjordyndns-blogdnsamsclubartowfarmsteadyndns-freeboxosloftoy" + + "osatoyokawaxn--h3cuzk1discountyxn--hbmer-xqaxn--hcesuolo-7ya35ba" + + "silicataniautoscanadaeguambulancechirealmpmnavuotnapleskns3-eu-w" + + "est-2xn--hery-iraxn--hgebostad-g3axn--hkkinen-5waxn--hmmrfeasta-" + + "s4accident-prevention-rancherkasydneyxn--hnefoss-q1axn--hobl-ira" + + "xn--holtlen-hxaxn--hpmir-xqaxn--hxt814exn--hyanger-q1axn--hyland" + + "et-54axn--i1b6b1a6a2exn--imr513nxn--indery-fyasuokanoyaltakatori" + + "s-leetrentino-stirolxn--io0a7is-lostrodawaraxn--j1aefbxosavannah" + + "gaxn--j1amhakonexn--j6w193gxn--jlq480n2rgxn--jlq61u9w7basketball" + + "finanzgoraveroykengerdalces3-eu-west-3xn--jlster-byatominamidait" + + "omanchesterxn--jrpeland-54axn--jvr189misakis-a-therapistoiaxn--k" + + "7yn95exn--karmy-yuaxn--kbrq7oxn--kcrx77d1x4axn--kfjord-iuaxn--kl" + + "bu-woaxn--klt787dxn--kltp7dxn--kltx9axn--klty5xn--3oq18vl8pn36ax" + + "n--koluokta-7ya57hakubahcavuotnagaivuotnagaokakyotambabyenglandx" + + "n--kprw13dxn--kpry57dxn--kput3is-not-certifiedugit-pagespeedmobi" + + "lizeroticanonoichinomiyakexn--krager-gyatsukanraxn--kranghke-b0a" + + "xn--krdsherad-m8axn--krehamn-dxaxn--krjohka-hwab49jdevcloudnshir" + + "ahamatonbetsurnadalxn--ksnes-uuaxn--kvfjord-nxaxn--kvitsy-fyatsu" + + "shiroxn--kvnangen-k0axn--l-1fairwindsrvarggatrentinsued-tirolxn-" + + "-l1accentureklamborghinikolaeventstoregontrailroadxn--laheadju-7" + + "yawaraxn--langevg-jxaxn--lcvr32dxn--ldingen-q1axn--leagaviika-52" + + "batochiokinoshimaizuruhrhcloudiscoveryomitanobninskaracoldwarsza" + + "wavocatanzarowebspacebizenakanojohanamakinoharaukraanghkeymachin" + + "eustargardds3-ca-central-1xn--lesund-huaxn--lgbbat1ad8jdfastvps-" + + "serveronakanotoddenxn--lgrd-poacctrvaroyxn--lhppi-xqaxn--linds-p" + + "ramericanartrycloudflareplantationxn--lns-qlaquilanstorfjordxn--" + + "loabt-0qaxn--lrdal-sraxn--lrenskog-54axn--lt-liacnpyatigorskodje" + + "ffersonxn--lten-granexn--lury-iraxn--m3ch0j3axn--mely-iraxn--mer" + + "ker-kuaxn--mgb2ddestorjcphonefosshioyandexcloudxn--mgb9awbfedora" + + "peoplegnicapebretonamicrosoftbankasukabedzin-berlindasdaburxn--m" + + "gba3a3ejtrysiljanxn--mgba3a4f16axn--mgba3a4franamizuholdingstpet" + + "ersburgxn--mgba7c0bbn0axn--mgbaakc7dvfedoraprojectraniandriabarl" + + "ettatraniandriaxn--mgbaam7a8hakuis-a-gurustkannamilanotogawaxn--" + + "mgbab2bdxn--mgbah1a3hjkrdxn--mgbai9a5eva00batsfjordishakotanayor" + + "ovigovtaxihuanfshostrolekamishihoronobeauxartsandcrafts3-website" + + "-ap-northeast-1xn--mgbai9azgqp6jelasticbeanstalkddietnedalxn--mg" + + "bayh7gpaleoxn--mgbbh1a71exn--mgbc0a9azcgxn--mgbca7dzdoxn--mgberp" + + "4a5d4a87gxn--mgberp4a5d4arxn--mgbgu82axn--mgbi4ecexposedxn--mgbp" + + "l2fhskydivingxn--mgbqly7c0a67fbcnsantoandreamhostersanukis-a-cel" + + "ticsfanxn--mgbqly7cvafranziskanerimaringatlantakahashimamakiryuo" + + "hdattorelayxn--mgbt3dhdxn--mgbtf8flatangerxn--mgbtx2bauhausposts" + + "-and-telecommunications3-website-ap-southeast-1xn--mgbx4cd0abbvi" + + "eeexn--mix082feiraquarelleaseeklogesaveincloudynvpnplus-4xn--mix" + + "891fermochizukirovogradoyxn--mjndalen-64axn--mk0axin-dslgbtuneso" + + "r-odalxn--mk1bu44cntoystre-slidrettozawaxn--mkru45is-savedunetfl" + + "ixilxn--mlatvuopmi-s4axn--mli-tlarvikooris-a-nursembokukitchenxn" + + "--mlselv-iuaxn--moreke-juaxn--mori-qsakuragawaxn--mosjen-eyawata" + + "hamaxn--mot-tlavagiskexn--mre-og-romsdal-qqbuserveexchangexn--ms" + + "y-ula0hakusanagochijiwadell-ogliastraderxn--mtta-vrjjat-k7aflaks" + + "tadaokagakicks-assnasaarlandxn--muost-0qaxn--mxtq1misasaguris-an" + + "-accountantshinshiroxn--ngbc5azdxn--ngbe9e0axn--ngbrxn--3pxu8kom" + + "vuxn--32vp30haebaruericssongdalenviknakatsugawaxn--nit225kopervi" + + "khakassiaxn--nmesjevuemie-tcbalsan-sudtirollagdenesnaaseinet-fre" + + "akstreamswatch-and-clockerxn--nnx388axn--nodessakurais-slickazun" + + "ow-dnshiojirishirifujiedaxn--nqv7fs00emaxn--nry-yla5gxn--ntso0iq" + + "x3axn--ntsq17gxn--nttery-byaeservehttplantslzxn--nvuotna-hwaxn--" + + "nyqy26axn--o1acheltenham-radio-opencraftrainingxn--o3cw4haldenxn" + + "--o3cyx2axn--od0algorithmiasakuchinotsuchiurakawaxn--od0aq3benev" + + "entoeidskoguchikuzenhktcp4xn--ogbpf8flekkefjordxn--oppegrd-ixaxn" + + "--ostery-fyaxn--osyro-wuaxn--otu796dxn--p1acferraraxn--p1ais-ube" + + "rleetrentino-sud-tirolxn--pgbs0dhlxn--porsgu-sta26ferraris-a-cub" + + "icle-slavellinodeobjectsaves-the-whalessandria-trani-barletta-an" + + "driatranibarlettaandriaxn--pssu33lxn--pssy2uxn--q9jyb4collection" + + "xn--qcka1pmcdirxn--qqqt11misawaxn--qxa6axn--qxamuneuestudioxn--r" + + "ady-iraxn--rdal-poaxn--rde-ulavangenxn--rdy-0nabaris-very-badajo" + + "zxn--rennesy-v1axn--rhkkervju-01aferrerotikagoshimalvikasumigaur" + + "ayasudaxn--rholt-mragowoodsidemonmouthalsaitamatsukuris-a-hard-w" + + "orkersewilliamhillxn--rhqv96gxn--rht27zxn--rht3dxn--rht61exn--ri" + + "sa-5nativeamericanantiquestudynamisches-dnsolognexn--risr-iraxn-" + + "-rland-uuaxn--rlingen-mxaxn--rmskog-byaxn--rny31hammarfeastafric" + + "apitalonewmexicodyn-o-saurlandesharis-a-hunterxn--rovu88bentleyo" + + "nagoyavoues3-external-1xn--rros-granvindafjordxn--rskog-uuaxn--r" + + "st-0naturalhistorymuseumcenterxn--rsta-francaiseharaxn--rvc1e0am" + + "3exn--ryken-vuaxn--ryrvik-byaxn--s-1faithamurakamigoris-a-knight" + + "pointtohobby-sitexn--s9brj9colognewyorkshirecifedexeterxn--sandn" + + "essjen-ogbeppublishproxyzgorzeleccogjerstadotsuruokakamigaharaxa" + + "urskog-holandinggfarmerseine164-baltimore-og-romsdalipayboltates" + + "hinanomachimkentateyamaetnaamesjevuemielno-ipifonyaarpalmasfjord" + + "enaturhistorisches3-ap-southeast-1xn--sandy-yuaxn--sdtirol-n2axn" + + "--seral-lraxn--ses554gxn--sgne-graphoxn--42c2d9axn--skierv-utaza" + + "stuff-4-salexn--skjervy-v1axn--skjk-soaxn--sknit-yqaxn--sknland-" + + "fxaxn--slat-5naturalsciencesnaturellestufftoread-booksnesolundbe" + + "ckomakiyosunndalxn--slt-elabcieszynxn--smla-hraxn--smna-gratange" + + "ntlentapisa-geekoryokamikawanehonbetsurutaharaxn--snase-nraxn--s" + + "ndre-land-0cbeskidyn-ip24xn--snes-poaxn--snsa-roaxn--sr-aurdal-l" + + "8axn--sr-fron-q1axn--sr-odal-q1axn--sr-varanger-ggbestbuyshouses" + + "3-website-ap-southeast-2xn--srfold-byaxn--srreisa-q1axn--srum-gr" + + "atis-a-bulls-fanxn--stfold-9xaxn--stjrdal-s1axn--stjrdalshalsen-" + + "sqbetainaboxfusejnymemergencyahabaghdadiskussionsbereichaseljeep" + + "sondriodejaneirockartuzyonagunicommbankaragandaxn--stre-toten-zc" + + "bhzcasertairaumalborkarasjohkamikitayamatsurin-the-bandain-vpnca" + + "sinordkappalmspringsakerxn--t60b56axn--tckweatherchannelxn--tiq4" + + "9xqyjelenia-goraxn--tjme-hraxn--tn0agrinetbankosaigawaxn--tnsber" + + "g-q1axn--tor131oxn--trany-yuaxn--trentin-sd-tirol-rzbieidsvollim" + + "anowarudaxn--trentin-sdtirol-7vbrplsbxn--45br5cylxn--trentino-sd" + + "-tirol-c3bielawaltervistaipeigersundisrechtranakaiwamizawatchand" + + "clockarasjokarasuyamarshallstatebankarateu-3xn--trentino-sdtirol" + + "-szbiellaakesvuemielecceu-4xn--trentinosd-tirol-rzbieszczadygeya" + + "chiyodaejeonbukcoalvdalaheadjudygarlandivtasvuodnakamagayahikobi" + + "erzycevje-og-hornnes3-website-eu-west-1xn--trentinosdtirol-7vbie" + + "vat-band-campaniaxn--trentinsd-tirol-6vbifukagawashingtondclkara" + + "tsuginamikatagamilitaryoriikareliancextraspace-to-rentalstomakom" + + "aibaraxn--trentinsdtirol-nsbigv-infoodnetworkangerxn--trgstad-r1" + + "axn--trna-woaxn--troms-zuaxn--tysvr-vraxn--uc0atvestfoldxn--uc0a" + + "y4axn--uist22handsonyoursidellogliastradingxn--uisz3gxn--unjrga-" + + "rtashkentunkommunexn--unup4yxn--uuwu58axn--vads-jraxn--valle-aos" + + "te-ebbturystykanmakiwielunnerxn--valle-d-aoste-ehbodollstuttgart" + + "rentinsuedtirolxn--valleaoste-e7axn--valledaoste-ebbvacationsusa" + + "kis-gonexn--vard-jraxn--vegrshei-c0axn--vermgensberater-ctbihoro" + + "logyoshiokanzakiyokawaraxn--vermgensberatung-pwbikedaemoneyukinc" + + "heonhlfanhs3-website-sa-east-1xn--vestvgy-ixa6oxn--vg-yiabkhazia" + + "xn--vgan-qoaxn--vgsy-qoa0jeonnamerikawauexn--vgu402colonialwilli" + + "amsburgroks-thisayamanobeokakudamatsuexn--vhquvestnesorfoldxn--v" + + "ler-qoaxn--vre-eiker-k8axn--vrggt-xqadxn--vry-yla5gxn--vuq861bil" + + "baokinawashirosatochigiessensiositecnologiaxn--w4r85el8fhu5dnrax" + + "n--w4rs40lxn--wcvs22dxn--wgbh1coloradoplateaudioxn--wgbl6axn--xh" + + "q521billustrationredumbrellahppiacenzachpomorskienikonanporovnob" + + "serverxn--xkc2al3hye2axn--xkc2dl3a5ee0hangglidingxn--y9a3aquariu" + + "misconfusedxn--yer-znaturbruksgymnxn--yfro4i67oxn--ygarden-p1axn" + + "--ygbi2ammxn--45brj9civilizationiyodogawaxn--ystre-slidre-ujbioc" + + "eanographics3-website-us-east-1xn--zbx025dxn--zf0ao64axn--zf0avx" + + "lxn--zfr164birdartcenterprisecloudcontrolappleborkdalwaysdatabas" + + "eballangenkainanaerobatickets3-website-us-west-1xnbayxz" // nodes is the list of nodes. Each node is represented as a uint32, which // encodes the node's children, wildcard bit and node type (as an index into @@ -526,1818 +528,1812 @@ const text = "9guacuiababia-goracleaningroks-theatree12hpalermomahachijoinvill" // [15 bits] text index // [ 6 bits] text length var nodes = [...]uint32{ - 0x297a83, - 0x32a504, - 0x2eadc6, - 0x24c943, - 0x24c946, - 0x38b146, - 0x3b05c3, - 0x214bc4, - 0x201507, - 0x2eaa08, + 0x32f643, + 0x3b5c84, + 0x2f7846, + 0x2ed303, + 0x2ed306, + 0x391ec6, + 0x3ba683, + 0x242cc4, + 0x2089c7, + 0x2f7488, 0x1a000c2, - 0x1f36987, - 0x376649, - 0x36c4ca, - 0x36c4cb, - 0x201203, - 0x233985, - 0x2201602, - 0x2d2044, - 0x2eaf43, - 0x269045, - 0x2601742, - 0x343083, - 0x2a135c4, - 0x2982c5, - 0x2e0de42, - 0x26e24e, - 0x250b83, - 0x3a6286, - 0x3203082, - 0x306087, - 0x2372c6, - 0x3606bc2, - 0x27f943, - 0x27f944, - 0x399b86, - 0x35bc88, - 0x286046, - 0x26fc84, + 0x1f3c187, + 0x37b0c9, + 0x39a04a, + 0x39a04b, + 0x231983, + 0x234b85, + 0x2202642, + 0x280004, + 0x2f79c3, + 0x202645, + 0x2608c02, + 0x365e83, + 0x2a15d84, + 0x3b5585, + 0x2e12282, + 0x27520e, + 0x251a43, + 0x3adec6, + 0x3207d42, + 0x306e07, + 0x237306, + 0x3601f82, + 0x26d143, + 0x334e46, + 0x360f48, + 0x28e806, + 0x276804, 0x3a00ac2, - 0x34abc9, - 0x2236c7, - 0x202446, - 0x353689, - 0x32f208, - 0x2478c4, - 0x23f2c6, - 0x3c3846, - 0x3e041c2, - 0x36fcc6, - 0x242f4f, - 0x2d108e, - 0x219a44, - 0x218b45, - 0x32a405, - 0x2e7589, - 0x23d709, - 0x39a387, - 0x3ddf06, - 0x267243, - 0x42037c2, - 0x21adc3, - 0x35054a, - 0x460f283, - 0x3d95c5, - 0x29d282, - 0x38b6c9, - 0x4e01182, - 0x201c84, - 0x2f3146, - 0x28a745, - 0x36d1c4, - 0x560fbc4, - 0x220dc3, - 0x232d04, - 0x5a02d02, - 0x235784, - 0x5e79284, - 0x33cb4a, + 0x34cd89, + 0x222087, + 0x3b4c86, + 0x370f49, + 0x3c8608, + 0x354f84, + 0x25b9c6, + 0x3cdd86, + 0x3e029c2, + 0x2a7f06, + 0x24394f, + 0x27f04e, + 0x221684, + 0x2d4205, + 0x32f545, + 0x215589, + 0x23d909, + 0x335647, + 0x355246, + 0x203583, + 0x42272c2, + 0x22ce03, + 0x2937ca, + 0x4601ac3, + 0x3e1a45, + 0x239202, + 0x392449, + 0x4e03502, + 0x209784, + 0x2f4406, + 0x28fac5, + 0x3732c4, + 0x56263c4, + 0x233f03, + 0x233f04, + 0x5a02e42, + 0x385d04, + 0x5e83a84, + 0x25d6ca, 0x6200882, - 0x3c1f47, - 0x2d0548, - 0x76031c2, - 0x328287, - 0x2c9044, - 0x2c9047, - 0x3d57c5, - 0x378847, - 0x303c06, - 0x2f0e44, - 0x342e05, - 0x257187, - 0x8e01482, - 0x36fe43, - 0x9226782, - 0x3633c3, - 0x9606b42, - 0x274985, + 0x229547, + 0x27e508, + 0x7a07282, + 0x334a47, + 0x2ce984, + 0x2ce987, + 0x3dbac5, + 0x390e07, + 0x34b706, + 0x2a1184, + 0x36a285, + 0x257e87, + 0x8e07cc2, + 0x2a8083, + 0x9210642, + 0x3b3f43, + 0x96074c2, + 0x2173c5, 0x9a00202, - 0x2cd104, - 0x2c23c5, - 0x219987, - 0x249e0e, - 0x2b6e44, - 0x290f44, - 0x210603, - 0x286ac9, - 0x3aa74b, - 0x2edac8, - 0x303148, - 0x3b1888, - 0x3d9ac8, - 0x3534ca, - 0x378747, - 0x2cdf46, - 0x9e47402, - 0x374d83, - 0x3ccac3, - 0x3ce604, - 0x374dc3, - 0x35cb83, - 0x1732182, - 0xa2016c2, - 0x27cd05, - 0x224686, - 0x233744, - 0x38a5c7, - 0x2355c6, - 0x2c8984, - 0x3abfc7, - 0x215dc3, - 0xa6d5bc2, - 0xaa20f82, - 0xae20d42, - 0x220d46, - 0xb200282, - 0x284405, - 0x3336c3, - 0x3c8744, - 0x2f7784, - 0x2f7785, - 0x3d6d83, - 0xb602703, - 0xba019c2, - 0x205fc5, - 0x205fcb, - 0x20ec0b, - 0x229904, - 0x206689, - 0x208244, - 0xbe09c42, - 0x20a483, - 0x20a703, - 0xc202e82, - 0x398a0a, - 0xc601542, - 0x2d22c5, - 0x2e6a0a, - 0x247584, - 0x20b103, - 0x20b7c4, - 0x20d6c3, - 0x20d6c4, - 0x20d6c7, - 0x20e245, - 0x2114c6, - 0x211846, - 0x2124c3, - 0x217688, - 0x208f03, - 0xca0cd42, - 0x308648, - 0x2862cb, - 0x21ffc8, - 0x2205c6, - 0x2213c7, - 0x227208, - 0xda07682, - 0xde1d482, - 0x298408, - 0x210c07, - 0x30dcc5, - 0x30dcc8, - 0xe301108, - 0x26c243, - 0x22a444, - 0x38b1c2, - 0xe62a882, - 0xea16182, - 0xf22c042, - 0x22c043, - 0xf6086c2, - 0x296303, - 0x3b2744, - 0x2086c3, - 0x247884, - 0x296a4b, - 0x215843, - 0x2f1486, - 0x278704, - 0x2c340e, - 0x38f345, - 0x261e48, - 0x3a6387, - 0x3a638a, - 0x22f983, - 0x2343c7, - 0x3aa905, - 0x22f984, - 0x2526c6, - 0x2526c7, - 0x31a204, - 0xfb0d704, - 0x24a144, - 0x33c806, - 0x22b844, - 0x3b5cc6, - 0x232443, - 0x3ba348, - 0x3df888, - 0x290f03, - 0x3989c3, - 0x340384, - 0x355943, - 0x10215702, - 0x1068d502, - 0x218043, - 0x2435c6, - 0x343343, - 0x30c504, - 0x10a3fec2, - 0x24cf43, - 0x327783, - 0x212c02, - 0x10e00d42, - 0x2cb886, - 0x234807, - 0x3c25c7, - 0x3b91c5, - 0x3d3004, - 0x29fbc5, - 0x2253c7, - 0x2ade49, - 0x2c19c6, - 0x2ec246, - 0x1120b682, - 0x2f4b48, - 0x3ae1c6, - 0x2aed85, - 0x30a6c7, - 0x3562c4, - 0x3562c5, - 0x11668c84, - 0x268c88, - 0x11a06082, - 0x11e00482, - 0x26e986, - 0x200488, - 0x331ac5, - 0x34b646, - 0x34ef88, - 0x35b788, - 0x12201805, - 0x126136c4, - 0x2136c7, - 0x12a07cc2, - 0x12e167c2, - 0x14201242, - 0x2f3245, - 0x14a83545, - 0x262486, - 0x323647, - 0x39f087, - 0x14e14a83, - 0x338487, - 0x38a948, - 0x2022cd09, - 0x26e407, - 0x22d447, - 0x22e548, - 0x22ed46, - 0x22f486, - 0x2300cc, - 0x23180a, - 0x231c07, - 0x23384b, - 0x234647, - 0x23464e, - 0x20635944, - 0x235b44, - 0x238b07, - 0x25c7c7, - 0x23d006, - 0x23d007, - 0x3b3147, - 0x2d2c43, - 0x20a2ba02, - 0x23e306, - 0x23e30a, - 0x23f44b, - 0x240987, - 0x241405, - 0x241e43, - 0x242246, - 0x242247, - 0x2f8983, - 0x20e00102, - 0x242bca, - 0x21377dc2, - 0x2173da82, - 0x21a3fd02, - 0x21e373c2, - 0x245385, - 0x245d44, - 0x22a05582, - 0x235805, - 0x23fa43, - 0x314885, - 0x2688c4, - 0x2afb04, - 0x2cea06, - 0x250f06, - 0x2061c3, - 0x3bb644, - 0x303ec3, - 0x23a02a42, - 0x213c44, - 0x213c46, - 0x221745, - 0x244d46, - 0x30a7c8, - 0x223dc4, - 0x367bc8, - 0x231e85, - 0x262b88, - 0x2caa06, - 0x217c07, - 0x273504, - 0x24e73506, - 0x252239c3, - 0x39e183, - 0x31d988, - 0x29ffc4, - 0x2572ccc7, - 0x25ee4846, - 0x2e4849, - 0x362008, - 0x36a408, - 0x3b6544, - 0x3c7903, - 0x22dd42, - 0x2624e782, - 0x2660fa82, - 0x3c9083, - 0x26a01642, - 0x2f8904, - 0x279986, - 0x21c103, - 0x2bc7c7, - 0x303743, - 0x32fcc8, - 0x20b885, - 0x25a683, - 0x2c2345, - 0x2c2484, + 0x375d04, + 0x2ef285, + 0x2215c7, + 0x25d04e, + 0x2ba484, + 0x29a884, + 0x20ebc3, + 0x35c549, + 0x2c17cb, + 0x2c75c8, + 0x32cc48, + 0x3313c8, + 0x3e1f48, + 0x370d8a, + 0x390d07, + 0x356606, + 0x9e3de82, + 0x26f0c3, + 0x3d2103, + 0x3d3c84, + 0x26f103, + 0x361e43, + 0x1737f82, + 0xa206c02, + 0x284a05, + 0x2bc146, + 0x234944, + 0x3aee07, + 0x26bdc6, + 0x2cd644, + 0x3bdc87, + 0x20d483, + 0xa6d7f02, + 0xab0bf02, + 0xae7b6c2, 0x30bcc6, - 0x20cac6, - 0x2198c6, - 0x2f39c4, - 0x234a03, - 0x26e0fe02, - 0x27233fc5, - 0x200843, - 0x27a07382, - 0x22d1c3, - 0x2676c5, - 0x27e32dc3, - 0x28632dc9, - 0x28a00942, - 0x29208902, - 0x28ce05, - 0x213f06, - 0x28ec06, - 0x2e6608, - 0x2e660b, - 0x339c8b, - 0x3b93c5, - 0x2d6149, - 0x1600b42, - 0x2f0548, - 0x206984, - 0x29a03c42, - 0x34a843, - 0x2a25c986, - 0x3c2888, - 0x2a6142c2, - 0x35c708, - 0x2aaaac82, - 0x337f8a, - 0x2aedb383, - 0x2b776c86, - 0x392488, - 0x214886, - 0x387b87, - 0x243147, - 0x3c33ca, - 0x247604, - 0x360704, - 0x376209, - 0x2bba9dc5, - 0x26e286, - 0x210e03, - 0x24e3c4, - 0x2be196c4, - 0x3458c7, - 0x2c241c87, - 0x294f84, - 0x39f545, - 0x262548, - 0x39e647, - 0x3a24c7, - 0x2c60dec2, - 0x29cf44, - 0x293048, - 0x246d84, - 0x24b904, - 0x24bcc5, - 0x24be07, - 0x2ca7ebc9, - 0x2232c4, - 0x24d789, - 0x24d9c8, - 0x24e144, - 0x24e147, - 0x2ce4e583, - 0x24ea87, - 0x2d20bb42, - 0x16b8842, - 0x24fa46, - 0x250087, - 0x250704, - 0x251d07, - 0x253787, - 0x253f83, - 0x22dec2, - 0x20d982, - 0x303243, - 0x3c6704, - 0x3c670b, - 0x2d703248, - 0x25a044, - 0x255b85, - 0x257407, - 0x2e92c5, - 0x33144a, + 0xb200282, + 0x2a4d45, + 0x3394c3, + 0x3d5bc4, + 0x2f9284, + 0x2f9285, + 0x3dff03, + 0xb64ac43, + 0xba05102, + 0x2093c5, + 0x2093cb, + 0x2b2a0b, + 0x204cc4, + 0x209849, + 0x20ae84, + 0xbe0b742, + 0x20c303, + 0x20e1c3, + 0xc207f42, + 0x2f2aca, + 0xc608a02, + 0x280285, + 0x2e858a, + 0x242644, + 0x210143, + 0x210a04, + 0x211943, + 0x211944, + 0x211947, + 0x212685, + 0x213086, + 0x213386, + 0x214683, + 0x218248, + 0x217143, + 0xca0cfc2, + 0x266308, + 0x28ea8b, + 0x2208c8, + 0x221106, + 0x222887, + 0x225048, + 0xda0aac2, + 0xde1c942, + 0x272d48, + 0x20f1c7, + 0x20f705, + 0x310f88, + 0xe302e48, + 0x2b0ec3, + 0x22bec4, + 0x391f42, + 0xe62c0c2, + 0xea06cc2, + 0xf22c442, + 0x22c443, + 0xf60cf02, + 0x316343, + 0x332284, + 0x214803, + 0x354f44, + 0x32430b, + 0x20cf03, + 0x2f2086, + 0x25d544, + 0x2c888e, + 0x377205, + 0x268a88, + 0x3adfc7, + 0x3adfca, + 0x231503, + 0x2355c7, + 0x2c1985, + 0x231504, + 0x253a06, + 0x253a07, + 0x31dd84, + 0xfb109c4, + 0x25d384, + 0x25d386, + 0x252684, + 0x3c2f86, + 0x20f4c3, + 0x20f4c8, + 0x210448, + 0x29a843, + 0x2f2a83, + 0x343c04, + 0x35c0c3, + 0x1020cdc2, + 0x106bd282, + 0x205083, + 0x243fc6, + 0x25bac3, + 0x274784, + 0x10a30c82, + 0x25ce43, + 0x316a83, + 0x214dc2, + 0x10e00d42, + 0x2d3286, + 0x235a07, + 0x229bc7, + 0x3c0d85, + 0x21cc84, + 0x2a0dc5, + 0x30f247, + 0x2e5a49, + 0x2ee886, + 0x3032c6, + 0x11602282, + 0x307a08, + 0x31a706, + 0x2b1bc5, + 0x30c3c7, + 0x30dcc4, + 0x30dcc5, + 0x11a02284, + 0x202288, + 0x11e09482, + 0x12200482, + 0x275946, + 0x200488, + 0x337b45, + 0x34d686, + 0x350448, + 0x360a48, + 0x12608cc5, + 0x12a15e84, + 0x215e87, + 0x12e0a902, + 0x13361e82, + 0x14612402, + 0x2f4505, + 0x14e8af45, + 0x269506, + 0x327ec7, + 0x3b26c7, + 0x1522ea43, + 0x32bb87, + 0x3c17c8, + 0x2162ed49, + 0x2753c7, + 0x22f487, + 0x22fe88, + 0x230686, + 0x231006, + 0x231c4c, + 0x23294a, + 0x232d47, + 0x234a4b, + 0x235847, + 0x23584e, + 0x21a36344, + 0x236704, + 0x238a07, + 0x260b47, + 0x23d046, + 0x23d047, + 0x335887, + 0x226dc3, + 0x21e2c982, + 0x23e846, + 0x23e84a, + 0x24004b, + 0x241287, + 0x241d05, + 0x242183, + 0x2423c6, + 0x2423c7, + 0x2fa483, + 0x22200102, + 0x2435ca, + 0x2277c682, + 0x22b49682, + 0x22e40902, + 0x23237402, + 0x246ac5, + 0x247344, + 0x23e0da02, + 0x385d85, + 0x240643, + 0x299645, + 0x201ec4, + 0x21dd04, + 0x2d4e46, + 0x251dc6, + 0x2095c3, + 0x3cce44, + 0x37f243, + 0x24e0f982, + 0x216404, + 0x216406, + 0x222c05, + 0x2482c6, + 0x30c4c8, + 0x265e44, + 0x294208, + 0x232fc5, + 0x259508, + 0x2d0686, + 0x30e0c7, + 0x269c04, + 0x26269c06, + 0x26622383, + 0x3a47c3, + 0x2f7108, + 0x38bc44, + 0x26b32ec7, + 0x2e6946, + 0x2e6949, + 0x369588, + 0x37d748, + 0x389c84, + 0x204583, + 0x240702, + 0x2724e682, + 0x27626282, + 0x205c83, + 0x27a08b02, + 0x2fa404, + 0x2790c6, + 0x21a203, + 0x2c3d47, + 0x3b3a83, + 0x2ba548, + 0x21edc5, 0x259f83, - 0x2da05dc2, - 0x208e04, - 0x25c589, - 0x260c03, - 0x260cc7, - 0x240749, - 0x205dc8, - 0x22af03, - 0x27b3c7, - 0x27be89, - 0x225583, - 0x283b84, - 0x284d09, - 0x28b2c6, - 0x2f4103, - 0x2015c2, - 0x23c903, - 0x2b8647, - 0x23c905, - 0x3b1686, - 0x270744, - 0x35ff85, - 0x27c7c3, - 0x212706, - 0x292503, - 0x206882, - 0x248f84, - 0x2de299c2, - 0x2e2299c3, - 0x2e607082, - 0x248343, - 0x211cc4, - 0x2ece07, - 0x2946c6, - 0x262302, - 0x2ea5cd82, - 0x30a9c4, - 0x2f20d842, - 0x2f616902, - 0x2ef084, - 0x2ef085, - 0x302c85, - 0x35ef86, - 0x2fa0f582, - 0x39b745, - 0x3ba745, - 0x283483, - 0x20f586, - 0x20fec5, - 0x220cc2, - 0x35b3c5, - 0x220cc4, - 0x223d03, - 0x223f43, - 0x2fe05b42, - 0x2e29c7, - 0x24dbc4, + 0x2ef205, + 0x2ef344, + 0x30d9c6, + 0x220006, + 0x221506, + 0x2f4c84, + 0x235c03, + 0x27e11702, + 0x282351c5, + 0x200843, + 0x28a0da82, + 0x22f203, + 0x3233c5, + 0x28e33fc3, + 0x29633fc9, + 0x29a00942, + 0x2a20fc42, + 0x292845, + 0x2166c6, + 0x2ada86, + 0x2e9f08, + 0x2e9f0b, + 0x346d4b, + 0x3c0f85, + 0x2d8489, + 0x1600b42, + 0x39b4c8, + 0x209b44, + 0x2aa031c2, + 0x34ca03, + 0x2b260d06, + 0x2b600fc2, + 0x3619c8, + 0x2ba293c2, + 0x33d78a, + 0x2bedd983, + 0x2c77b706, + 0x397c88, + 0x242986, + 0x38dc47, + 0x243b47, + 0x3cd90a, + 0x2426c4, + 0x365c04, + 0x37a709, + 0x2cbb1905, + 0x275246, + 0x20f3c3, + 0x24e104, + 0x2ced8384, + 0x3b4447, + 0x2d233647, + 0x25ce84, + 0x3b2b85, + 0x2695c8, + 0x3a4c87, + 0x3a9847, + 0x2d60fa02, + 0x26acc4, + 0x2981c8, + 0x248604, + 0x24bb44, + 0x24bf45, + 0x24c087, + 0x2da81989, + 0x21eb04, + 0x24d4c9, + 0x24d708, + 0x24de84, + 0x24de87, + 0x2de4e483, + 0x24f8c7, + 0x2e201282, + 0x16be142, + 0x250386, + 0x251187, + 0x2515c4, + 0x252dc7, + 0x254047, + 0x254603, + 0x2ba882, + 0x20e782, + 0x32cd43, + 0x3ce884, + 0x3ce88b, + 0x2e72cd48, + 0x259a04, + 0x255d05, + 0x2576c7, + 0x20e785, + 0x31d28a, + 0x259943, + 0x2ea091c2, + 0x21d304, + 0x260909, + 0x264e43, + 0x264f07, + 0x28c949, + 0x2091c8, + 0x26f783, + 0x283187, + 0x283b89, + 0x26a503, + 0x28b544, + 0x28cb89, + 0x290cc6, + 0x2e9d03, + 0x207c82, + 0x23cc03, + 0x2bdf47, + 0x23cc05, + 0x2c15c6, + 0x296d84, + 0x365485, + 0x2844c3, + 0x2148c6, + 0x27eb43, + 0x209a42, + 0x24ac04, + 0x2ee08882, + 0x2f368483, + 0x2f6033c2, + 0x249f83, + 0x20dc44, + 0x303b07, + 0x348546, + 0x27cec2, + 0x2fa04d82, + 0x30c6c4, + 0x30211ac2, + 0x30621c42, + 0x2f0f04, + 0x2f0f05, + 0x363e85, + 0x260286, + 0x30a06d42, + 0x20f8c5, + 0x219a45, + 0x21bb43, + 0x225d86, + 0x227545, + 0x265d82, + 0x360685, + 0x30bc44, + 0x265d83, + 0x265fc3, + 0x30e08f42, + 0x2e4dc7, + 0x24d904, + 0x24d909, + 0x24e004, + 0x28adc3, + 0x2b9808, + 0x3128adc4, + 0x28adc6, + 0x2a49c3, + 0x256543, + 0x266a83, + 0x316fb9c2, + 0x308982, + 0x31a00642, + 0x33b208, + 0x3e0108, + 0x3bef86, + 0x351a05, + 0x303c85, + 0x207d87, + 0x31e46145, + 0x23ca82, + 0x3229cac2, + 0x32600042, + 0x27db48, + 0x31a645, + 0x2feac4, + 0x248205, + 0x2497c7, + 0x388944, + 0x2434c2, + 0x32a0b2c2, + 0x352084, + 0x228b07, + 0x292d07, + 0x390dc4, + 0x3d2c03, + 0x29a784, + 0x29a788, + 0x231346, + 0x25388a, + 0x2f5844, + 0x299e48, + 0x235384, + 0x222986, + 0x29ca84, + 0x2f4806, 0x24dbc9, - 0x24e2c4, - 0x2833c3, - 0x2b61c8, - 0x302833c4, - 0x2833c6, - 0x2a37c3, - 0x256303, - 0x308003, - 0x306f7642, - 0x309442, - 0x30a00642, - 0x335408, - 0x36af48, - 0x3b7906, - 0x3830c5, - 0x22c805, - 0x204287, - 0x30e77185, - 0x23c782, - 0x3129b602, - 0x31600042, - 0x2cfb88, - 0x3ae105, - 0x2fc7c4, - 0x244c85, - 0x2547c7, - 0x3a3884, - 0x242ac2, - 0x31a11442, - 0x351144, - 0x220a87, - 0x28ddc7, - 0x378804, - 0x3cd483, - 0x290e44, - 0x290e48, - 0x22f7c6, - 0x25254a, - 0x326584, - 0x299288, - 0x234184, - 0x2214c6, - 0x29b5c4, - 0x2f3546, - 0x24de89, - 0x2a9fc7, - 0x207543, - 0x31e3ee42, - 0x3b62c3, - 0x209e42, - 0x32204702, - 0x349e46, - 0x381988, - 0x2abfc7, - 0x228b09, - 0x2b1549, - 0x2ad505, - 0x2afc09, + 0x2abc07, + 0x213ec3, + 0x32e5b542, + 0x3a2503, + 0x20b942, + 0x33205742, + 0x34c006, + 0x386d08, + 0x2adc07, + 0x30b109, + 0x2addc9, 0x2b0405, - 0x2b1245, - 0x2b1f88, - 0x32608784, - 0x32a540c7, - 0x22d803, - 0x2b2187, - 0x22d806, - 0x2b25c7, - 0x2a9ac5, - 0x22d083, - 0x32e315c2, - 0x20b344, - 0x3320e782, - 0x33606502, - 0x380e86, - 0x2d04c5, - 0x2b54c7, - 0x343a03, - 0x35cb04, - 0x209283, - 0x2cd743, - 0x33a06182, - 0x34205bc2, - 0x38b244, - 0x22de83, - 0x3047c5, - 0x34600f42, - 0x34e01f02, - 0x304fc6, - 0x201f04, - 0x306bc4, - 0x306bca, - 0x356005c2, - 0x213903, - 0x21884a, - 0x21bac8, - 0x35a21dc4, + 0x2b2d89, + 0x2b3cc5, + 0x2b4b05, + 0x2b5f88, + 0x33611b04, + 0x33a54747, + 0x22f843, + 0x2b6187, + 0x22f846, + 0x2b6987, + 0x2ab845, + 0x22f0c3, + 0x33e32702, + 0x210384, + 0x3422cb02, + 0x3460b5c2, + 0x314d06, + 0x27e485, + 0x2b8ec7, + 0x356e03, + 0x361dc4, + 0x21d783, + 0x355e03, + 0x34a09582, + 0x35208fc2, + 0x391fc4, + 0x32ae03, + 0x305545, + 0x3560f782, + 0x35e02182, + 0x305d46, + 0x2069c4, + 0x30a304, + 0x30a30a, + 0x366005c2, + 0x2160c3, + 0x21528a, + 0x219008, + 0x36a0e704, 0x2005c3, - 0x35e96b43, - 0x237909, - 0x22e0c9, - 0x2bc8c6, - 0x3621bc83, - 0x21bc85, - 0x222f8d, - 0x226586, - 0x26518b, - 0x3660ccc2, - 0x205708, - 0x3a217782, - 0x3a605382, - 0x2bad85, - 0x3aa04582, - 0x2b3307, - 0x210083, - 0x210088, - 0x3ae07882, - 0x288304, - 0x20c743, - 0x33b805, - 0x23fb46, - 0x224004, - 0x398983, - 0x2b9583, - 0x3b201d82, - 0x3b9344, - 0x3d4c45, - 0x2b8247, - 0x279403, - 0x2b8e43, - 0x16b9102, - 0x2b9103, - 0x2b9503, - 0x3b600e02, - 0x3473c4, - 0x251106, - 0x2e42c3, - 0x2b9c03, - 0x3ba49582, - 0x249588, - 0x2bab84, - 0x347146, - 0x255707, - 0x284646, - 0x29ff44, - 0x49e03fc2, - 0x22d6cb, - 0x2ff50e, - 0x216d8f, - 0x39d6c3, - 0x4a65ac42, - 0x161fb02, - 0x4aa0af02, - 0x2928c3, - 0x2108c3, - 0x20af06, - 0x21d306, - 0x34dec7, - 0x310c44, - 0x4ae14042, - 0x4b20bd82, - 0x2e0685, - 0x2ff987, - 0x2bb206, - 0x4b662702, - 0x384c44, - 0x2c03c3, - 0x4ba01e42, - 0x4bf73103, - 0x2c2984, - 0x2c8009, - 0x4c2ced42, - 0x4c614d42, - 0x344945, - 0x4cad3942, - 0x4ce06002, - 0x35f947, - 0x3768cb, - 0x242f05, - 0x258109, - 0x26aa86, - 0x4d209504, - 0x295449, - 0x2d46c7, - 0x3dea87, - 0x22c343, - 0x2eef06, - 0x324047, - 0x25cc03, - 0x2a6a86, - 0x4da1ae42, - 0x4de33042, - 0x3b6403, - 0x38b885, - 0x21f407, - 0x236146, - 0x23c885, - 0x24db44, - 0x2a8985, - 0x38dac4, - 0x4e202482, - 0x2cc844, - 0x22dfc4, - 0x22dfcd, - 0x377189, - 0x22c648, - 0x344bc4, - 0x328845, - 0x3b8c47, - 0x3c5cc4, - 0x265907, - 0x2e4005, - 0x4e6ac604, - 0x2bf345, - 0x25f8c4, - 0x3a39c6, - 0x3973c5, - 0x4ea05442, - 0x26e903, - 0x267fc3, - 0x348cc4, - 0x348cc5, - 0x396886, - 0x23c9c5, - 0x22ae84, - 0x329743, - 0x4ee1a286, - 0x221fc5, - 0x222a85, - 0x323544, - 0x2f6283, - 0x32660c, - 0x4f208b02, - 0x4f605102, - 0x4fa02042, - 0x21a8c3, - 0x21a8c4, - 0x4fe08282, - 0x30e1c8, - 0x3b1745, - 0x2d3b84, - 0x23af86, - 0x50223502, - 0x5061b542, - 0x50a00c42, - 0x290c05, - 0x2f3886, - 0x219604, - 0x39a0c6, - 0x362dc6, - 0x211183, - 0x50ea240a, - 0x2795c5, - 0x350503, - 0x222446, - 0x3d2d09, - 0x222447, - 0x2b4d08, - 0x32f0c9, - 0x2adfc8, - 0x227d46, - 0x2105c3, - 0x512017c2, - 0x39fa08, - 0x51601f42, - 0x51a09e82, - 0x2137c3, - 0x2ec0c5, - 0x29f2c4, - 0x2fe389, - 0x2898c4, - 0x24aec8, - 0x52209e83, - 0x52696ec4, - 0x213f48, - 0x22df07, - 0x52b3d642, - 0x238442, - 0x32a385, - 0x37fc49, - 0x23c803, - 0x27e384, - 0x31d284, - 0x210943, - 0x27f28a, - 0x52e03f82, - 0x5320b182, - 0x2d5b43, - 0x390883, - 0x1627f82, - 0x374583, - 0x5361d542, - 0x53a00bc2, - 0x53f06c44, - 0x3d7846, - 0x26bbc4, - 0x277d83, - 0x281c83, - 0x54200bc3, - 0x23f7c6, - 0x208405, - 0x2d9ac7, - 0x2d9a06, - 0x2dab48, - 0x2dad46, - 0x20e944, - 0x2a0f0b, - 0x2dd603, - 0x2dd605, - 0x20f002, - 0x35fc42, - 0x54645402, - 0x54a02382, - 0x202383, - 0x54e6c9c2, - 0x26c9c3, - 0x2de083, - 0x55622902, - 0x55ae2406, - 0x258946, - 0x55e05902, - 0x5620a742, - 0x56623f82, - 0x56a15402, - 0x56e18482, - 0x57202802, - 0x214e83, - 0x385546, - 0x57619a04, - 0x213a4a, - 0x3a4986, - 0x20da84, - 0x204643, - 0x5820ce02, - 0x208482, - 0x23a0c3, - 0x5861a3c3, - 0x3bd287, - 0x3972c7, - 0x5aed3087, - 0x344407, - 0x228643, - 0x22864a, - 0x262044, - 0x31afc4, - 0x31afca, - 0x22cb45, - 0x5b21bb02, - 0x24fa03, - 0x5b600602, - 0x24e283, - 0x3b6283, - 0x5be00582, - 0x38a8c4, - 0x204484, - 0x3c2d05, - 0x3dd205, - 0x26a146, - 0x306e06, - 0x5c230a42, - 0x5c602902, - 0x310805, - 0x258652, - 0x35e586, - 0x207283, - 0x359106, - 0x2bf805, - 0x16535c2, - 0x64a0a9c2, - 0x372b43, - 0x20a9c3, - 0x292083, - 0x64e06e42, - 0x210e83, - 0x6521ad42, - 0x276e43, - 0x24b188, - 0x2624c3, - 0x2ad386, - 0x3cfc87, - 0x321486, - 0x32148b, - 0x20d9c7, - 0x31d784, - 0x65a00c02, - 0x3b15c5, - 0x65e08443, - 0x26d243, - 0x3b29c5, - 0x33f243, - 0x6673f246, - 0x3cac0a, - 0x2a7083, - 0x2366c4, + 0x36e0a2c3, + 0x26a749, + 0x247109, + 0x2c3e46, + 0x372191c3, + 0x2191c5, + 0x21e7cd, + 0x22db06, + 0x2e61cb, + 0x37607542, + 0x358448, + 0x3b20c202, + 0x3b603082, + 0x39e285, + 0x3ba04b82, + 0x2af7c7, + 0x205603, + 0x227708, + 0x3be022c2, + 0x25ef84, + 0x21fc83, + 0x354a05, + 0x240746, + 0x227104, + 0x2f2a43, + 0x384583, + 0x3c206142, + 0x3c0f04, + 0x2bab45, + 0x2bdb47, + 0x281403, + 0x2be4c3, + 0x1616fc2, + 0x2be783, + 0x2beb83, + 0x3c600e02, + 0x33f584, + 0x235e06, + 0x2e6503, + 0x2bf943, + 0x3ca4b202, + 0x24b208, + 0x2c0904, + 0x33f306, + 0x253e87, + 0x29a946, + 0x38bbc4, + 0x4ae03102, + 0x22f70b, + 0x30180e, + 0x217a8f, + 0x2be183, + 0x4b65a642, + 0x1641882, + 0x4ba03802, + 0x2563c3, + 0x20ee83, + 0x21b306, + 0x34e0c6, + 0x395dc7, + 0x3d2484, + 0x4be16802, + 0x4c21f2c2, + 0x2e2845, + 0x33dec7, + 0x2c2506, + 0x4c669782, + 0x3626c4, + 0x2c7a83, + 0x4ca06902, + 0x4cf78103, + 0x2c9284, + 0x2cde89, + 0x4d2d5182, + 0x4d60a342, + 0x248985, + 0x4dad5682, + 0x4de01582, + 0x364e47, + 0x37b34b, + 0x243905, + 0x258509, + 0x270906, + 0x4e201584, + 0x206d89, + 0x2d6a07, + 0x22a147, + 0x22c743, + 0x2f0d86, + 0x352f87, + 0x21df43, + 0x2a87c6, + 0x4ea29a82, + 0x4ee34242, + 0x2061c3, + 0x392605, + 0x303147, + 0x236d06, + 0x23cb85, + 0x24d884, + 0x2aad45, + 0x393dc4, + 0x4f201482, + 0x2e9184, + 0x247004, + 0x24700d, + 0x2ee249, + 0x22ca48, + 0x248c04, + 0x347fc5, + 0x204407, + 0x206504, + 0x26be87, + 0x267a45, + 0x4f60a284, + 0x2c6045, + 0x201484, + 0x253306, + 0x394fc5, + 0x4faa4c82, + 0x2758c3, + 0x357643, + 0x35d804, + 0x35d805, + 0x39d506, + 0x23ccc5, + 0x368e84, + 0x364343, + 0x4fe17e86, + 0x21a8c5, + 0x21e2c5, + 0x327dc4, + 0x2f58c3, + 0x2f58cc, + 0x502bdc42, + 0x50600e82, + 0x50a02702, + 0x21e1c3, + 0x21e1c4, + 0x50e0a682, + 0x3b9e88, + 0x2c1685, + 0x2d5ec4, + 0x230e86, + 0x51204202, + 0x5162d582, + 0x51a00c42, + 0x296545, + 0x2f4b46, + 0x265684, + 0x335386, + 0x229306, + 0x25bfc3, + 0x51e9068a, + 0x2815c5, + 0x293783, + 0x209f06, + 0x209f09, + 0x223fc7, + 0x2b7fc8, + 0x3c84c9, + 0x2e5bc8, + 0x22dd86, + 0x20eb83, + 0x52208c82, + 0x32d248, + 0x52606a02, + 0x52a0b982, + 0x215f83, + 0x2ee705, + 0x2a0484, + 0x300689, + 0x3c04c4, + 0x20bc08, + 0x5320b983, + 0x53724784, + 0x216708, + 0x246f47, + 0x53b49242, + 0x370242, + 0x32f4c5, + 0x385509, + 0x23cb03, + 0x31bb84, + 0x3424c4, + 0x204483, + 0x28698a, + 0x53f93b42, + 0x542101c2, + 0x2d7e83, + 0x396083, + 0x162dfc2, + 0x26e8c3, + 0x54615782, + 0x54a00bc2, + 0x54e17544, + 0x217546, + 0x271a44, + 0x27d983, + 0x289683, + 0x55200bc3, + 0x2403c6, + 0x3d5d85, + 0x2dbe07, + 0x2dbd46, + 0x2dcd88, + 0x2dcf86, + 0x202a04, + 0x2a21cb, + 0x2dfa03, + 0x2dfa05, + 0x20e982, + 0x365142, + 0x55646b42, + 0x55a0a942, + 0x216843, + 0x55e720c2, + 0x2720c3, + 0x2e0483, + 0x56603e42, + 0x56ae4806, + 0x258d46, + 0x56ee4942, + 0x5720e202, + 0x57666002, + 0x57a0cac2, + 0x57e0e882, + 0x58203882, + 0x20c543, + 0x3af006, + 0x5861e484, + 0x21620a, + 0x3b0106, + 0x281284, + 0x208143, + 0x59216102, + 0x203182, + 0x241c83, + 0x59617fc3, + 0x3c49c7, + 0x394ec7, + 0x5c245ec7, + 0x37efc7, + 0x228803, + 0x22880a, + 0x237bc4, + 0x31ef04, + 0x31ef0a, + 0x22eb85, + 0x5c60e742, + 0x250343, + 0x5ca00602, + 0x24dfc3, + 0x3a24c3, + 0x5d200582, + 0x3c1744, + 0x207f84, + 0x3dcc45, + 0x32e9c5, + 0x2f6786, + 0x30a546, + 0x5d63bec2, + 0x5da02542, + 0x301dc5, + 0x258a52, + 0x363486, + 0x291043, + 0x31c146, + 0x2b6585, + 0x1605cc2, + 0x65e0fec2, + 0x377b43, + 0x20fec3, + 0x39f483, + 0x66201102, + 0x20f443, + 0x666035c2, + 0x207583, + 0x3dcf88, + 0x269543, + 0x2b0286, + 0x3da087, + 0x34f0c6, + 0x34f0cb, + 0x2811c7, + 0x2f6f04, + 0x66e00c02, + 0x2c1505, + 0x67217f83, + 0x235fc3, + 0x332505, + 0x34a9c3, + 0x67b4a9c6, + 0x3d048a, + 0x2a98c3, + 0x2371c4, 0x2003c6, - 0x2af186, - 0x66a42543, - 0x299047, - 0x237807, - 0x2a2c85, - 0x2e4406, - 0x222003, - 0x6960f7c3, - 0x69a00a82, - 0x69e0f044, - 0x3df689, - 0x21d685, - 0x356cc4, - 0x355b48, - 0x264bc5, - 0x6a231ac5, - 0x241f49, - 0x202503, - 0x33da04, - 0x6a614282, - 0x214283, - 0x6aa57b82, - 0x257b86, - 0x1677282, - 0x6ae15302, - 0x290b08, - 0x290e03, - 0x2bf287, - 0x2b9605, - 0x2b9185, - 0x2b918b, - 0x2eec86, - 0x2b9386, - 0x27d384, - 0x2efa86, - 0x6b321708, - 0x27fd03, - 0x265f03, - 0x265f04, - 0x2ed8c4, - 0x2f6a07, - 0x315645, - 0x6b72a5c2, - 0x6ba0a882, - 0x6c21bfc5, - 0x2c1044, - 0x2e0a0b, - 0x2f7688, - 0x253604, - 0x6c62c4c2, - 0x6ca1b742, - 0x3ba2c3, - 0x2f9484, - 0x2f9745, - 0x2fa147, - 0x6cefc304, - 0x378904, - 0x6d2141c2, - 0x37ab09, - 0x2fd745, - 0x2431c5, - 0x2fe2c5, - 0x6d6141c3, - 0x237f04, - 0x237f0b, - 0x2fedc4, - 0x2ff08b, - 0x3001c5, - 0x216eca, - 0x301708, - 0x30190a, - 0x3021c3, - 0x3021ca, - 0x6de11e42, - 0x6e214b42, - 0x6e615d43, - 0x6eadbd02, - 0x3068c3, - 0x6eef6702, - 0x6f333e42, - 0x309004, - 0x2177c6, - 0x399e05, - 0x30a643, - 0x298046, - 0x399905, - 0x3573c4, - 0x6f600902, - 0x299ec4, - 0x2d5dca, - 0x2ba807, - 0x33f5c6, - 0x234207, - 0x23e343, - 0x2c29c8, - 0x3d21cb, - 0x2bc9c5, - 0x2c8b85, - 0x2c8b86, - 0x34cb84, - 0x38ab88, - 0x21aa43, - 0x26ee44, - 0x3c3747, - 0x31d3c6, - 0x380b86, - 0x2c324a, - 0x24d804, - 0x31c0ca, - 0x6fb12606, - 0x312607, - 0x255c07, - 0x2a9a04, - 0x34a189, - 0x238dc5, - 0x307a4b, - 0x2f6603, - 0x20cc83, - 0x6fe1e243, - 0x22fb84, - 0x70200682, - 0x307e06, - 0x706c60c5, - 0x359345, - 0x24fc86, - 0x2a4944, - 0x70a013c2, - 0x241e84, - 0x70e0ca42, - 0x2160c5, - 0x3b2e44, - 0x71a1c5c3, - 0x71e0aa02, - 0x20aa03, - 0x21f646, - 0x72205142, - 0x393d08, - 0x2222c4, - 0x2222c6, - 0x391106, - 0x726574c4, - 0x21a205, - 0x356d88, - 0x3577c7, - 0x2ae247, - 0x2ae24f, - 0x292f46, - 0x23d183, - 0x242144, - 0x209043, - 0x221604, - 0x24e484, - 0x72a0b382, - 0x28d203, - 0x330983, - 0x72e090c2, - 0x215803, - 0x220f03, - 0x20e2ca, - 0x273847, - 0x25284c, - 0x73252b06, - 0x252c86, - 0x255407, - 0x7362e987, - 0x25a749, - 0x308784, - 0x73a5be04, - 0x73e023c2, - 0x742045c2, - 0x2c3606, - 0x298e44, - 0x28d686, - 0x22ee08, - 0x38b944, - 0x2eafc6, - 0x28ebc5, - 0x74750788, - 0x242343, - 0x3a6b85, - 0x3aa603, - 0x2432c3, - 0x2432c4, - 0x208dc3, - 0x74a499c2, - 0x74e02d42, - 0x2f64c9, - 0x290d05, - 0x291604, - 0x29ab05, - 0x206a84, - 0x286707, - 0x35a685, - 0x7523e804, - 0x2db988, - 0x2dcdc6, - 0x2e2d44, - 0x2e6e08, - 0x2e7447, - 0x75607842, - 0x2ef184, - 0x314cc4, - 0x2c9247, - 0x75a07844, - 0x24a682, - 0x75e02f82, - 0x210883, - 0x2e5ac4, - 0x299943, - 0x2b2cc5, - 0x7622ae42, - 0x309345, - 0x23c7c2, - 0x30f885, - 0x23c7c5, - 0x76607242, - 0x327704, - 0x76a071c2, - 0x33d486, - 0x2c8686, - 0x37fd88, - 0x2c9c08, - 0x380e04, - 0x3cdb05, - 0x310389, - 0x2f0684, - 0x3cabc4, - 0x288b03, - 0x26c703, - 0x76f02905, - 0x3829c5, - 0x283644, - 0x359b4d, - 0x294ec2, - 0x376403, - 0x77206382, - 0x77603242, - 0x3937c5, - 0x24b447, - 0x224244, - 0x32f2c9, - 0x2d5f09, - 0x2770c3, - 0x2770c8, - 0x312b09, - 0x21e7c7, - 0x77a08805, - 0x396406, - 0x3a06c6, - 0x3a8645, - 0x377285, - 0x77e01bc2, - 0x27a585, - 0x2bd4c8, - 0x2cb646, - 0x783b4347, - 0x2cf3c4, - 0x2da987, - 0x30b306, - 0x78601082, - 0x396586, - 0x30ef0a, - 0x30f785, - 0x78af00c2, - 0x78e11102, - 0x365486, - 0x211108, - 0x7928df87, - 0x79601402, - 0x214b83, - 0x3c0706, - 0x2caac4, - 0x346ac6, - 0x271ac6, - 0x26930a, - 0x2047c5, - 0x286f06, - 0x384643, - 0x384644, - 0x79a35002, - 0x2869c3, - 0x79e1a902, - 0x2ea903, - 0x7a218ac4, - 0x211244, - 0x7a61124a, - 0x21bd03, - 0x237ac7, - 0x313146, - 0x33c284, - 0x20d942, - 0x2aad42, - 0x7aa007c2, - 0x226e83, - 0x2559c7, + 0x2b1fc6, + 0x67e3e083, + 0x273987, + 0x26a647, + 0x2a3e85, + 0x2b2346, + 0x21a903, + 0x6aa25fc3, + 0x6ae00a82, + 0x6b20e9c4, + 0x213b49, + 0x226685, + 0x266e44, + 0x35a3c8, + 0x241e85, + 0x6b642285, + 0x247e89, + 0x3b4d43, + 0x349604, + 0x6ba05b42, + 0x216a43, + 0x6be75c42, + 0x275c46, + 0x167ce82, + 0x6c20c182, + 0x296448, + 0x29a743, + 0x2c5f87, + 0x384605, + 0x2be805, + 0x2be80b, + 0x2f0b06, + 0x2bea06, + 0x2804c4, + 0x211c86, + 0x6c6f1608, + 0x287403, + 0x25be43, + 0x25be44, + 0x2f0184, + 0x2f8747, + 0x318245, + 0x6cb20202, + 0x6ce04fc2, + 0x6d604fc5, + 0x2c6a84, + 0x2f114b, + 0x2f9188, + 0x306444, + 0x6da2c8c2, + 0x6de2d782, + 0x3c2f03, + 0x2faf84, + 0x2fb245, + 0x2fbd47, + 0x6e2fe604, + 0x390ec4, + 0x6e616982, + 0x380fc9, + 0x2ffa45, + 0x243bc5, + 0x3005c5, + 0x6ea16983, + 0x237e84, + 0x237e8b, + 0x3010c4, + 0x30138b, + 0x301f05, + 0x217bca, + 0x303dc8, + 0x303fca, + 0x304883, + 0x30488a, + 0x6f213982, + 0x6f642c42, + 0x6fa0d403, + 0x6fede302, + 0x307643, + 0x702f8442, + 0x70739c42, + 0x308544, + 0x218386, + 0x3350c5, + 0x30c343, + 0x32fc06, + 0x3a0645, + 0x366b44, + 0x70a00902, + 0x2ae704, + 0x2d810a, + 0x2c0587, + 0x34ad46, + 0x235407, + 0x23e883, + 0x2c92c8, + 0x3dc44b, + 0x2ce445, + 0x223585, + 0x223586, + 0x342604, + 0x3cd748, + 0x2198c3, + 0x28b144, + 0x3cdc87, + 0x2f6b46, + 0x314a06, + 0x2c86ca, + 0x24d544, + 0x3214ca, + 0x70f5ccc6, + 0x35ccc7, + 0x255d87, + 0x2ab784, + 0x34c349, + 0x238cc5, + 0x2f8343, + 0x2201c3, + 0x7121b843, + 0x231704, + 0x71600682, + 0x266886, + 0x71acbc45, + 0x31c385, + 0x2505c6, + 0x2a6184, + 0x71e02b02, + 0x2421c4, + 0x7220d782, + 0x20d785, + 0x37d504, + 0x7361a6c3, + 0x73a08382, + 0x208383, + 0x34d886, + 0x73e07742, + 0x399508, + 0x223e44, + 0x223e46, + 0x396906, + 0x74257784, + 0x217e05, + 0x368548, + 0x265c07, + 0x2b1087, + 0x2b108f, + 0x2980c6, + 0x23c0c3, + 0x23db04, + 0x219b43, + 0x222ac4, + 0x24c404, + 0x74606c82, + 0x2bef83, + 0x337143, + 0x74a08502, + 0x20cec3, + 0x30be83, + 0x21270a, + 0x279407, + 0x25070c, + 0x74e509c6, + 0x250b46, + 0x253b87, + 0x752302c7, + 0x259009, + 0x75666444, + 0x75a0a1c2, + 0x75e02442, + 0x2c8a86, + 0x273784, + 0x2bf406, + 0x230748, + 0x3926c4, + 0x2f7a46, + 0x2ada45, + 0x7628dc88, + 0x2424c3, + 0x292005, + 0x3ab143, + 0x243cc3, + 0x243cc4, + 0x21d2c3, + 0x7664b642, + 0x76a04782, + 0x2f8209, + 0x293a05, + 0x293d84, + 0x294545, + 0x210f44, + 0x28eec7, + 0x35ff05, + 0x772ddf84, + 0x2ddf88, + 0x2df1c6, + 0x2e5144, + 0x2e8988, + 0x2e8fc7, + 0x7760ab02, + 0x2f1004, + 0x219c04, + 0x2ceb87, + 0x77a0ab04, + 0x2670c2, + 0x77e0ee42, + 0x20ee43, + 0x248884, + 0x29a503, + 0x2b7085, + 0x78201442, + 0x308885, + 0x23cac2, + 0x312645, + 0x23cac5, + 0x786010c2, + 0x316a04, + 0x78a018c2, + 0x349086, + 0x25ab46, + 0x385648, + 0x2cf888, + 0x314c84, + 0x35a585, + 0x310489, + 0x39b604, + 0x3d0444, + 0x2132c3, + 0x237c83, + 0x78f1fb05, + 0x24fd85, + 0x28b044, + 0x35eacd, + 0x25cdc2, + 0x366543, + 0x79201702, + 0x79600ec2, + 0x398fc5, + 0x341947, + 0x227344, + 0x3c86c9, + 0x2d8249, + 0x25fc83, + 0x27ccc8, + 0x35d1c9, + 0x220f47, + 0x79b7b845, + 0x39d086, + 0x3a7d46, + 0x3ac645, + 0x2ee345, + 0x79e06242, + 0x28db85, + 0x2c4b48, + 0x2d1686, + 0x7a22aa87, + 0x2d1ec4, + 0x2d1447, + 0x30d006, + 0x7a603c02, + 0x39d206, + 0x311cca, + 0x312545, + 0x7aa30ac2, + 0x7ae92ec2, + 0x36c7c6, + 0x7b292ec7, + 0x7b60d982, + 0x242c83, + 0x3c75c6, + 0x2d0744, + 0x33ec86, + 0x24eac6, + 0x20290a, + 0x359945, + 0x35c986, + 0x38a183, + 0x38a184, + 0x7ba1cc42, + 0x28f183, + 0x7be1e202, + 0x2fccc3, + 0x7c215504, + 0x20de04, + 0x7c60de0a, + 0x219243, + 0x239747, + 0x315146, + 0x3670c4, + 0x281142, + 0x2ac982, + 0x7ca007c2, + 0x22b3c3, + 0x255b47, 0x2007c7, - 0x285d84, - 0x3da107, - 0x2fa246, - 0x210d47, - 0x220e44, - 0x2ae145, - 0x205345, - 0x7ae1e502, - 0x3d7286, - 0x220383, - 0x2266c2, - 0x2266c6, - 0x7b21f3c2, - 0x7b633442, - 0x29d005, - 0x7ba02c02, - 0x7be02982, - 0x324605, - 0x2d7505, - 0x2ac745, - 0x7c65b003, - 0x279a45, - 0x2eed47, - 0x36cc85, - 0x204985, - 0x261f44, - 0x264a46, - 0x38e104, - 0x7ca008c2, - 0x7d793085, - 0x3cb087, - 0x3c0bc8, - 0x253c46, - 0x253c4d, - 0x262d49, - 0x262d52, - 0x37a385, - 0x37ae03, - 0x7da09d42, - 0x3027c4, - 0x226603, - 0x3cb985, - 0x310f85, - 0x7de0c782, - 0x25a6c3, - 0x7e226dc2, - 0x7ea1d602, - 0x7ee00082, - 0x2e9bc5, - 0x207643, - 0x7f205b02, - 0x7f60c2c2, - 0x38a886, - 0x2d020a, - 0x215003, - 0x2579c3, - 0x2ff8c3, - 0x80e01b82, - 0x8f20c1c2, - 0x8fa0a5c2, - 0x203642, - 0x3ce689, - 0x2ce144, - 0x2dfac8, - 0x8ff04382, - 0x90606482, - 0x3bd905, - 0x233c88, - 0x231148, - 0x2f738c, - 0x2398c3, - 0x90a075c2, - 0x90e00f02, - 0x24ac46, - 0x313fc5, - 0x295b43, - 0x254686, - 0x314106, - 0x296b03, - 0x314c03, - 0x315046, - 0x316884, - 0x29cc86, - 0x23cd44, - 0x316f44, - 0x31784a, - 0x912b7402, - 0x24e705, - 0x3193ca, - 0x319305, - 0x31a7c4, - 0x31a8c6, - 0x31aa44, - 0x214546, - 0x91602b42, - 0x24c5c6, - 0x33bf85, - 0x286d87, - 0x33a106, - 0x255604, - 0x2e3407, - 0x234f85, - 0x23b687, - 0x3bc247, - 0x3bc24e, - 0x278646, - 0x222705, - 0x207787, - 0x20a783, - 0x3d3a47, - 0x20ab85, - 0x2123c4, - 0x22a8c2, - 0x325ec7, - 0x310cc4, - 0x23dec4, - 0x284a4b, - 0x21cb83, - 0x2c4907, - 0x21cb84, - 0x2c4c07, - 0x3a6603, - 0x34e40d, - 0x3a2f88, - 0x91a292c4, - 0x23e705, - 0x31b805, - 0x31bc43, - 0x91e221c2, - 0x31d1c3, - 0x31e083, - 0x3d7404, - 0x27bf85, - 0x220407, - 0x3846c6, - 0x38d943, - 0x22680b, - 0x249b8b, - 0x2acfcb, - 0x2c174b, - 0x3ccd4a, - 0x31734b, - 0x36ea8b, - 0x394e0c, - 0x3ada0b, - 0x3bf811, - 0x3dcf4a, - 0x31f58b, - 0x31f84c, - 0x31fb4b, - 0x3200ca, - 0x3209ca, - 0x3221ce, - 0x32294b, - 0x322c0a, - 0x324751, - 0x324b8a, - 0x32508b, - 0x3255ce, - 0x326c8c, - 0x32784b, - 0x327b0e, - 0x327e8c, - 0x328bca, - 0x329d4c, - 0x9232a04a, - 0x32a808, - 0x32b3c9, - 0x32ce8a, - 0x32d10a, - 0x32d38b, - 0x33010e, - 0x3316d1, - 0x33e209, - 0x33e44a, - 0x33ee8b, - 0x33fc0d, - 0x340a8a, - 0x341616, - 0x34298b, - 0x34668a, - 0x347d0a, - 0x3490cb, - 0x34aa49, - 0x34ed89, - 0x34f30d, - 0x34fe0b, - 0x351c8b, - 0x352509, - 0x352b4e, - 0x35328a, - 0x353dca, - 0x35438a, - 0x354a0b, - 0x35524b, - 0x3585cd, - 0x35a18d, - 0x35b050, - 0x35b50b, - 0x35ce4c, - 0x35d98b, - 0x35f44b, - 0x360c4e, - 0x36128b, - 0x36128d, - 0x3663cb, - 0x366e4f, - 0x36720b, - 0x36860a, - 0x368e49, - 0x369509, - 0x9276988b, - 0x369b4e, - 0x369ece, - 0x36be8b, - 0x36d64f, - 0x370acb, - 0x370d8b, - 0x37104b, - 0x37164a, - 0x3764c9, - 0x37964f, - 0x37e24c, - 0x37f30c, - 0x38058e, - 0x3810cf, - 0x38148e, - 0x381e50, - 0x38224f, - 0x382b4e, - 0x38320c, - 0x383511, - 0x383952, - 0x3856d1, - 0x385dce, - 0x38620b, - 0x38620e, - 0x38658f, - 0x38694e, - 0x386cd3, - 0x387191, - 0x3875cc, - 0x3878ce, - 0x387d4c, - 0x388293, - 0x388a90, - 0x389b8c, - 0x389e8c, - 0x38a34b, - 0x38ae4e, - 0x38b34b, - 0x38cb4b, - 0x38ddcc, - 0x39424a, - 0x39460c, - 0x39490c, - 0x394c09, - 0x396a0b, - 0x396cc8, - 0x397509, - 0x39750f, - 0x3991cb, - 0x92b9a54a, - 0x39bd0c, - 0x39cccb, - 0x39cf89, - 0x39d348, - 0x39da4b, - 0x39df4b, - 0x39eb8a, - 0x39ee0b, - 0x39f78c, - 0x3a0149, - 0x3a0388, - 0x3a3d0b, - 0x3a6f4b, - 0x3a91ce, - 0x3aaf4b, - 0x3ad38b, - 0x3bbdcb, - 0x3bc089, - 0x3bc5cd, - 0x3cbe4a, - 0x3cf5d7, - 0x3d18d8, - 0x3d5909, - 0x3d6b0b, - 0x3d79d4, - 0x3d7ecb, - 0x3d844a, - 0x3d894a, - 0x3d8bcb, - 0x3da790, - 0x3dab91, - 0x3db24a, - 0x3dc54d, - 0x3dcc4d, - 0x3e06cb, - 0x3d7383, - 0x92f9b403, - 0x289b06, - 0x246085, - 0x30ccc7, - 0x2ef746, - 0x165c942, - 0x270b89, - 0x297e44, - 0x2ed408, - 0x21e183, - 0x302707, - 0x205602, - 0x2b5503, - 0x93201442, - 0x2d69c6, - 0x2d8084, - 0x38f1c4, - 0x268643, - 0x93ad3982, - 0x93e2a784, - 0x34a0c7, - 0x9422a502, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x105dc8, - 0x203dc3, + 0x28e544, + 0x3e2587, + 0x2fbe46, + 0x20f307, + 0x30bdc4, + 0x2e5d45, + 0x218ac5, + 0x7ce05682, + 0x216f86, + 0x227043, + 0x227ec2, + 0x227ec6, + 0x7d21c882, + 0x7d62dc42, + 0x238f85, + 0x7da03d02, + 0x7de02a82, + 0x353545, + 0x2d9845, + 0x2af105, + 0x7e65aa03, + 0x279185, + 0x2f0bc7, + 0x2b7945, + 0x359b05, + 0x268b84, + 0x266cc6, + 0x3944c4, + 0x7ea008c2, + 0x7f798885, + 0x3d0907, + 0x3a09c8, + 0x269f86, + 0x269f8d, + 0x26f7c9, + 0x26f7d2, + 0x34d185, + 0x380843, + 0x7fa03b42, + 0x31f9c4, + 0x22db83, + 0x393e85, + 0x313785, + 0x7fe1fcc2, + 0x259fc3, + 0x8022b302, + 0x80a1cac2, + 0x80e00082, + 0x2ec2c5, + 0x213fc3, + 0x81208f02, + 0x81604642, + 0x3c1706, + 0x27e1ca, + 0x20c6c3, + 0x257c83, + 0x2f7343, + 0x832072c2, + 0x9161f702, + 0x91e07ac2, + 0x2034c2, + 0x3d3d09, + 0x2d4584, + 0x2e1c88, + 0x92305102, + 0x92a01502, + 0x2c2285, + 0x234e88, + 0x2f65c8, + 0x2fb70c, + 0x239683, + 0x92e13f42, + 0x9320e482, + 0x2bce06, + 0x315fc5, + 0x2e5583, + 0x247cc6, + 0x316106, + 0x253383, + 0x317803, + 0x317c46, + 0x319484, + 0x26aa06, + 0x236444, + 0x319b44, + 0x31ad0a, + 0x936bb102, + 0x24e605, + 0x31c58a, + 0x31c4c5, + 0x31e504, + 0x31e606, + 0x31e784, + 0x216d06, + 0x93a03c42, + 0x2ecf86, + 0x358f85, + 0x35c807, + 0x3c7386, + 0x253d84, + 0x2e5807, + 0x21dfc5, + 0x21dfc7, + 0x3c3a87, + 0x3c3a8e, + 0x280bc6, + 0x2bda05, + 0x20aa47, + 0x20e243, + 0x20e247, + 0x228f05, + 0x22bfc4, + 0x368842, + 0x32a1c7, + 0x241184, + 0x32a684, + 0x3ab1cb, + 0x21ab83, + 0x2dd0c7, + 0x21ab84, + 0x2dd3c7, + 0x3ae243, + 0x34f8cd, + 0x3aa588, + 0x93e45f84, + 0x366dc5, + 0x31f345, + 0x31f783, + 0x94223d42, + 0x322283, + 0x322b03, + 0x217104, + 0x283c85, + 0x224e87, + 0x38a206, + 0x393c43, + 0x22ad4b, + 0x322c8b, + 0x283d8b, + 0x2b32cb, + 0x2c718a, + 0x2d184b, + 0x2f1b4b, + 0x35ab4c, + 0x319f4b, + 0x374b91, + 0x39ad0a, + 0x3b794b, + 0x3c694c, + 0x3df28b, + 0x3256ca, + 0x325bca, + 0x326a4e, + 0x3271cb, + 0x32748a, + 0x328a51, + 0x328e8a, + 0x32938b, + 0x3298ce, + 0x32b70c, + 0x32c34b, + 0x32c60e, + 0x32c98c, + 0x32d6ca, + 0x32ee8c, + 0x9472f18a, + 0x32fd88, + 0x330949, + 0x33308a, + 0x33330a, + 0x33358b, + 0x3368ce, + 0x337751, + 0x341dc9, + 0x34200a, + 0x342b4b, + 0x34348d, + 0x34430a, + 0x3455d6, + 0x34694b, + 0x349e0a, + 0x34a38a, + 0x34b28b, + 0x34cc09, + 0x350249, + 0x3507cd, + 0x3510cb, + 0x352bcb, + 0x353689, + 0x353cce, + 0x35410a, + 0x35a04a, + 0x35a7ca, + 0x35b18b, + 0x35b9cb, + 0x35e2cd, + 0x35fa0d, + 0x360310, + 0x3607cb, + 0x36210c, + 0x36288b, + 0x36494b, + 0x36614e, + 0x36660b, + 0x36660d, + 0x36d70b, + 0x36e18f, + 0x36e54b, + 0x36f50a, + 0x36fb09, + 0x370089, + 0x94b7040b, + 0x3706ce, + 0x370a4e, + 0x3726cb, + 0x37374f, + 0x375fcb, + 0x37628b, + 0x37654a, + 0x37af49, + 0x37fa0f, + 0x3841cc, + 0x384bcc, + 0x385ece, + 0x38644f, + 0x38680e, + 0x3871d0, + 0x3875cf, + 0x3883ce, + 0x388f0c, + 0x389211, + 0x389652, + 0x38b3d1, + 0x38be8e, + 0x38c2cb, + 0x38c2ce, + 0x38c64f, + 0x38ca0e, + 0x38cd93, + 0x38d251, + 0x38d68c, + 0x38d98e, + 0x38de0c, + 0x38e353, + 0x38f1d0, + 0x3902cc, + 0x3905cc, + 0x390a8b, + 0x391bce, + 0x3920cb, + 0x392e4b, + 0x39418c, + 0x399a4a, + 0x39a50c, + 0x39a80c, + 0x39ab09, + 0x39d68b, + 0x39d948, + 0x39e649, + 0x39e64f, + 0x39ff0b, + 0x94fa0bca, + 0x3a268c, + 0x3a364b, + 0x3a3909, + 0x3a3cc8, + 0x3a458b, + 0x3a688a, + 0x3a6b0b, + 0x3a700c, + 0x3a77c9, + 0x3a7a08, + 0x3ab48b, + 0x3aeb8b, + 0x3b0d0e, + 0x3b244b, + 0x3b72cb, + 0x3c360b, + 0x3c38c9, + 0x3c3e0d, + 0x3d148a, + 0x3d4917, + 0x3d5618, + 0x3d8989, + 0x3d9ccb, + 0x3daad4, + 0x3dafcb, + 0x3db54a, + 0x3dbc0a, + 0x3dbe8b, + 0x3dd190, + 0x3dd591, + 0x3ddc4a, + 0x3de88d, + 0x3def8d, + 0x3e104b, + 0x217083, + 0x953b3583, + 0x2b0f46, + 0x27ca85, + 0x29c647, + 0x384906, + 0x1602342, + 0x2b3609, + 0x32fa04, + 0x2efcc8, + 0x21b783, + 0x31f907, + 0x230902, + 0x2b8f03, + 0x95603602, + 0x2d8d06, + 0x2da3c4, + 0x377084, + 0x201c43, + 0x95ed56c2, + 0x9622c344, + 0x34c287, + 0x9662bf82, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x106b48, + 0x205803, 0x2000c2, - 0x9a048, - 0x201242, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x20e2c3, - 0x337396, - 0x364d53, - 0x3d9f89, - 0x2135c8, - 0x3b1449, - 0x319546, - 0x351190, - 0x20dcd3, - 0x31d488, - 0x277e87, - 0x279e87, - 0x2a86ca, - 0x343189, - 0x267d49, - 0x2d368b, - 0x303c06, - 0x30334a, - 0x2205c6, - 0x32a4c3, - 0x2e2905, - 0x3ba348, - 0x27decd, - 0x2f330c, - 0x2ec347, - 0x30bfcd, - 0x2136c4, - 0x22fe4a, - 0x23134a, - 0x23180a, - 0x20dfc7, - 0x23cb87, - 0x240104, - 0x273506, - 0x348a44, - 0x304c08, - 0x289909, - 0x2e6606, - 0x2e6608, - 0x24360d, - 0x2d6149, - 0x392488, - 0x243147, - 0x3b27ca, - 0x250086, - 0x2fd244, - 0x212107, - 0x30800a, - 0x3ab68e, - 0x277185, - 0x3daf8b, - 0x226bc9, - 0x22e0c9, - 0x2b3147, - 0x3d090a, - 0x2c9187, - 0x2ff649, - 0x33b048, - 0x2a5e8b, - 0x2ec0c5, - 0x22c50a, - 0x223d49, - 0x295aca, - 0x20f30b, - 0x21200b, - 0x2d3415, - 0x2c8205, - 0x2431c5, - 0x237f0a, - 0x22b98a, - 0x2f5d87, - 0x233dc3, - 0x2c3588, - 0x2e0eca, - 0x2222c6, - 0x259c09, - 0x350788, - 0x2e2d44, - 0x388049, - 0x2c9c08, - 0x2ca947, - 0x393086, - 0x3cb087, - 0x2be807, - 0x23f5c5, - 0x2d314c, - 0x23e705, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x201242, - 0x214a83, - 0x21a3c3, - 0x203dc3, - 0x242543, - 0x214a83, - 0x21a3c3, - 0x3dc3, - 0x2624c3, - 0x242543, - 0x1cc203, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x9a048, - 0x201242, - 0x214a83, - 0x22ca07, - 0x86504, - 0x21a3c3, - 0x97a04, - 0x242543, - 0x201242, - 0x2052c2, - 0x3192c2, - 0x207882, - 0x201582, - 0x2eda82, - 0x908c6, - 0x50849, - 0xf3fc7, - 0x481c5c3, - 0x86107, - 0x148406, - 0x7783, - 0x11af85, + 0xae888, + 0x212402, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0x208503, + 0x33cb96, + 0x36c093, + 0x3e2409, + 0x215d88, + 0x2c1389, + 0x31c706, + 0x3520d0, + 0x212113, + 0x2f6c08, + 0x282247, + 0x28d487, + 0x2aaa8a, + 0x36a609, + 0x3573c9, + 0x24cd4b, + 0x34b706, + 0x32ce4a, + 0x221106, + 0x32f603, + 0x2e4d05, + 0x20f4c8, + 0x28598d, + 0x2f45cc, + 0x3033c7, + 0x30e60d, + 0x215e84, + 0x2319ca, + 0x23248a, + 0x23294a, + 0x212407, + 0x23ce87, + 0x2410c4, + 0x269c06, + 0x35d584, + 0x305988, + 0x3c0509, + 0x2e9f06, + 0x2e9f08, + 0x24400d, + 0x2d8489, + 0x397c88, + 0x243b47, + 0x33230a, + 0x251186, + 0x2ff544, + 0x225c07, + 0x266a8a, + 0x23fb8e, + 0x246145, + 0x3dd98b, + 0x22b109, + 0x247109, + 0x205447, + 0x20544a, + 0x2ceac7, + 0x301949, + 0x347c88, + 0x33284b, + 0x2ee705, + 0x22c90a, + 0x265dc9, + 0x3568ca, + 0x21b8cb, + 0x225b0b, + 0x24cad5, + 0x2ce085, + 0x243bc5, + 0x237e8a, + 0x2527ca, + 0x321a07, + 0x234fc3, + 0x2c8a08, + 0x2e32ca, + 0x223e46, + 0x256689, + 0x28dc88, + 0x2e5144, + 0x38e109, + 0x2cf888, + 0x2d05c7, + 0x398886, + 0x3d0907, + 0x2c51c7, + 0x2401c5, + 0x245f8c, + 0x366dc5, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x5803, + 0x23e083, + 0x212402, + 0x22ea43, + 0x217fc3, + 0x205803, + 0x23e083, + 0x22ea43, + 0x217fc3, + 0x5803, + 0x269543, + 0x23e083, + 0x1d1843, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0xae888, + 0x212402, + 0x22ea43, + 0x22ea47, + 0x8ecc4, + 0x217fc3, + 0x1b5c04, + 0x23e083, + 0x212402, + 0x204542, + 0x2f6e82, + 0x2022c2, + 0x202582, + 0x2f2402, + 0x96206, + 0x51709, + 0xe9bc7, + 0x481a6c3, + 0x8e8c7, + 0x154546, + 0xaa43, + 0x11eec5, 0xc1, - 0x5214a83, - 0x232dc3, - 0x228503, - 0x308003, - 0x21bc83, - 0x23c803, - 0x2e2806, - 0x21a3c3, - 0x242543, - 0x233d43, - 0x9a048, - 0x345b44, - 0x296c87, - 0x268683, - 0x2bad84, - 0x2187c3, - 0x284d43, - 0x308003, - 0x17e707, + 0x522ea43, + 0x233fc3, + 0x280203, + 0x266a83, + 0x2191c3, + 0x23cb03, + 0x2e4c06, + 0x217fc3, + 0x23e083, + 0x234f43, + 0xae888, + 0x3b46c4, + 0x324547, + 0x201c83, + 0x39e284, + 0x2052c3, + 0x2054c3, + 0x266a83, + 0x178d87, 0x9c4, - 0x4e83, - 0x68b05, + 0x157bc3, + 0x2105, 0x66000c2, - 0x2703, - 0x6a01242, - 0x6c8c109, - 0x8c98d, - 0x8cccd, - 0x3192c2, - 0x21dc4, - 0x68b49, + 0x4ac43, + 0x6a12402, + 0x6e8b749, + 0x7091e09, + 0x923cd, + 0x9270d, + 0x2f6e82, + 0xe704, + 0x2149, 0x2003c2, - 0x7221cc8, - 0xfe7c4, - 0x31c843, - 0x9a048, - 0x1414882, + 0x7623188, + 0x100ac4, + 0x320c03, + 0xae888, + 0x41184, + 0x140ea82, 0x14005c2, - 0x1414882, - 0x1517146, - 0x22f043, - 0x26f6c3, - 0x7a14a83, - 0x22fe44, - 0x7e32dc3, - 0x8b08003, - 0x206182, - 0x221dc4, - 0x21a3c3, - 0x3b1e83, - 0x204042, - 0x242543, - 0x202642, - 0x308f43, - 0x205142, - 0x2263c3, - 0x223a43, - 0x201342, - 0x9a048, - 0x22f043, - 0x3df888, - 0x83b1e83, - 0x204042, - 0x308f43, - 0x205142, - 0x86263c3, - 0x223a43, - 0x201342, - 0x252b07, - 0x232dc9, - 0x308f43, - 0x205142, - 0x2263c3, - 0x223a43, - 0x201342, - 0x214a83, - 0x16c2, - 0x32443, - 0x3c42, - 0xaac82, - 0x5cd82, - 0x17c2, - 0x1b82, - 0x43342, - 0x202703, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21bc83, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x20eb02, - 0x2141c3, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x202703, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21a3c3, - 0x242543, - 0x208805, - 0x20c782, + 0x140ea82, + 0x1519d46, + 0x230983, + 0x276243, + 0x7e2ea43, + 0x2319c4, + 0x8233fc3, + 0x8a66a83, + 0x209582, + 0x20e704, + 0x217fc3, + 0x3319c3, + 0x209282, + 0x23e083, + 0x2188c2, + 0x308483, + 0x207742, + 0x203b83, + 0x222403, + 0x207d02, + 0xae888, + 0x230983, + 0x210448, + 0x87319c3, + 0x209282, + 0x308483, + 0x207742, + 0x203b83, + 0x222403, + 0x207d02, + 0x2509c7, + 0x308483, + 0x207742, + 0x203b83, + 0x222403, + 0x207d02, + 0x22ea43, + 0x6c02, + 0xf4c3, + 0x31c2, + 0x293c2, + 0x4d82, + 0x8c82, + 0x72c2, + 0x43d42, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x2191c3, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x201b02, + 0x216983, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x24ac43, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x217fc3, + 0x23e083, + 0x37b845, + 0x21fcc2, 0x2000c2, - 0x9a048, - 0x144ca88, - 0x12848a, - 0x308003, - 0x225cc1, + 0xae888, + 0x1454408, + 0x7b64a, + 0x266a83, + 0x202881, 0x2009c1, 0x200a01, - 0x204ac1, - 0x204781, - 0x20a541, - 0x201941, - 0x225dc1, - 0x23ff81, + 0x201781, + 0x202101, + 0x20bac1, + 0x201d01, + 0x203001, + 0x230d41, 0x200001, 0x2000c1, 0x200201, - 0x139b05, - 0x9a048, + 0x146bc5, + 0xae888, 0x200101, - 0x201301, + 0x201381, 0x200501, - 0x205dc1, + 0x201281, 0x200041, 0x200801, 0x200181, @@ -2348,7193 +2344,7257 @@ var nodes = [...]uint32{ 0x200581, 0x2003c1, 0x200a81, - 0x215481, + 0x20c241, 0x200401, 0x200741, 0x2007c1, 0x200081, - 0x200f01, - 0x201341, - 0x204f01, - 0x201b41, - 0x201441, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x201242, - 0x214a83, - 0x232dc3, + 0x201501, + 0x207d01, + 0x20a8c1, + 0x202341, + 0x201c41, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x212402, + 0x22ea43, + 0x233fc3, 0x2003c2, - 0x242543, - 0x1bf83, - 0x17e707, - 0xd1407, - 0x28886, - 0x34b8a, - 0x8b848, - 0x54e08, - 0x558c7, - 0x174586, - 0xea585, - 0x97805, - 0x125483, - 0x11ec6, - 0x365c6, - 0x2d3684, - 0x328147, - 0x9a048, - 0x2e3504, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x1242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x32a248, - 0x204244, - 0x232d04, - 0x229904, - 0x24ab47, - 0x2e0007, - 0x214a83, - 0x235b4b, - 0x29650a, - 0x33c147, - 0x23bc48, - 0x33b888, - 0x232dc3, - 0x287847, - 0x228503, - 0x206f88, - 0x2130c9, - 0x221dc4, - 0x21bc83, - 0x23b248, - 0x23c803, - 0x2dd74a, - 0x2e2806, - 0x3a4987, - 0x21a3c3, - 0x267906, - 0x26f548, - 0x242543, - 0x24d446, - 0x2f78cd, - 0x2f9e08, - 0x2fedcb, - 0x20eb46, - 0x24b347, - 0x2225c5, - 0x21674a, - 0x308245, - 0x3828ca, - 0x20c782, - 0x207783, - 0x23dec4, + 0x23e083, + 0x1a083, + 0x178d87, + 0x7f3c7, + 0x36fc6, + 0x3a8ca, + 0x91248, + 0x54d88, + 0x55a47, + 0x6e8c6, + 0xec7c5, + 0x1b5a05, + 0x129783, + 0x13a06, + 0x134c46, + 0x24cd44, + 0x334907, + 0xae888, + 0x2e5904, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x12402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x32f388, + 0x207d44, + 0x233f04, + 0x204cc4, + 0x2bcd07, + 0x2e21c7, + 0x22ea43, + 0x23670b, + 0x323dca, + 0x34b9c7, + 0x238548, + 0x354a88, + 0x233fc3, + 0x25e4c7, + 0x280203, + 0x211448, + 0x212e49, + 0x20e704, + 0x2191c3, + 0x23b948, + 0x23cb03, + 0x2dfb4a, + 0x2e4c06, + 0x3b0107, + 0x217fc3, + 0x323606, + 0x2760c8, + 0x23e083, + 0x257546, + 0x2f93cd, + 0x2fba08, + 0x3010cb, + 0x2b2946, + 0x341847, + 0x21ecc5, + 0x3da84a, + 0x22ac05, + 0x24fc8a, + 0x21fcc2, + 0x20aa43, + 0x32a684, 0x200006, - 0x3b05c3, - 0x299f43, - 0x27ee03, - 0x204243, - 0x296183, - 0x2041c2, - 0x355dc5, - 0x2ad8c9, - 0x23fc43, - 0x220dc3, - 0x21fdc3, + 0x3ba683, + 0x2ae783, + 0x281bc3, + 0x207d43, + 0x323a43, + 0x2029c2, + 0x309b85, + 0x2b07c9, + 0x201ac3, + 0x240843, + 0x233f03, + 0x232283, 0x200201, - 0x2f0447, - 0x2e9905, - 0x3b5c03, - 0x3d6d83, - 0x229904, - 0x343a43, - 0x20ff88, - 0x35d143, - 0x30d98d, - 0x278708, - 0x3dfa46, - 0x286a03, - 0x361583, - 0x38e083, - 0xce14a83, - 0x232608, - 0x235b44, - 0x240983, + 0x39b3c7, + 0x2ec005, + 0x3c2003, + 0x2a4d43, + 0x3dff03, + 0x204cc4, + 0x356e43, + 0x227608, + 0x322bc3, + 0x310c4d, + 0x280c88, + 0x210606, + 0x28f1c3, + 0x366903, + 0x394443, + 0xce2ea43, + 0x233808, + 0x236704, + 0x23d3c3, + 0x241283, 0x200106, - 0x243d88, - 0x27b0c3, - 0x216783, - 0x22d1c3, - 0x232dc3, - 0x21afc3, - 0x2532c3, - 0x283603, - 0x286983, - 0x2cbf83, - 0x2196c3, - 0x38b5c5, - 0x250804, - 0x251987, - 0x22dec2, - 0x254483, - 0x257d06, - 0x2592c3, - 0x25a283, - 0x277083, - 0x374e43, - 0x345843, - 0x29c047, - 0xd308003, - 0x2425c3, - 0x286a43, - 0x206c03, - 0x21bac3, - 0x24c903, - 0x20ef85, - 0x373c83, - 0x200e09, - 0x20bb83, - 0x311283, - 0xd63c883, - 0x2d3b03, - 0x219208, - 0x2ad806, - 0x374c06, - 0x2b7106, - 0x389147, - 0x227d43, - 0x2137c3, - 0x23c803, - 0x28b946, - 0x20f002, - 0x267d83, - 0x353145, - 0x21a3c3, - 0x319e87, - 0x1603dc3, - 0x202903, - 0x2089c3, - 0x21fec3, - 0x26d243, - 0x242543, - 0x209006, - 0x3b5f86, - 0x37a243, - 0x2f8a83, - 0x2141c3, - 0x220ec3, - 0x314c83, - 0x305fc3, - 0x309303, - 0x399905, - 0x22b983, - 0x39f446, - 0x2d1cc8, - 0x20cc83, - 0x20cc89, - 0x298948, - 0x223488, - 0x229a85, - 0x22f18a, - 0x23818a, - 0x239b4b, - 0x23b808, - 0x398943, - 0x38da83, - 0x30a583, - 0x326f48, - 0x376dc3, - 0x384644, - 0x235002, - 0x25ca83, + 0x244e88, + 0x20f983, + 0x21fa43, + 0x2b6ec3, + 0x222383, + 0x3da883, + 0x22f203, + 0x233fc3, + 0x22d003, + 0x249203, + 0x24cbc3, + 0x28b003, + 0x28f143, + 0x20a003, + 0x265743, + 0x392345, + 0x2516c4, + 0x252a47, + 0x2ba882, + 0x254b03, + 0x258106, + 0x259243, + 0x259c43, + 0x27cc83, + 0x26f183, + 0x20b183, + 0x3b43c3, + 0x29d847, + 0xd266a83, + 0x2c3fc3, + 0x28f203, + 0x204903, + 0x20e703, + 0x2ed2c3, + 0x20e905, + 0x37fd83, + 0x24b709, + 0x2012c3, + 0x313a83, + 0xd63cb83, + 0x2d5e43, + 0x204d03, + 0x218bc8, + 0x2b0706, + 0x26ef46, + 0x2ba8c6, + 0x38f887, + 0x205e03, + 0x215f83, + 0x23cb03, + 0x291346, + 0x20e982, + 0x2b8a83, + 0x33b645, + 0x217fc3, + 0x31da07, + 0x1605803, + 0x2760c3, + 0x212483, + 0x232383, + 0x235fc3, + 0x23e083, + 0x21d506, + 0x3b5d46, + 0x380703, + 0x2fa583, + 0x216983, + 0x250983, + 0x317883, + 0x306d43, + 0x308843, + 0x3a0645, + 0x235403, + 0x3b2a86, + 0x221d43, + 0x27fc88, + 0x2201c3, + 0x2201c9, + 0x273288, + 0x221e48, + 0x225645, + 0x36000a, + 0x38e84a, + 0x22f98b, + 0x238108, + 0x294983, + 0x2f2a03, + 0x393d83, + 0x39fa83, + 0x316248, + 0x37a903, + 0x38a184, + 0x21cc42, + 0x20de03, + 0x260e03, 0x2007c3, - 0x356c43, - 0x263343, - 0x233d43, - 0x20c782, - 0x229e43, - 0x2398c3, - 0x3172c3, - 0x318284, - 0x23dec4, - 0x20fe43, - 0x9a048, + 0x22dc43, + 0x27b143, + 0x234f43, + 0x21fcc2, + 0x22b8c3, + 0x239683, + 0x319ec3, + 0x31b744, + 0x32a684, + 0x21cb03, + 0xae888, 0x2000c2, 0x200ac2, - 0x2041c2, - 0x204b42, + 0x2029c2, + 0x201802, 0x200202, - 0x204342, - 0x240702, - 0x203c42, + 0x205082, + 0x249382, + 0x2031c2, 0x200382, 0x200c42, - 0x33d642, - 0x202382, - 0x26c9c2, + 0x349242, + 0x20a942, + 0x2720c2, 0x200a82, - 0x2eda82, - 0x214282, - 0x205742, - 0x2141c2, - 0x2c1902, - 0x2069c2, + 0x2f2402, + 0x205b42, + 0x211c82, + 0x216982, + 0x206002, + 0x205502, 0x200682, - 0x206f02, - 0x2013c2, - 0x2090c2, - 0x2045c2, - 0x26c702, - 0x202982, + 0x2113c2, + 0x202b02, + 0x208502, + 0x202442, + 0x207142, + 0x202a82, 0xc2, 0xac2, - 0x41c2, - 0x4b42, + 0x29c2, + 0x1802, 0x202, - 0x4342, - 0x40702, - 0x3c42, + 0x5082, + 0x49382, + 0x31c2, 0x382, 0xc42, - 0x13d642, - 0x2382, - 0x6c9c2, + 0x149242, + 0xa942, + 0x720c2, 0xa82, - 0xeda82, - 0x14282, - 0x5742, - 0x141c2, - 0xc1902, - 0x69c2, + 0xf2402, + 0x5b42, + 0x11c82, + 0x16982, + 0x6002, + 0x5502, 0x682, - 0x6f02, - 0x13c2, - 0x90c2, - 0x45c2, - 0x6c702, - 0x2982, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x7782, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x1242, - 0x201242, - 0x242543, - 0xee14a83, - 0x308003, - 0x23c803, - 0x1b4103, - 0x22aec2, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x3dc3, - 0x1b4103, - 0x242543, - 0x1442, + 0x113c2, + 0x2b02, + 0x8502, + 0x2442, + 0x7142, + 0x2a82, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x83c2, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x12402, + 0x212402, + 0x23e083, + 0xee2ea43, + 0x266a83, + 0x23cb03, + 0x1c0443, + 0x230242, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x5803, + 0x1c0443, + 0x23e083, + 0x3602, 0x2001c2, - 0x15c45c5, - 0x139b05, - 0x20b3c2, - 0x9a048, - 0x1242, - 0x2347c2, - 0x206782, - 0x204642, - 0x21bb02, - 0x230a42, - 0x97805, - 0x202f42, - 0x204042, - 0x206e42, - 0x205e42, - 0x214282, - 0x23fcc2, - 0x202f82, - 0x292882, - 0xfe98384, + 0x1567b85, + 0x146bc5, + 0x210402, + 0xae888, + 0x12402, + 0x2359c2, + 0x206b02, + 0x208142, + 0x20e742, + 0x23bec2, + 0x1b5a05, + 0x201402, + 0x209282, + 0x201102, + 0x2053c2, + 0x205b42, + 0x2408c2, + 0x20ee42, + 0x256382, + 0xfe72cc4, 0x142, - 0x17e707, - 0x12380d, - 0xea609, - 0x115e0b, - 0xeec08, - 0x65dc9, - 0x111b86, - 0x308003, - 0x9a048, + 0x178d87, + 0x30a83, + 0x12808d, + 0xec849, + 0x118a0b, + 0xf0a88, + 0x5bd09, + 0x1145c6, + 0x266a83, + 0xae888, 0x9c4, - 0x4e83, - 0x68b05, - 0x9a048, - 0xe5a47, - 0x56306, - 0x68b49, - 0x1d134e, - 0x14a887, + 0x157bc3, + 0x2105, + 0xae888, + 0xe7607, + 0x1104d007, + 0x56546, + 0x2149, + 0xa28e, + 0x14ca47, + 0x150e583, 0x2000c2, - 0x2d3684, - 0x201242, - 0x214a83, - 0x2052c2, - 0x232dc3, - 0x1bb43, + 0x24cd44, + 0x212402, + 0x22ea43, + 0x204542, + 0x233fc3, + 0xfa03, 0x200382, - 0x2e3504, - 0x21bc83, - 0x201f42, - 0x21a3c3, - 0x30a42, + 0x2e5904, + 0x2191c3, + 0x206a02, + 0x217fc3, + 0x3bec2, 0x2003c2, - 0x242543, - 0x2431c6, - 0x32d94f, + 0x23e083, + 0x243bc6, + 0x333b4f, 0x602, - 0x725e43, - 0x2f294a, - 0x9a048, - 0x201242, - 0x228503, - 0x308003, - 0x23c803, - 0x3dc3, - 0x1467206, - 0x1d1348, - 0x141650b, - 0x156518a, - 0xf1fc9, - 0x15d024a, - 0x1511707, - 0xa878b, - 0x10b7c5, - 0xebbc5, - 0x119bc9, - 0x139b05, - 0x17e707, - 0xfbfc4, - 0x201242, - 0x214a83, - 0x308003, - 0x21a3c3, + 0x72a143, + 0x2f3c0a, + 0xae888, + 0x212402, + 0x280203, + 0x266a83, + 0x23cb03, + 0x5803, + 0x1522f06, + 0x1c4104, + 0xa288, + 0x140dbcb, + 0x156c4ca, + 0xf3289, + 0x15da64a, + 0x1513f07, + 0xaab4b, + 0x10d4c5, + 0xf0545, + 0x11d749, + 0x146bc5, + 0x178d87, + 0x1c4104, + 0xfe2c4, + 0x212402, + 0x22ea43, + 0x266a83, + 0x217fc3, 0x2000c2, 0x200c82, - 0x2019c2, - 0x13214a83, - 0x23d342, - 0x232dc3, - 0x20bb42, - 0x2299c2, - 0x308003, - 0x23c782, - 0x25d282, - 0x22a742, + 0x205102, + 0x1362ea43, + 0x23d542, + 0x233fc3, + 0x201282, + 0x208882, + 0x266a83, + 0x23ca82, + 0x27b882, + 0x22c302, 0x200cc2, - 0x290602, + 0x295f42, 0x200802, 0x200d82, - 0x23ee42, - 0x27b8c2, - 0x204702, - 0x1b19cc, - 0x2b8e42, - 0x252e82, - 0x2203c2, - 0x248642, - 0x23c803, - 0x200bc2, - 0x21a3c3, - 0x243802, - 0x249b42, - 0x242543, - 0x308c82, - 0x2090c2, - 0x2023c2, - 0x202d42, - 0x207242, - 0x2f00c2, - 0x21e502, - 0x226dc2, - 0x223fc2, - 0x322c0a, - 0x36860a, - 0x39abca, - 0x3e0d02, - 0x210702, - 0x20ef42, - 0x1376fcc9, - 0x13b5cbca, - 0x142e307, - 0x13e026c2, - 0x14fe3c3, - 0x4a82, - 0x15cbca, - 0x15dc0e, - 0x24c0c4, - 0x572c5, - 0x14614a83, - 0x3dc83, - 0x232dc3, - 0x24d9c4, - 0x308003, - 0x221dc4, - 0x21bc83, - 0x137a89, - 0x68006, - 0x23c803, - 0xefa04, - 0x4743, - 0x21a3c3, - 0x1df105, - 0x203dc3, - 0x242543, - 0x1464b04, - 0x22b983, - 0x11b504, - 0x207783, - 0x9a048, - 0x1521403, - 0x125d86, - 0x1574504, - 0x68445, - 0x14a64a, - 0x129cc2, - 0x1500160d, - 0x1a6286, - 0x15291, - 0x1576fcc9, - 0x684c8, - 0x62888, - 0x1c12c707, - 0x1182, - 0x16fe47, - 0x2380e, - 0x139b0b, - 0x13f10b, - 0x1b3d4a, - 0x29907, - 0x9a048, - 0x11c988, - 0x7bc7, - 0x1c4169cb, - 0x1bf87, - 0xcd42, - 0x26ccd, - 0x1c2a07, - 0xaed8a, - 0x1d92cf, - 0x6738f, - 0x167c2, - 0x1242, - 0x83548, - 0x1c8f48cc, - 0xe770a, - 0xe554a, - 0x18990a, - 0x78508, - 0x8d08, - 0x5aa88, - 0xe5a08, - 0x145e88, - 0x2a42, - 0x1c464f, - 0xc134b, - 0x79108, - 0x25687, - 0x14474a, - 0x2490b, - 0x33249, - 0x46e07, - 0x8c08, - 0x3834c, - 0x15c087, - 0x1a67ca, - 0x106c8, - 0x2888e, - 0x2904e, - 0x2974b, - 0x2aa8b, - 0x15748b, - 0x14bf09, - 0xe3b0b, - 0xec58d, - 0x1261cb, - 0x30b4d, - 0x30ecd, - 0x3640a, - 0x3dd0b, - 0x3e54b, - 0x46405, - 0x1cd79a10, - 0x199e8f, - 0x9854f, - 0x63c4d, - 0x137c50, - 0xaac82, - 0x1d20c388, - 0xd1288, - 0xe8090, - 0xcf48e, - 0x1d75d105, - 0x4d1cb, - 0x136b90, - 0x8e0a, - 0x2ac49, - 0x61487, - 0x617c7, - 0x61987, - 0x61d07, - 0x631c7, - 0x63407, - 0x65587, - 0x65ac7, - 0x66007, - 0x66387, - 0x66a47, - 0x66c07, - 0x66dc7, - 0x66f87, - 0x69a47, - 0x6a407, - 0x6ac07, - 0x6afc7, - 0x6b607, - 0x6b8c7, - 0x6ba87, - 0x6bd87, - 0x6c887, - 0x6ca87, - 0x6d907, - 0x6dac7, - 0x6dc87, - 0x6f247, - 0x71247, - 0x71707, - 0x72207, - 0x724c7, - 0x72847, - 0x72a07, - 0x72e07, - 0x73247, - 0x73707, - 0x73c87, - 0x73e47, - 0x74007, - 0x74447, - 0x74ec7, - 0x75407, - 0x75987, - 0x75b47, - 0x75ec7, - 0x76407, - 0x6882, - 0x5ab8a, - 0x11cc8, - 0x1b0ecc, - 0x71b87, - 0x85805, - 0xa7951, - 0x1c0d86, - 0xfb14a, - 0x833ca, - 0x56306, - 0xb060b, - 0x642, - 0x2f7d1, - 0xbf089, - 0x9b209, - 0x9bb06, - 0x3ee42, - 0x9218a, - 0xacdc9, - 0xad50f, - 0xadb0e, - 0xaff88, - 0x6502, - 0x174a49, - 0x8a58e, - 0x1c7f0c, - 0xf1ccf, - 0x1b7a0e, - 0x3230c, - 0x41a89, - 0xd2551, - 0xd2b08, - 0x59452, - 0x62a4d, - 0x733cd, - 0x7984b, - 0x7ea95, - 0xf0c09, - 0x182f8a, - 0x1a3749, - 0x1aa210, - 0x9028b, - 0x9378f, - 0xa694b, - 0xab54c, - 0xb1b90, - 0xb4b0a, - 0xcc00d, - 0xb7ece, - 0x14db0a, - 0x1bd50c, - 0xbe4d4, - 0xbed11, - 0xc0f0b, - 0xc310f, - 0xc5f8d, - 0xc854e, - 0xca80c, - 0xcb00c, - 0xcbd0b, - 0x13ea4e, - 0x16c350, - 0xd974b, - 0xda40d, - 0xdcf0f, - 0xdf00c, - 0xe648e, - 0xf2391, - 0x10498c, - 0x1dc387, - 0x10b44d, - 0x11a00c, - 0x140cd0, - 0x15fd8d, - 0x168847, - 0x18e8d0, - 0x19d508, - 0x1a160b, - 0xb6b8f, - 0x1b1148, - 0x149d4d, - 0x10f810, - 0x17e609, - 0x1db799c8, - 0x1deb9c06, - 0xbaac3, - 0x15a889, - 0xc00c5, - 0x1e42, - 0x144bc9, - 0x14a34a, - 0x1e259906, - 0x145990d, - 0x1e7c2c04, - 0x57a46, - 0x1e08a, - 0x6474d, - 0x1e9df489, - 0x19a83, - 0x1175ca, - 0xe4651, - 0xe4a89, - 0xe54c7, - 0xe61c8, - 0xe68c7, - 0x71c48, - 0x1540b, - 0x12bc49, - 0xf1210, - 0xf16cc, - 0xf27c8, - 0xf4705, - 0x13b1c8, - 0x1961ca, - 0x184947, - 0x2902, - 0x1ef47415, - 0x13788a, - 0x1b2589, - 0x108a08, - 0x9cd89, - 0x46145, - 0x119d0a, - 0x8decf, - 0x10b84b, - 0xf04c, - 0x18ee12, - 0x77285, - 0x114e48, - 0xf678b, - 0xe0a11, - 0x4dcca, - 0x1f2fe185, - 0x19b18c, - 0x133e43, - 0x192286, - 0x3fcc2, - 0x10948b, - 0x109f4a, - 0x150a2cc, - 0xd1608, - 0x30d08, - 0x1f708a86, - 0x1b2f07, - 0xca42, - 0x5142, - 0x18bb50, - 0x69bc7, - 0x2ee0f, - 0x11ec6, - 0x11ed0e, - 0x94c0b, - 0x472c8, - 0x33609, - 0x13ce92, - 0x19234d, - 0x115488, - 0x115cc9, - 0x176f4d, - 0x198609, - 0x63cb, - 0x6bf08, - 0x7a688, - 0x7ce08, - 0x7d249, - 0x7d44a, - 0x8c30c, - 0x3e80a, - 0xf198a, - 0x114cc7, - 0x9994a, - 0x1c350d, - 0xd2e11, - 0x1fac8846, - 0x1cd64b, - 0x97c4c, - 0x39988, - 0x13d849, - 0x15b84d, - 0x61f50, - 0x1808cd, - 0xc2c2, - 0x4f70d, - 0x1b82, - 0xc1c2, - 0x114c0a, - 0x6e70a, - 0xfb04a, - 0x10260b, - 0x292cc, - 0x11c48a, - 0x11c70e, - 0x1d74cd, - 0x1fde0bc5, - 0x128948, - 0x1442, - 0x14239c3, - 0x15a6960e, - 0x16204b4e, - 0x16a6820a, - 0x1734630e, - 0x17b63a8e, - 0x18289d0c, - 0x142e307, - 0x142e309, - 0x14fe3c3, - 0x18b0400c, - 0x1933dfc9, - 0x19b48e89, - 0x1a353b89, - 0x4a82, - 0x69551, - 0x4a91, - 0x6814d, - 0x146251, - 0x1639d1, - 0x89c4f, - 0x103f4f, - 0x13df0c, - 0x148dcc, - 0x153acc, - 0x4b5cd, - 0x1aaa15, - 0xedc8c, - 0x1b32cc, - 0x13f810, - 0x16b10c, - 0x178fcc, - 0x1ac319, - 0x1b6959, - 0x1c1259, - 0x1da294, - 0x76d4, - 0x7d54, - 0x9754, - 0x9f94, - 0x1aa07989, - 0x1b008009, - 0x1bbb3389, - 0x15ed2d09, - 0x4a82, - 0x166d2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x16ed2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x176d2d09, - 0x4a82, - 0x17ed2d09, - 0x4a82, - 0x186d2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x18ed2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x196d2d09, - 0x4a82, - 0x19ed2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x1a6d2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x1aed2d09, - 0x4a82, - 0x1b6d2d09, - 0x4a82, - 0x1bed2d09, - 0x4a82, - 0x76ca, - 0x4a82, - 0x1400401, - 0x15285, - 0x1b3d44, - 0x14c86c3, - 0x15d6e03, - 0x14f8943, - 0x6960e, - 0x4b4e, - 0x7c80e, - 0x6820a, - 0x14630e, - 0x163a8e, - 0x89d0c, - 0x10400c, - 0x13dfc9, - 0x148e89, - 0x153b89, - 0x7989, - 0x8009, - 0x1b3389, - 0x13f8cd, - 0x9a09, - 0xa249, - 0x12f604, - 0x18ad44, - 0x1bad44, - 0x1bf004, - 0xa8a44, - 0x2cc04, - 0x3ca84, - 0x53684, - 0x11dc4, - 0x62b84, - 0x1588703, - 0x13dd87, - 0x147dc8c, - 0xf283, - 0xaac82, - 0xae8c6, - 0x1d74c3, - 0xf283, - 0x9fc83, - 0x8582, - 0x8588, - 0xe9247, - 0x12bcc7, - 0x2a42, - 0x2000c2, - 0x201242, - 0x2052c2, - 0x20dec2, - 0x200382, - 0x2003c2, - 0x205142, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21bac3, - 0x21a3c3, - 0x242543, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x21a3c3, - 0x242543, - 0xb2c3, - 0x308003, - 0x21dc4, - 0x2000c2, - 0x202703, - 0x22214a83, - 0x38b9c7, - 0x308003, - 0x21a8c3, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x21e2ca, - 0x2431c5, - 0x2141c3, - 0x233442, - 0x9a048, - 0x226d8a4a, - 0xe01, - 0x9a048, - 0x1242, - 0x131a42, - 0x22fdf20b, - 0x23227fc4, - 0x1c2b45, - 0x1805, - 0xf48c6, - 0x23601805, - 0x53bc3, - 0x94e83, - 0x9c4, - 0x4e83, - 0x68b05, - 0x139b05, - 0x9a048, - 0x1bf87, - 0x14a83, - 0x2cd0d, - 0x23e3a147, - 0x144686, - 0x24146145, - 0x1b8dd2, - 0x3a247, - 0x1d35ca, - 0x1d3488, - 0x95c7, - 0x6574a, - 0x1a7308, - 0xe2b07, - 0x1a870f, - 0x169347, - 0x53486, - 0x136b90, - 0x11dccf, - 0x1a009, - 0x57ac4, - 0x2443a30e, - 0x35509, - 0x670c6, - 0x10ecc9, - 0x18d986, - 0x1ba1c6, - 0x78ecc, - 0x24b0a, - 0x333c7, - 0x14420a, - 0x33c9, - 0xf714c, - 0x1d40a, - 0x5c30a, - 0x68b49, - 0x57a46, - 0x3348a, - 0x11634a, - 0xa430a, - 0x14fbc9, - 0xe30c8, - 0xe3346, - 0xeb54d, - 0x5390b, - 0xc0545, - 0x24b55a0c, - 0x14a887, - 0x10d1c9, - 0xbf407, - 0x10fc14, - 0x11010b, - 0x254ca, - 0x13cd0a, - 0xaabcd, - 0x1502809, - 0x11524c, - 0x115acb, - 0x106c3, - 0x106c3, - 0x28886, - 0x106c3, - 0xf48c8, - 0x155983, - 0x44ec4, - 0x53f83, - 0x335c5, - 0x146e943, - 0x50849, - 0xf678b, - 0x14df283, - 0x148406, - 0x14ecac7, - 0x1aa487, - 0x2592c5c9, - 0x1a286, - 0x173d09, - 0x2703, - 0x9a048, - 0x1242, - 0x4d9c4, - 0x88c3, - 0x8805, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x220dc3, - 0x214a83, - 0x232dc3, - 0x228503, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x29b3c3, - 0x207783, - 0x220dc3, - 0x2d3684, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x2308c3, - 0x2752c6c5, - 0x142c943, - 0x214a83, - 0x232dc3, - 0x21bb43, - 0x228503, - 0x308003, - 0x221dc4, - 0x2059c3, - 0x2137c3, - 0x23c803, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x2141c3, - 0x2821e9c3, - 0x18ed09, - 0x1242, - 0x3c0743, - 0x28e14a83, - 0x232dc3, - 0x247103, - 0x308003, - 0x223703, - 0x2137c3, - 0x242543, - 0x2f4bc3, - 0x3b9a84, - 0x9a048, - 0x29614a83, - 0x232dc3, - 0x2b0043, - 0x308003, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x22e983, - 0x9a048, - 0x29e14a83, - 0x232dc3, - 0x228503, - 0x203dc3, - 0x242543, - 0x9a048, - 0x142e307, - 0x202703, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x139b05, - 0x17e707, - 0x10fe4b, - 0xe4e84, - 0xc0545, - 0x144ca88, - 0x2a54d, - 0x2b231ac5, - 0x647c4, - 0x1242, - 0x3a83, - 0x17e505, - 0x2aec2, - 0x5e42, - 0x303dc5, - 0x9a048, - 0x106c2, - 0x1d2c3, - 0x16454f, - 0x1242, - 0x105646, - 0x2000c2, - 0x202703, - 0x214a83, - 0x308003, - 0x221dc4, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x2141c3, - 0x2aec2, - 0x32a988, - 0x2d3684, - 0x349646, - 0x353986, - 0x9a048, - 0x3373c3, - 0x2cd549, - 0x217915, - 0x1791f, - 0x214a83, - 0xd1ac7, - 0x214892, - 0x169046, - 0x1712c5, - 0x8e0a, - 0x2ac49, - 0x21464f, - 0x2e3504, - 0x224445, - 0x311050, - 0x2137c7, - 0x203dc3, - 0x31bf88, - 0x1283c6, - 0x27cfca, - 0x221c84, - 0x2fdbc3, - 0x233442, - 0x2f850b, - 0x3dc3, - 0x17cc84, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x306403, - 0x201242, - 0x89ac3, - 0x1dee04, - 0x21a3c3, - 0x242543, - 0x2ed73e05, - 0x8346, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a8c3, - 0x223d43, - 0x242543, - 0x2703, - 0x201242, - 0x214a83, - 0x232dc3, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x267c2, - 0x2000c2, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x1805, - 0xf283, - 0x2d3684, - 0x214a83, - 0x232dc3, - 0x306c44, - 0x21a3c3, - 0x242543, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x1b3089, - 0x29904, - 0x214a83, - 0x2a42, - 0x232dc3, - 0x228503, - 0x206c03, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x2982, - 0x214a83, - 0x232dc3, - 0x308003, - 0x343104, - 0x221dc4, - 0x21a3c3, - 0x242543, - 0x207783, - 0x16c2, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x2f3983, - 0x13903, - 0x1a8c3, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x322c0a, - 0x3413c9, - 0x35fb0b, - 0x3602ca, - 0x36860a, - 0x377c8b, - 0x38d74a, - 0x39424a, - 0x39abca, - 0x39ae4b, - 0x3bcfc9, - 0x3ca20a, - 0x3ca58b, - 0x3d818b, - 0x3e040a, - 0x15702, - 0x214a83, - 0x232dc3, - 0x228503, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x1558b, - 0xcf487, - 0x5b788, - 0x177084, - 0x8f308, - 0xe8006, - 0x15546, - 0x366c9, - 0x9a048, - 0x214a83, - 0x8e04, - 0x261484, - 0x202742, - 0x219a04, - 0x269045, - 0x220dc3, - 0x2d3684, - 0x214a83, - 0x235b44, - 0x232dc3, - 0x24d9c4, - 0x2e3504, - 0x221dc4, - 0x2137c3, - 0x21a3c3, - 0x242543, - 0x24f8c5, - 0x2308c3, - 0x2141c3, - 0x32bf03, - 0x23e804, - 0x325d04, - 0x373fc5, - 0x9a048, - 0x203ac4, - 0x3b5cc6, - 0x268c84, - 0x201242, - 0x38f207, - 0x3a25c7, - 0x24b904, - 0x2e92c5, - 0x35ff85, - 0x22d805, - 0x221dc4, - 0x389208, - 0x22b586, - 0x3295c8, - 0x27b905, - 0x2ec0c5, - 0x262044, - 0x242543, - 0x2fe7c4, - 0x376806, - 0x2432c3, - 0x23e804, - 0x3829c5, - 0x344b44, - 0x23acc4, - 0x233442, - 0x231d86, - 0x3aeb46, - 0x313fc5, - 0x2000c2, - 0x202703, - 0x33e01242, - 0x20c504, - 0x200382, - 0x23c803, - 0x215402, - 0x21a3c3, - 0x2003c2, - 0x2fb406, - 0x20e2c3, - 0x207783, - 0x9a048, - 0x9a048, - 0x308003, - 0x1b4103, - 0x2000c2, - 0x34a01242, - 0x308003, - 0x266d43, - 0x2059c3, - 0x227fc4, - 0x21a3c3, - 0x242543, - 0x9a048, - 0x2000c2, - 0x35201242, - 0x214a83, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x682, - 0x209d42, - 0x20c782, - 0x21a8c3, - 0x2f7103, - 0x2000c2, - 0x139b05, - 0x9a048, - 0x17e707, - 0x201242, - 0x232dc3, - 0x24d9c4, - 0x207083, - 0x308003, - 0x206c03, - 0x23c803, - 0x21a3c3, - 0x2125c3, - 0x242543, - 0x233dc3, - 0x12be53, - 0x12e714, - 0x139b05, - 0x17e707, - 0x1d35c9, - 0x10d8c6, - 0xf5ecb, - 0x28886, - 0x54c47, - 0x15aec6, - 0x649, - 0x15794a, - 0x8b70d, - 0x12350c, - 0x116cca, - 0x112988, - 0x97805, - 0x1d3608, - 0x11ec6, - 0x1c6606, - 0x365c6, - 0x602, - 0x2aac82, - 0x174ec4, - 0x9fc86, - 0x12c310, - 0x147498e, - 0x68846, - 0x6264c, - 0x36a6720b, - 0x139b05, - 0x14820b, - 0x36fc6544, - 0x1b3f07, - 0x22111, - 0x1ae28a, - 0x214a83, - 0x3727db88, - 0x656c5, - 0x19b808, - 0xca04, - 0x14a545, - 0x3755ca06, - 0xa7946, - 0xc7746, - 0x908ca, - 0x1b5c43, - 0x37a0dc84, - 0x50849, - 0x129747, - 0x1274ca, - 0x14d8949, - 0x605, - 0xec503, - 0x37e33f07, - 0x1df105, - 0x1538186, - 0x1498886, - 0xb06cc, - 0x101b88, - 0x3803fcc3, - 0xf874b, - 0x13864b, - 0x38647c0c, - 0x140a503, - 0xc2dc8, - 0xf89c5, - 0xc11c9, - 0xea803, - 0x102908, - 0x141dfc6, - 0x86107, - 0x38b5b849, - 0x19d887, - 0xebbca, - 0x39fbf648, - 0x11578d, - 0xa788, - 0xf283, - 0x1443f09, - 0x174483, - 0x28886, - 0xf48c8, - 0x11dc4, - 0x1205c5, - 0x148df83, - 0x239c7, - 0x38e239c3, - 0x393c0a06, - 0x39637f04, - 0x39b0a107, - 0xf48c4, - 0xf48c4, - 0xf48c4, - 0xf48c4, - 0x41, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x2000c2, - 0x201242, - 0x308003, - 0x206182, - 0x21a3c3, - 0x242543, - 0x20e2c3, - 0x3810cf, - 0x38148e, - 0x9a048, - 0x214a83, - 0x43bc7, - 0x232dc3, - 0x308003, - 0x21bc83, - 0x21a3c3, - 0x242543, - 0x68784, - 0x4fc4, - 0x145bc4, - 0x21c9c3, - 0x296747, - 0x203082, - 0x26ce49, - 0x200ac2, - 0x38be4b, - 0x2a1b8a, - 0x2a2889, - 0x200542, - 0x20cdc6, - 0x236a55, - 0x38bf95, - 0x2391d3, - 0x38c513, - 0x2037c2, - 0x2037c5, - 0x2037cc, - 0x27514b, - 0x276205, - 0x204b42, - 0x29d282, - 0x37bb86, - 0x201182, - 0x2c9d46, - 0x20908d, - 0x3dee8c, - 0x379a84, - 0x200882, - 0x202b02, - 0x259808, - 0x200202, - 0x205086, - 0x395a8f, - 0x205090, - 0x3a1544, - 0x236c15, - 0x239353, - 0x24d2c3, - 0x34934a, - 0x214f07, - 0x383d89, - 0x327387, - 0x220f82, - 0x200282, - 0x3beb06, - 0x205fc2, - 0x9a048, - 0x202e82, - 0x201542, - 0x20ac47, - 0x36a6c7, - 0x36a6d1, - 0x2180c5, - 0x2180ce, - 0x218e8f, - 0x20cd42, - 0x2679c7, - 0x21d008, - 0x207682, - 0x21d482, - 0x2101c6, - 0x2101cf, - 0x263710, - 0x22c042, - 0x2086c2, - 0x238c48, - 0x2086c3, - 0x25cec8, - 0x2c1bcd, - 0x215843, - 0x363208, - 0x27fc4f, - 0x28000e, - 0x33c9ca, - 0x2f5211, - 0x2f5690, - 0x300acd, - 0x300e0c, - 0x24a147, - 0x3494c7, - 0x349709, - 0x220f42, - 0x204342, - 0x25678c, - 0x256a8b, - 0x200d42, - 0x2cbec6, - 0x20b682, - 0x200482, - 0x2167c2, - 0x201242, - 0x22d204, - 0x239e07, - 0x22ba02, - 0x23f707, - 0x241247, - 0x22f142, - 0x22ec02, - 0x243a85, - 0x205582, - 0x392dce, - 0x3cae0d, - 0x232dc3, - 0x28508e, - 0x2b794d, - 0x328b03, - 0x2027c2, - 0x21fc84, - 0x24cf02, - 0x222342, - 0x38cdc5, - 0x39d187, - 0x246702, - 0x20dec2, - 0x24d5c7, - 0x250bc8, - 0x22dec2, - 0x277306, - 0x25660c, - 0x25694b, - 0x205dc2, - 0x25db0f, - 0x25ded0, - 0x25e2cf, - 0x25e695, - 0x25ebd4, - 0x25f0ce, - 0x25f44e, - 0x25f7cf, - 0x25fb8e, - 0x25ff14, - 0x260413, - 0x2608cd, - 0x2765c9, - 0x28d003, - 0x207082, - 0x31e805, - 0x3ddc86, - 0x200382, - 0x37f147, - 0x308003, - 0x200642, - 0x361608, - 0x2f5451, - 0x2f5890, - 0x201f02, - 0x28bf47, - 0x204582, - 0x271547, - 0x201e42, - 0x295749, - 0x37bb47, - 0x29ac08, - 0x35c846, - 0x24b083, - 0x24b085, - 0x233042, - 0x2004c2, - 0x3bef05, - 0x39b605, - 0x202482, - 0x21bdc3, - 0x348587, - 0x20e5c7, - 0x201842, - 0x345044, - 0x210543, - 0x31d809, - 0x210548, - 0x202042, - 0x208282, - 0x2ed207, - 0x2f5145, - 0x298bc8, - 0x2ae507, - 0x20fac3, - 0x29fb06, - 0x30094d, - 0x300ccc, - 0x305086, - 0x206782, - 0x2017c2, - 0x209e82, - 0x27facf, - 0x27fece, - 0x360007, - 0x210942, - 0x372385, - 0x372386, - 0x21d542, - 0x200bc2, - 0x28e5c6, - 0x247703, - 0x3c5d46, - 0x2d6705, - 0x2d670d, - 0x2d6f95, - 0x2d7e0c, - 0x2d818d, - 0x2d84d2, - 0x202382, - 0x26c9c2, - 0x202802, - 0x219386, - 0x3c7dc6, - 0x202902, - 0x3ddd06, - 0x206e42, - 0x296f45, - 0x201582, - 0x392f09, - 0x21ae0c, - 0x21b14b, - 0x2003c2, - 0x251d88, - 0x202942, - 0x200a82, - 0x272b46, - 0x2d2c85, - 0x200a87, - 0x227c85, - 0x257145, - 0x215542, - 0x2a3882, - 0x214282, - 0x293a87, - 0x2fb4cd, - 0x2fb84c, - 0x234307, - 0x277282, + 0x25b542, + 0x2295c2, 0x205742, - 0x3d2508, - 0x344d48, - 0x3298c8, - 0x3b1104, - 0x33ecc7, - 0x3c2c83, - 0x21b742, - 0x20cb42, - 0x2fc0c9, - 0x228c87, - 0x2141c2, - 0x272f45, - 0x214b42, - 0x20eb42, - 0x2f6e43, - 0x2f6e46, - 0x305fc2, - 0x308c02, - 0x200402, - 0x35c406, - 0x21fbc7, - 0x213fc2, - 0x200902, - 0x25cd0f, - 0x284ecd, - 0x28a98e, - 0x2b77cc, - 0x206842, - 0x206142, - 0x35c685, - 0x320b86, - 0x200b82, - 0x2069c2, - 0x200682, - 0x285244, - 0x2c1a44, - 0x384486, - 0x205142, - 0x27a207, - 0x23d903, - 0x23d908, - 0x23e108, - 0x2d23c7, - 0x24c186, - 0x207842, - 0x20b603, - 0x20b607, - 0x3a6dc6, - 0x2ee0c5, - 0x274608, - 0x2071c2, - 0x3b9447, - 0x26c702, - 0x294ec2, - 0x206382, - 0x205249, - 0x201082, - 0xcb3c8, - 0x203882, - 0x234583, - 0x204847, - 0x203282, - 0x21af8c, - 0x21b28b, - 0x305106, - 0x2ec445, - 0x202c02, - 0x202982, - 0x2c55c6, - 0x216643, - 0x342e87, - 0x291f82, - 0x2008c2, - 0x2368d5, - 0x38c155, - 0x239093, - 0x38c693, - 0x24ee47, - 0x26ee11, - 0x275590, - 0x283712, - 0x2eb111, - 0x29a208, - 0x29a210, - 0x29f38f, - 0x2a1953, - 0x2a2652, - 0x2a7d50, - 0x2b4ecf, - 0x3689d2, - 0x3a1891, - 0x3d4d53, - 0x2b9d52, - 0x2d634f, - 0x2ddd0e, - 0x2e1112, - 0x2e1fd1, - 0x2e5e0f, - 0x2e7c8e, - 0x2efbd1, - 0x2f8ed0, - 0x301d52, - 0x306491, - 0x309b50, - 0x311f8f, - 0x3cea91, - 0x347910, - 0x37b006, - 0x380cc7, - 0x218987, - 0x209f42, - 0x280f85, - 0x310dc7, - 0x20c782, - 0x2018c2, - 0x229e45, - 0x21ec03, - 0x374946, - 0x2fb68d, - 0x2fb9cc, - 0x203642, - 0x20364b, - 0x27500a, - 0x22408a, - 0x2c43c9, - 0x2fa74b, - 0x2ae64d, - 0x3114cc, - 0x35d58a, - 0x244f8c, - 0x27188b, - 0x27604c, - 0x29b68e, - 0x2bf90b, - 0x2b8a0c, - 0x2dc483, - 0x376e46, - 0x3bf642, - 0x304382, - 0x24f4c3, - 0x206482, - 0x20c3c3, - 0x324506, - 0x25e847, - 0x352386, - 0x2e78c8, - 0x348408, - 0x2cf746, - 0x200f02, - 0x31398d, - 0x313ccc, - 0x338807, - 0x316b07, - 0x234a42, - 0x2143c2, - 0x20b582, - 0x27c602, - 0x330496, - 0x335f95, - 0x3395d6, - 0x33ff53, - 0x340612, - 0x355513, - 0x358152, - 0x3acc8f, - 0x3be558, - 0x3bf117, - 0x3bfc59, - 0x3c1898, - 0x3c3c58, - 0x3c5fd7, - 0x3c6b17, - 0x3c8216, - 0x3cc693, - 0x3ccfd5, - 0x3cdd52, - 0x3ce1d3, - 0x201242, - 0x21a3c3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x20e2c3, + 0x13150c, + 0x2be4c2, + 0x250d42, + 0x227082, + 0x24a282, + 0x23cb03, + 0x200bc2, + 0x217fc3, + 0x209ec2, + 0x25c042, + 0x23e083, + 0x3081c2, + 0x208502, + 0x20a1c2, + 0x204782, + 0x2010c2, + 0x230ac2, + 0x205682, + 0x22b302, + 0x2270c2, + 0x32748a, + 0x36f50a, + 0x3a124a, + 0x3e2d42, + 0x208902, + 0x20e8c2, + 0x13aa7f09, + 0x13f61e8a, + 0x142fc47, + 0x142050c2, + 0x143a083, + 0x1742, + 0x161e8a, + 0x162b0e, + 0x241ec4, + 0x57fc5, + 0x14a2ea43, + 0x3dc03, + 0x233fc3, + 0x24d704, + 0x266a83, + 0x20e704, + 0x2191c3, + 0x13d289, + 0x157686, + 0x23cb03, + 0xf1584, + 0x1598c3, + 0x217fc3, + 0x2a7c5, + 0x205803, + 0x23e083, + 0x1466d84, + 0x235403, + 0x181584, + 0x20aa43, + 0xae888, + 0x154f043, + 0x12a086, + 0x146e844, + 0x1a45, + 0x14c80a, + 0x124d82, + 0x15408acd, + 0x1adec6, + 0x159a140b, + 0xc951, + 0x15ea7f09, + 0x1ac8, + 0x69908, + 0x1c9415c7, + 0x3502, + 0xa8087, + 0x221ce, + 0x146bcb, + 0x14a88b, + 0x1c008a, + 0x1683c7, + 0xae888, + 0x120d48, + 0xa807, + 0x1cc176cb, + 0x1a087, + 0xcfc2, + 0x2b20d, + 0x16a7c7, + 0xb1bca, + 0x1e174f, + 0x12308f, + 0x161e82, + 0x12402, + 0x8af48, + 0x1d10778c, + 0x1570a, + 0xe710a, + 0x19004a, + 0x80a88, + 0x1d208, + 0x5a488, + 0xe75c8, + 0x1388, + 0xf982, + 0x167c0f, + 0xc6d8b, + 0x10f508, + 0x35cc7, + 0x4878a, + 0xbc3cb, + 0x34449, + 0x48687, + 0x83986, + 0x1d108, + 0x18ea0c, + 0x161347, + 0x1ae40a, + 0xec88, + 0x10ae8e, + 0x10b64e, + 0x16820b, + 0x168a8b, + 0x658cb, + 0x66609, + 0x6754b, + 0xbd4cd, + 0xf548b, + 0xf5fcd, + 0xf634d, + 0x10360a, + 0x12a4cb, + 0x166c0b, + 0x3bfc5, + 0x1d58b810, + 0x13514f, + 0x72e8f, + 0x2470d, + 0x13d450, + 0x293c2, + 0x1da1f8c8, + 0x7f248, + 0xea790, + 0x17fe0e, + 0x1df22b85, + 0x4c84b, + 0x13c390, + 0x1d30a, + 0x168c49, + 0x680c7, + 0x68407, + 0x685c7, + 0x68947, + 0x69e07, + 0x6a2c7, + 0x6bb07, + 0x6c047, + 0x6d587, + 0x6d907, + 0x6dfc7, + 0x6e187, + 0x6e347, + 0x6e507, + 0x6f307, + 0x6fc47, + 0x70a87, + 0x70e47, + 0x71487, + 0x71747, + 0x71907, + 0x71c07, + 0x71f87, + 0x72187, + 0x748c7, + 0x74a87, + 0x74c47, + 0x75dc7, + 0x77207, + 0x776c7, + 0x77dc7, + 0x78087, + 0x78407, + 0x785c7, + 0x789c7, + 0x78e07, + 0x792c7, + 0x79847, + 0x79a07, + 0x79bc7, + 0x7a007, + 0x7aa87, + 0x7afc7, + 0x7b207, + 0x7b3c7, + 0x7bb87, + 0x7c187, + 0x9a42, + 0x5a58a, + 0x13808, + 0x1baf8c, + 0x4eb87, + 0x918c5, + 0x9b311, + 0x1bb46, + 0x104dca, + 0x8adca, + 0x56546, + 0xb3ecb, + 0x642, + 0x31351, + 0xc5d89, + 0x9bf49, + 0x9d306, + 0x5b542, + 0x1b21ca, + 0xafcc9, + 0xb040f, + 0xb0a0e, + 0xb3108, + 0x11b08, + 0xb5c2, + 0x6ed89, + 0x1e3586c9, + 0xbd049, + 0xbd04c, + 0x8f90e, + 0x4b8c, + 0xf2f8f, + 0x1bf08e, + 0x12b40c, + 0x33449, + 0x45391, + 0x45948, + 0x1a4e12, + 0x593cd, + 0x69acd, + 0x78f8b, + 0x81855, + 0x860c9, + 0x1518ca, + 0x188809, + 0x1aad50, + 0x1ae8cb, + 0x9890f, + 0xa868b, + 0xa914c, + 0xaa110, + 0xb7dca, + 0xb894d, + 0xd3a0e, + 0x195a0a, + 0xc1e8c, + 0xc4e94, + 0xc5a11, + 0xc694b, + 0xc858f, + 0xcbb0d, + 0xcd20e, + 0xd048c, + 0xd0c8c, + 0xd370b, + 0x172a8e, + 0x199ed0, + 0xdba8b, + 0xdc74d, + 0xdf30f, + 0xe804c, + 0xe9d8e, + 0xf3651, + 0x10570c, + 0x1d4047, + 0x10d14d, + 0x11db8c, + 0x144550, + 0x16528d, + 0x16efc7, + 0x176790, + 0x19dd08, + 0x1a3e8b, + 0xba1cf, + 0x1bb208, + 0x14bf0d, + 0x1125d0, + 0x178c89, + 0x1e78b7c8, + 0x1eabf946, + 0xc0843, + 0x3ec49, + 0xc7405, + 0x6902, + 0x48c09, + 0x14c50a, + 0x1efa52c6, + 0x15a52cd, + 0x1f36a9c4, + 0x57d06, + 0x1b68a, + 0x27bcd, + 0x1f52b109, + 0x216c3, + 0x11bb8a, + 0xe6751, + 0xe6b89, + 0xe7087, + 0xe7d88, + 0xe8447, + 0x4ec48, + 0xcacb, + 0x1311c9, + 0xf1e10, + 0xf22cc, + 0x1faf270d, + 0xf3a88, + 0xf4ec5, + 0x147e08, + 0x19ce4a, + 0x18a347, + 0x2542, + 0x1ff3f5d5, + 0x13d08a, + 0x1320c9, + 0x9e588, + 0x6ab09, + 0x7cb45, + 0x11d88a, + 0x92e0f, + 0x10d54b, + 0x11ff4c, + 0x176cd2, + 0xe9c6, + 0x7ce85, + 0x117a48, + 0xf84cb, + 0xf1151, + 0x16acc7, + 0x4da0a, + 0x20300485, + 0x1b330c, + 0x139c43, + 0x197a86, + 0x408c2, + 0x1089cb, + 0x10948a, + 0x150980c, + 0x7f5c8, + 0xf6188, + 0x2069e606, + 0x17d5c7, + 0xd782, + 0x7742, + 0x1a55d0, + 0x65087, + 0x3074f, + 0x13a06, + 0xd2b8e, + 0x99a0b, + 0x3dd48, + 0x34809, + 0x5da12, + 0x197b4d, + 0x118088, + 0x1188c9, + 0xee00d, + 0x19f749, + 0xb48b, + 0x6c348, + 0x71d88, + 0x75a88, + 0x80389, + 0x8058a, + 0x84b0c, + 0x166eca, + 0xf17ca, + 0x1178c7, + 0x9a50a, + 0x1cda4d, + 0x45c51, + 0x20acd506, + 0x1b994b, + 0x12f80c, + 0x94388, + 0x149449, + 0x160b0d, + 0x68b90, + 0x1812cd, + 0x4642, + 0x4a68d, + 0x72c2, + 0x1f702, + 0x11780a, + 0x756ca, + 0x20e7b508, + 0x104cca, + 0x11f80b, + 0x10b8cc, + 0x12048a, + 0x12070f, + 0x120ace, + 0x171cd, + 0x211e2c05, + 0x12d408, + 0x3602, + 0x1422383, + 0x415505, + 0x45d884, + 0x16202c0e, + 0x16b59cce, + 0x1720180a, + 0x17b9184e, + 0x1835788e, + 0x18b7f38c, + 0x142fc47, + 0x142fc49, + 0x143a083, + 0x1926060c, + 0x19b49bc9, + 0x1a36af09, + 0x1ab71749, + 0x1742, + 0x2b51, + 0x159c11, + 0x174d, + 0x1b6451, + 0x1577d1, + 0x17f2cf, + 0x6054f, + 0x149b0c, + 0x16ae4c, + 0x17168c, + 0x1af28d, + 0x15d915, + 0xc1a8c, + 0xc778c, + 0x135a10, + 0x141acc, + 0x14af8c, + 0x18ad99, + 0x191599, + 0x1bdfd9, + 0x1cb4d4, + 0x1d6294, + 0x1e02d4, + 0x1e2714, + 0xa994, + 0x1b2c1b49, + 0x1b9e0589, + 0x1c2c7849, + 0x16645b49, + 0x1742, + 0x16e45b49, + 0x1742, + 0xa98a, + 0x1742, + 0x17645b49, + 0x1742, + 0xa98a, + 0x1742, + 0x17e45b49, + 0x1742, + 0x18645b49, + 0x1742, + 0x18e45b49, + 0x1742, + 0xa98a, + 0x1742, + 0x19645b49, + 0x1742, + 0xa98a, + 0x1742, + 0x19e45b49, + 0x1742, + 0x1a645b49, + 0x1742, + 0xa98a, + 0x1742, + 0x1ae45b49, + 0x1742, + 0xa98a, + 0x1742, + 0x1b645b49, + 0x1742, + 0x1be45b49, + 0x1742, + 0x1c645b49, + 0x1742, + 0xa98a, + 0x1742, + 0x1400401, + 0xc945, + 0x1c0084, + 0x144ce03, + 0x1426d83, + 0x14fa443, + 0x2c0e, + 0x159cce, + 0x8450e, + 0x180a, + 0x19184e, + 0x15788e, + 0x17f38c, + 0x6060c, + 0x149bc9, + 0x16af09, + 0x171749, + 0xc1b49, + 0x1e0589, + 0xc7849, + 0x135acd, + 0x141b89, + 0xac49, + 0x12d5c4, + 0x132ac4, + 0x1c8a04, + 0x1c95c4, + 0xaae04, + 0x2ec44, + 0x3cd84, + 0x192d44, + 0x13904, + 0xbec06, + 0x59504, + 0x158e7c3, + 0x149987, + 0x148574c, + 0x1ac3, + 0x293c2, + 0x107788, + 0xd1784, + 0x14386, + 0xd8a84, + 0x15aa06, + 0x16b82, + 0xa8c1, + 0x20e44, + 0xb1706, + 0x171c3, + 0x1ac3, + 0xa0e83, + 0x13d385, + 0x124dc2, + 0x124dc8, + 0xeb947, + 0x131247, + 0xf982, 0x2000c2, - 0x201602, - 0x3be933c5, - 0x3c281445, - 0x3c746bc6, - 0x9a048, - 0x3caba385, - 0x201242, - 0x2052c2, - 0x3ce871c5, - 0x3d27e985, - 0x3d680387, - 0x3da806c9, - 0x3de1f844, + 0x212402, + 0x204542, + 0x20fa02, + 0x200382, + 0x2003c2, + 0x207742, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e703, + 0x217fc3, + 0x23e083, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x217fc3, + 0x23e083, + 0x10303, + 0x266a83, + 0xe704, + 0x2000c2, + 0x24ac43, + 0x2362ea43, + 0x392747, + 0x266a83, + 0x21e1c3, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x226e0a, + 0x243bc5, + 0x216983, + 0x22dc42, + 0xae888, + 0x23adad8a, + 0xe01, + 0xae888, + 0x12402, + 0x137ac2, + 0x2432ae8b, + 0x2462e004, + 0x16a905, + 0x8cc5, + 0x107786, + 0x24a08cc5, + 0x54383, + 0x5cd83, + 0x9c4, + 0x157bc3, + 0x2105, + 0x146bc5, + 0xae888, + 0x1a087, + 0x2ea43, + 0x2ed4d, + 0x2523a707, + 0x159146, + 0x25401645, + 0x1c0992, + 0x159207, + 0x1dbca, + 0x10ac8, + 0x1dac7, + 0x6bcca, + 0x1bc448, + 0xe4f07, + 0x1ac70f, + 0x36fc7, + 0x192b46, + 0x13c390, + 0xcee8f, + 0x21c49, + 0x57d84, + 0x259592ce, + 0x185a89, + 0x6e646, + 0x111a89, + 0x193c86, + 0x1c2e06, + 0x4f10c, + 0xbc5ca, + 0x345c7, + 0x17edca, + 0x1596c9, + 0xf8e8c, + 0x1c8ca, + 0x4b8ca, + 0x2149, + 0x57d06, + 0x3468a, + 0x118f4a, + 0xa3a4a, + 0x137509, + 0xe54c8, + 0xe5746, + 0xed88d, + 0x5130b, + 0xc7c05, + 0x25f5a28c, + 0x14ca47, + 0x110289, + 0xd1047, + 0xc6114, + 0x1129cb, + 0x10f34a, + 0x5d88a, + 0xac80d, + 0x151fa09, + 0x117e4c, + 0x1186cb, + 0x88c3, + 0x88c3, + 0x36fc6, + 0x88c3, + 0x107788, + 0x15c103, + 0x46604, + 0x54603, + 0x347c5, + 0x1475903, + 0x51709, + 0xf84cb, + 0x14e82c3, + 0x154546, + 0x15037c7, + 0x1aafc7, + 0x26d41489, + 0x17e86, + 0x4ac43, + 0xae888, + 0x12402, + 0x4d704, + 0x61083, + 0x17b845, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x233f03, + 0x22ea43, + 0x233fc3, + 0x280203, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x2bd443, + 0x20aa43, + 0x233f03, + 0x24cd44, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x204ac3, + 0x28541585, + 0x142e6c3, + 0x22ea43, + 0x233fc3, + 0x20fa03, + 0x280203, + 0x266a83, + 0x20e704, + 0x3433c3, + 0x215f83, + 0x23cb03, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x216983, + 0x29219f03, + 0x176bc9, + 0x12402, + 0x3c7603, + 0x29e2ea43, + 0x233fc3, + 0x249283, + 0x266a83, + 0x2220c3, + 0x215f83, + 0x23e083, + 0x3005c3, + 0x3cd604, + 0xae888, + 0x2a62ea43, + 0x233fc3, + 0x2b31c3, + 0x266a83, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x2302c3, + 0xae888, + 0x2ae2ea43, + 0x233fc3, + 0x280203, + 0x205803, + 0x23e083, + 0xae888, + 0x142fc47, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x146bc5, + 0x178d87, + 0xc634b, + 0xe6f84, + 0xc7c05, + 0x1454408, + 0x2c10d, + 0x2c242285, + 0x27c44, + 0x12402, + 0x10103, + 0x184485, + 0x30242, + 0x53c2, + 0x34b8c5, + 0xae888, + 0x88c2, + 0x1b2c3, + 0x16b88f, + 0x12402, + 0x1063c6, + 0x2000c2, + 0x24ac43, + 0x22ea43, + 0x266a83, + 0x20e704, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x216983, + 0x30242, + 0x32ff08, + 0x24cd44, + 0x37e046, + 0x3af146, + 0xae888, + 0x31a6c3, + 0x355c09, + 0x30ddd5, + 0x10dddf, + 0x22ea43, + 0x7fa87, + 0x242992, + 0x1623c6, + 0x16fd05, + 0x1d30a, + 0x168c49, + 0x24274f, + 0x2e5904, + 0x2bbf05, + 0x313850, + 0x215f87, + 0x205803, + 0x321388, + 0x134b86, + 0x293b0a, + 0x223144, + 0x2ffec3, + 0x22dc42, + 0x2fa00b, + 0x5803, + 0x182c04, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0x307183, + 0x212402, + 0x1c06c3, + 0x2a4c4, + 0x217fc3, + 0x23e083, + 0x2fc39fc5, + 0x1d5cc6, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x21e1c3, + 0x265dc3, + 0x23e083, + 0x4ac43, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x217fc3, + 0x5803, + 0x23e083, + 0x17082, + 0x2000c2, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x8cc5, + 0x1ac3, + 0x24cd44, + 0x22ea43, + 0x233fc3, + 0x217544, + 0x217fc3, + 0x23e083, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x1357c9, + 0x4cc4, + 0x22ea43, + 0xf982, + 0x233fc3, + 0x280203, + 0x204903, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0x2a82, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x36a584, + 0x20e704, + 0x217fc3, + 0x23e083, + 0x20aa43, + 0x6c02, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x2f4c43, + 0x160c3, + 0x1e1c3, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x32748a, + 0x345389, + 0x36500b, + 0x3657ca, + 0x36f50a, + 0x37c54b, + 0x393a4a, + 0x399a4a, + 0x3a124a, + 0x3a1c4b, + 0x3c4709, + 0x3cf9ca, + 0x3cfe0b, + 0x3db28b, + 0x3e0d8a, + 0xcdc2, + 0x22ea43, + 0x233fc3, + 0x280203, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0xcc4b, + 0x17fe07, + 0x5af88, + 0xee144, + 0x1c4104, + 0x94dc8, + 0xea706, + 0xcc06, + 0x1a07c9, + 0xae888, + 0x22ea43, + 0x1d304, + 0x2680c4, + 0x201c02, + 0x21e484, + 0x202645, + 0x233f03, + 0x24cd44, + 0x22ea43, + 0x236704, + 0x233fc3, + 0x24d704, + 0x2e5904, + 0x20e704, + 0x215f83, + 0x217fc3, + 0x23e083, + 0x24a845, + 0x204ac3, + 0x216983, + 0x204343, + 0x2ddf84, + 0x32a004, + 0x23a185, + 0xae888, + 0x3b4e04, + 0x3c2f86, + 0x202284, + 0x212402, + 0x3770c7, + 0x3a9947, + 0x24bb44, + 0x20e785, + 0x365485, + 0x22f845, + 0x20e704, + 0x38f948, + 0x2523c6, + 0x3641c8, + 0x2836c5, + 0x2ee705, + 0x237bc4, + 0x23e083, + 0x300ac4, + 0x37b286, + 0x243cc3, + 0x2ddf84, + 0x24fd85, + 0x248b84, + 0x2a67c4, + 0x22dc42, + 0x232ec6, + 0x3b7ec6, + 0x315fc5, + 0x2000c2, + 0x24ac43, + 0x34e12402, + 0x21fa44, + 0x200382, + 0x23cb03, + 0x20cac2, + 0x217fc3, + 0x2003c2, + 0x2fcf46, + 0x208503, + 0x20aa43, + 0xae888, + 0xae888, + 0x266a83, + 0x1c0443, + 0x2000c2, + 0x35a12402, + 0x266a83, + 0x26e2c3, + 0x3433c3, + 0x22e004, + 0x217fc3, + 0x23e083, + 0xae888, + 0x2000c2, + 0x36212402, + 0x22ea43, + 0x217fc3, + 0x5803, + 0x23e083, + 0x682, + 0x203b42, + 0x21fcc2, + 0x21e1c3, + 0x2f8e43, + 0x2000c2, + 0x146bc5, + 0xae888, + 0x178d87, + 0x212402, + 0x233fc3, + 0x24d704, + 0x2033c3, + 0x266a83, + 0x204903, + 0x23cb03, + 0x217fc3, + 0x213cc3, + 0x23e083, + 0x234fc3, + 0x140d13, + 0x142dd4, + 0x146bc5, + 0x178d87, + 0x1dbc9, + 0x110b86, + 0x121b4b, + 0x36fc6, + 0x54bc7, + 0xe786, + 0x649, + 0x1d818a, + 0x9110d, + 0x127d8c, + 0x1198ca, + 0x15d048, + 0x1b5a05, + 0x1dc08, + 0x13a06, + 0x1ce786, + 0x134c46, + 0x602, + 0x2293c2, + 0x6f204, + 0xa0e86, + 0x1411d0, + 0x147a54e, + 0x1e46, + 0x696cc, + 0x37b22f0b, + 0x146bc5, + 0x15434b, + 0x37fce6c4, + 0x1c0247, + 0x23c91, + 0x11a7ca, + 0x22ea43, + 0x38285648, + 0x6bc45, + 0xf988, + 0x1ff44, + 0x14c705, + 0x38561cc6, + 0x9b306, + 0xc9b46, + 0x9620a, + 0x96ecc, + 0x1c2043, + 0x1c4104, + 0x38a120c4, + 0x51709, + 0x164347, + 0x1167ca, + 0x14dac89, + 0x605, + 0x103583, + 0x38e35107, + 0x2a7c5, + 0x153d986, + 0x14731c6, + 0xb3f8c, + 0x104248, + 0x390408c3, + 0xfa24b, + 0x12bd4b, + 0x3964950c, + 0x140ba83, + 0xc96c8, + 0xfa4c5, + 0xc6c09, + 0xeca43, + 0x11fb08, + 0x141b5c6, + 0x8e8c7, + 0x39b60b09, + 0x99c87, + 0xf054a, + 0x3afc6788, + 0x11838d, + 0xff48, + 0x1ac3, + 0x1445009, + 0x3a643, + 0x36fc6, + 0x107788, + 0x13904, + 0x154c85, + 0x1492ec3, + 0x22387, + 0x39e22383, + 0x3a3c78c6, + 0x3a637e84, + 0x3ab09647, + 0x107784, + 0x107784, + 0x107784, + 0x107784, + 0x41, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x2000c2, + 0x212402, + 0x266a83, + 0x209582, + 0x217fc3, + 0x23e083, + 0x208503, + 0x38644f, + 0x38680e, + 0xae888, + 0x22ea43, + 0x44cc7, + 0x233fc3, + 0x266a83, + 0x2191c3, + 0x217fc3, + 0x23e083, + 0x1d84, + 0x157d04, + 0x1b4744, + 0x21afc3, + 0x324007, + 0x207d42, + 0x272549, + 0x200ac2, + 0x3a58cb, + 0x2a6b8a, + 0x2aec89, + 0x200542, + 0x220306, + 0x244495, + 0x3a5a15, + 0x387d93, + 0x3a5f93, + 0x2272c2, + 0x2272c5, + 0x25f44c, + 0x27ad0b, + 0x277a05, + 0x201802, + 0x239202, + 0x381b06, + 0x203502, + 0x2cf9c6, + 0x21d58d, + 0x22a54c, + 0x38b884, + 0x200882, + 0x222b02, + 0x3a51c8, + 0x200202, + 0x336d46, + 0x39c70f, + 0x357dd0, + 0x229804, + 0x244655, + 0x387f13, + 0x24c943, + 0x369f8a, + 0x20c5c7, + 0x3a1ec9, + 0x316687, + 0x30bf02, + 0x200282, + 0x3c90c6, + 0x204cc2, + 0xae888, + 0x207f42, + 0x208a02, + 0x228fc7, + 0x348187, + 0x348191, + 0x218885, + 0x21888e, + 0x2194cf, + 0x20cfc2, + 0x3236c7, + 0x21b008, + 0x20aac2, + 0x21c942, + 0x227846, + 0x22784f, + 0x26c690, + 0x22c442, + 0x20cf02, + 0x238b48, + 0x214803, + 0x261248, + 0x2eea8d, + 0x20cf03, + 0x3cc248, + 0x28734f, + 0x28770e, + 0x25d54a, + 0x26cb11, + 0x26cf90, + 0x30280d, + 0x302b4c, + 0x3c20c7, + 0x36a107, + 0x37e109, + 0x29a842, + 0x205082, + 0x256b8c, + 0x256e8b, + 0x200d42, + 0x2d38c6, + 0x202282, + 0x200482, + 0x361e82, + 0x212402, + 0x22f244, + 0x239d87, + 0x22c982, + 0x240307, + 0x241b47, + 0x230a82, + 0x211d02, + 0x244b85, + 0x20da02, + 0x3985ce, + 0x3d068d, + 0x233fc3, + 0x28cf0e, + 0x2bb64d, + 0x35cc43, + 0x203142, + 0x28ac84, + 0x29a802, + 0x223ec2, + 0x3930c5, + 0x3a3b07, + 0x2481c2, + 0x20fa02, + 0x24d307, + 0x251a88, + 0x2ba882, + 0x27cf06, + 0x256a0c, + 0x256d4b, + 0x2091c2, + 0x261d4f, + 0x262110, + 0x26250f, + 0x2628d5, + 0x262e14, + 0x26330e, + 0x26368e, + 0x263a0f, + 0x263dce, + 0x264154, + 0x264653, + 0x264b0d, + 0x27c349, + 0x292a43, + 0x2033c2, + 0x2d2685, + 0x2033c6, + 0x200382, + 0x3451c7, + 0x266a83, + 0x200642, + 0x23e108, + 0x26cd51, + 0x26d190, + 0x202182, + 0x291c47, + 0x204b82, + 0x277507, + 0x206902, + 0x207089, + 0x381ac7, + 0x294648, + 0x361b06, + 0x207483, + 0x207485, + 0x234242, + 0x2004c2, + 0x3c94c5, + 0x3b3785, + 0x201482, + 0x219303, + 0x3546c7, + 0x20bdc7, + 0x204d02, + 0x249084, + 0x20eb03, + 0x2f6f89, + 0x20eb08, + 0x202702, + 0x20a682, + 0x26b947, + 0x26ca45, + 0x273508, + 0x2b1347, + 0x209f03, + 0x2a0d06, + 0x30268d, + 0x302a0c, + 0x305e06, + 0x206b02, + 0x208c82, + 0x20b982, + 0x2871cf, + 0x2875ce, + 0x365507, + 0x204482, + 0x388c05, + 0x388c06, + 0x215782, + 0x200bc2, + 0x293506, + 0x206583, + 0x206586, + 0x2d8a45, + 0x2d8a4d, + 0x2d92d5, + 0x2da14c, + 0x2da4cd, + 0x2da812, + 0x20a942, + 0x2720c2, + 0x203882, + 0x36ac46, + 0x204a46, + 0x202542, + 0x203446, + 0x201102, + 0x324805, + 0x202582, + 0x398709, + 0x22ce4c, + 0x22d18b, + 0x2003c2, + 0x252e48, + 0x202a42, + 0x200a82, + 0x278706, + 0x245ac5, + 0x200a87, + 0x22dcc5, + 0x257e45, + 0x201b42, + 0x21dcc2, + 0x205b42, + 0x298c07, + 0x2fd00d, + 0x2fd38c, + 0x235507, + 0x27ce82, + 0x211c82, + 0x3dc788, + 0x248d88, + 0x34f348, + 0x3bb1c4, + 0x372d07, + 0x36aa43, + 0x22d782, + 0x204ac2, + 0x2fe3c9, + 0x30b287, + 0x216982, + 0x278b05, + 0x242c42, + 0x20d402, + 0x2f8b83, + 0x2f8b86, + 0x306d42, + 0x308142, + 0x200402, + 0x3616c6, + 0x34de07, + 0x216782, + 0x200902, + 0x26108f, + 0x28cd4d, + 0x28fd0e, + 0x2bb4cc, + 0x208842, + 0x205302, + 0x361945, + 0x325d86, + 0x200b82, + 0x205502, + 0x200682, + 0x28d0c4, + 0x2c14c4, + 0x389fc6, + 0x207742, + 0x28d807, + 0x23c643, + 0x23c648, + 0x23d1c8, + 0x245207, + 0x249946, + 0x20ab02, + 0x2186c3, + 0x2186c7, + 0x292246, + 0x2ecb85, + 0x27a1c8, + 0x2018c2, + 0x3c1007, + 0x207142, + 0x25cdc2, + 0x201702, + 0x219649, + 0x203c02, + 0x10acc8, + 0x201f42, + 0x235783, + 0x3599c7, + 0x200f02, + 0x22cfcc, + 0x22d2cb, + 0x305e86, + 0x3034c5, + 0x203d02, + 0x202a82, + 0x2cb146, + 0x20dd03, + 0x36a307, + 0x2b3f42, + 0x2008c2, + 0x244315, + 0x3a5bd5, + 0x387c53, + 0x3a6113, + 0x2596c7, + 0x28b111, + 0x2908d0, + 0x2f7b92, + 0x29b711, + 0x2a0548, + 0x2a0550, + 0x2a2c8f, + 0x2a6953, + 0x2aea52, + 0x2b8190, + 0x36f14f, + 0x3a4112, + 0x2bac51, + 0x2bfa93, + 0x3426d2, + 0x2d868f, + 0x2e010e, + 0x2e3512, + 0x2e43d1, + 0x2e79cf, + 0x2ea38e, + 0x2ed451, + 0x2fa9d0, + 0x304412, + 0x307211, + 0x309090, + 0x321ecf, + 0x37ab11, + 0x3d2fd0, + 0x33fac6, + 0x314b47, + 0x2153c7, + 0x202402, + 0x288985, + 0x3135c7, + 0x21fcc2, + 0x208d82, + 0x22b8c5, + 0x208743, + 0x26ec86, + 0x2fd1cd, + 0x2fd50c, + 0x2034c2, + 0x25f2cb, + 0x27abca, + 0x22718a, + 0x2ca549, + 0x2fc34b, + 0x2b148d, + 0x313ccc, + 0x240cca, + 0x2466cc, + 0x24e88b, + 0x27784c, + 0x27bd0e, + 0x29cb4b, + 0x2b668c, + 0x2ec543, + 0x2edf06, + 0x3c6782, + 0x305102, + 0x25cb43, + 0x201502, + 0x204243, + 0x353446, + 0x262a87, + 0x2c3846, + 0x2158c8, + 0x354548, + 0x3800c6, + 0x20e482, + 0x31598d, + 0x315ccc, + 0x32bf07, + 0x319707, + 0x223542, + 0x216b82, + 0x203b02, + 0x284302, + 0x336c56, + 0x33b795, + 0x3407d6, + 0x3437d3, + 0x343e92, + 0x35bc93, + 0x35de52, + 0x3b6bcf, + 0x3c5758, + 0x3c6257, + 0x3c6c59, + 0x3c8b18, + 0x3c96d8, + 0x3cb9d7, + 0x3cc457, + 0x3ce196, + 0x3d1cd3, + 0x3d2755, + 0x3d33d2, + 0x3d3853, + 0x212402, + 0x217fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x208503, + 0x2000c2, + 0x202642, + 0x3ce98545, + 0x3d25ef05, + 0x3d73ed86, + 0xae888, + 0x3dac0105, + 0x212402, + 0x204542, + 0x3de5de45, + 0x3e285fc5, + 0x3e687a87, + 0x3ea87dc9, + 0x3ef4da84, 0x200382, 0x200642, - 0x3e249a05, - 0x3e69d789, - 0x3eb2fb48, - 0x3eeb4985, - 0x3f350107, - 0x3f61d988, - 0x3fb09745, - 0x3fe9e2c6, - 0x403a2709, - 0x406db0c8, - 0x40aca648, - 0x40e9ddca, - 0x412c21c4, - 0x4168e885, - 0x41ac6c08, - 0x41f44945, - 0x20fe82, - 0x42297703, - 0x426aa1c6, - 0x42aaf5c8, - 0x42ef2f86, - 0x4320ad88, - 0x43785546, - 0x43a02c44, - 0x43e08482, - 0x446f4cc7, - 0x44ab0b04, - 0x44e79487, - 0x453cfc87, + 0x3f25bf05, + 0x3f69e949, + 0x3fb36248, + 0x3feb87c5, + 0x403513c7, + 0x40623708, + 0x40b08c85, + 0x40e9f486, + 0x413a9a89, + 0x416dd6c8, + 0x41ad02c8, + 0x41e9ef8a, + 0x422ef084, + 0x426ad705, + 0x42acc788, + 0x42e48985, + 0x214882, + 0x4324bd03, + 0x436abe06, + 0x43a6af08, + 0x43ef4246, + 0x4434df48, + 0x447af006, + 0x44a463c4, + 0x44e03182, + 0x45707b87, + 0x45ab43c4, + 0x45e81487, + 0x463da087, 0x2003c2, - 0x456a2c85, - 0x45a13504, - 0x45fa3407, - 0x4623d187, - 0x466830c6, - 0x46a7f445, - 0x46e9d887, - 0x472daf48, - 0x477d0007, - 0x47b41189, - 0x47ed7505, - 0x48331207, - 0x48692a06, - 0x647cb, - 0x48b3aec8, - 0x225bcd, - 0x25d2c9, - 0x27418b, - 0x27c08b, - 0x2b014b, - 0x2f010b, - 0x320d8b, - 0x32104b, - 0x321e89, - 0x322e8b, - 0x32314b, - 0x323c8b, - 0x324e0a, - 0x32534a, - 0x32594c, - 0x32934b, - 0x329aca, - 0x33e6ca, - 0x34b30e, - 0x34d44e, - 0x34d7ca, - 0x34f64a, - 0x350c0b, - 0x350ecb, - 0x3519cb, - 0x36cdcb, - 0x36d3ca, - 0x36e08b, - 0x36e34a, - 0x36e5ca, - 0x36e84a, - 0x38e64b, - 0x39510b, - 0x397c0e, - 0x397f8b, - 0x39e8cb, - 0x39fc0b, - 0x3a3fca, - 0x3a4249, - 0x3a448a, - 0x3a5d8a, - 0x3bdf4b, - 0x3ca84b, - 0x3cb24a, - 0x3cc0cb, - 0x3d520b, - 0x3dfe4b, - 0x48e81788, - 0x4928ae89, - 0x496a5789, - 0x49aed408, - 0x3597c5, - 0x2041c3, - 0x251084, - 0x3015c5, - 0x21f586, - 0x307385, - 0x28a004, - 0x37f048, - 0x31bb05, - 0x294984, - 0x3c7607, - 0x2a4b0a, - 0x38f4ca, - 0x360107, - 0x34c207, - 0x2e6307, - 0x280947, - 0x334605, - 0x3b9b46, - 0x2f2207, - 0x39bc04, - 0x2f9b46, - 0x2f9a46, - 0x3c2d85, - 0x3b6684, - 0x29ee06, - 0x2a3bc7, - 0x34bb86, - 0x3adf47, - 0x251143, - 0x384106, - 0x238e85, - 0x280487, - 0x26a5ca, - 0x356504, - 0x219d88, - 0x31a2c9, - 0x2d4847, - 0x390606, - 0x3c5808, - 0x2f36c9, - 0x383f44, - 0x31eb84, - 0x2dea45, - 0x222b48, - 0x2d4b07, - 0x36c9c9, - 0x34cdc8, - 0x318406, - 0x264a46, - 0x29f988, - 0x36b706, - 0x281445, - 0x283186, - 0x279b88, - 0x27f9c6, - 0x255d8b, - 0x39d746, - 0x2a14cd, - 0x3d0845, - 0x2b09c6, - 0x20c045, - 0x24a789, - 0x370447, - 0x385188, - 0x291386, - 0x2a0689, - 0x3b1306, - 0x26a545, - 0x2a6dc6, - 0x2e5346, - 0x2d9209, - 0x2c0b06, - 0x2a4807, - 0x360b05, - 0x201583, - 0x21b7c5, - 0x34dd07, - 0x288f46, - 0x3d0749, - 0x346bc6, - 0x279686, - 0x20f849, - 0x282b89, - 0x2a8587, - 0x343488, - 0x2a7789, - 0x280c08, - 0x394486, - 0x2e2e85, - 0x2cfd8a, - 0x279706, - 0x33a806, - 0x2dc705, - 0x2523c8, - 0x326447, - 0x22f5ca, - 0x24e1c6, - 0x2e05c5, - 0x309186, - 0x215f87, - 0x3904c7, - 0x21c2c5, - 0x26a705, - 0x263586, - 0x269d46, - 0x26c0c6, - 0x2c70c4, - 0x282109, - 0x28bd06, - 0x30618a, - 0x2211c8, - 0x330f08, - 0x38f4ca, - 0x2af785, - 0x2a3b05, - 0x3c4f48, - 0x2c4f08, - 0x237c47, - 0x3b9d86, - 0x333988, - 0x2108c7, - 0x274848, - 0x2bebc6, - 0x283ec8, - 0x29c606, - 0x27ba87, - 0x3681c6, - 0x29ee06, - 0x2643ca, - 0x305206, - 0x2e2e89, - 0x36f506, - 0x2a5c8a, - 0x202c49, - 0x241706, - 0x2c2844, - 0x31e8cd, - 0x28b107, - 0x3b2a86, - 0x2ca505, - 0x3b1385, - 0x391106, - 0x2a7349, - 0x2bd687, - 0x27ab86, - 0x31db46, - 0x28a089, - 0x281384, - 0x244744, - 0x204088, - 0x356846, - 0x2a6ec8, - 0x318a88, - 0x2883c7, - 0x3c0549, - 0x26c2c7, - 0x2ba24a, - 0x2fcb8f, - 0x2e43ca, - 0x3d9e45, - 0x279dc5, - 0x2173c5, - 0x3c2147, - 0x215b43, - 0x343688, - 0x3de2c6, - 0x3de3c9, - 0x2f2b06, - 0x2d9047, - 0x2a0449, - 0x385088, - 0x2dc7c7, - 0x31f203, - 0x359845, - 0x215ac5, - 0x2c6f0b, - 0x344a04, - 0x23ba44, - 0x277906, - 0x31f3c7, - 0x39168a, - 0x3803c7, - 0x293607, - 0x27e985, - 0x3c8785, - 0x270489, - 0x29ee06, - 0x38024d, - 0x298b05, - 0x2bc683, - 0x226283, - 0x35c505, - 0x334285, - 0x3c5808, - 0x27b4c7, - 0x2444c6, - 0x2a5406, - 0x22a145, - 0x233087, - 0x287ec7, - 0x22b447, - 0x28e90a, - 0x3841c8, - 0x2c70c4, - 0x27f747, - 0x27d6c7, - 0x35e406, - 0x29bc87, - 0x2e9688, - 0x357b08, - 0x370346, - 0x34c448, - 0x2c0b84, - 0x2f2206, - 0x37ff46, - 0x3bbc46, - 0x204506, - 0x2a3044, - 0x280a06, - 0x2c95c6, - 0x29f1c6, - 0x245806, - 0x3d0d46, - 0x2e94c6, - 0x2443c8, - 0x2bb748, - 0x2dfcc8, - 0x307588, - 0x3c4ec6, - 0x206a05, - 0x21b786, - 0x2b4a05, - 0x393907, - 0x29d485, - 0x20d743, - 0x226305, - 0x2ed004, - 0x3d0e85, - 0x202943, - 0x395407, - 0x36c188, - 0x3ae006, - 0x37e88d, - 0x279d86, - 0x29e785, - 0x205243, - 0x2c65c9, - 0x281506, - 0x299486, - 0x292104, - 0x2e4347, - 0x35bf06, - 0x244945, - 0x23a8c3, - 0x206284, - 0x27d886, - 0x35ad44, - 0x26e588, - 0x3c7989, - 0x2bdc09, - 0x2a6cca, - 0x2a914d, - 0x361a87, - 0x3ba086, - 0x2afb04, - 0x2806c9, - 0x285b48, - 0x28ad06, - 0x234e86, - 0x29bc87, - 0x2c74c6, - 0x2261c6, - 0x287346, - 0x3cfd0a, - 0x21d988, - 0x265085, - 0x295e09, - 0x2d528a, - 0x30b048, - 0x2a34c8, - 0x299408, - 0x2b0d0c, - 0x34da05, - 0x2a5688, - 0x2bba46, - 0x372046, - 0x3db607, - 0x3802c5, - 0x283305, - 0x2bdac9, - 0x20d447, - 0x3de385, - 0x2283c7, - 0x226283, - 0x2d5745, - 0x2273c8, - 0x2d6d07, - 0x2a3389, - 0x2e2d45, - 0x380fc4, - 0x2a8e08, - 0x2c1e87, - 0x2dc988, - 0x20d188, - 0x2b1a85, - 0x20c206, - 0x2a5506, - 0x2dee09, - 0x380047, - 0x2b52c6, - 0x3de007, - 0x2027c3, - 0x21f844, - 0x2da0c5, - 0x2331c4, - 0x246744, - 0x389507, - 0x2664c7, - 0x27ad44, - 0x2a31d0, - 0x296007, - 0x3c8785, - 0x30394c, - 0x20cf44, - 0x2b9a08, - 0x27b989, - 0x3bcb46, - 0x302a48, - 0x267884, - 0x277c08, - 0x22fbc6, - 0x264248, - 0x2a4186, - 0x28ba4b, - 0x32b105, - 0x2d9f48, - 0x211b44, - 0x281e8a, - 0x2a3389, - 0x3680c6, - 0x2bbc48, - 0x259345, - 0x2c5bc4, - 0x2b9906, - 0x22b308, - 0x281788, - 0x32dc86, - 0x384404, - 0x2cfd06, - 0x26c347, - 0x279387, - 0x29bc8f, - 0x339e47, - 0x2417c7, - 0x372245, - 0x372ac5, - 0x2a8249, - 0x2ead06, - 0x389745, - 0x282e87, - 0x3db888, - 0x300805, - 0x3681c6, - 0x221008, - 0x2f2f8a, - 0x22b008, - 0x28e347, - 0x2fcfc6, - 0x295dc6, - 0x2003c3, - 0x212503, - 0x2d5449, - 0x2a7609, - 0x2b9806, - 0x2e2d45, - 0x2b0b88, - 0x2bbc48, - 0x36b888, - 0x2873cb, - 0x37eac7, - 0x31bdc9, - 0x29bf08, - 0x34f104, - 0x3bb888, - 0x28fe49, - 0x2b55c5, - 0x3c2047, - 0x21f8c5, - 0x281688, - 0x29324b, - 0x29d5d0, - 0x2b0545, - 0x211a8c, - 0x244685, - 0x27ea03, - 0x2bf706, - 0x2c8b04, - 0x368486, - 0x2a3bc7, - 0x202804, - 0x242808, - 0x34354d, - 0x318845, - 0x2a2cc4, - 0x2ae044, - 0x2b3e49, - 0x2b2308, - 0x32b5c7, - 0x22fc48, - 0x2821c8, - 0x27ae85, - 0x2d0e87, - 0x27ae07, - 0x2cd307, - 0x26a709, - 0x2879c9, - 0x3dfb46, - 0x301006, - 0x282f46, - 0x322605, - 0x3b8a04, - 0x3c4206, - 0x3c7086, - 0x27aec8, - 0x215c4b, - 0x3563c7, - 0x2afb04, - 0x35be46, - 0x2e99c7, - 0x36f805, - 0x2971c5, - 0x2ae204, - 0x287946, - 0x3c4288, - 0x2806c9, - 0x24bb46, - 0x285948, - 0x244a06, - 0x360a48, - 0x321a0c, - 0x27ad46, - 0x29e44d, - 0x29e8cb, - 0x2a48c5, - 0x288007, - 0x2c0c06, - 0x390388, - 0x3dfbc9, - 0x2ee4c8, - 0x3c8785, - 0x39b947, - 0x280d08, - 0x23b4c9, - 0x35bb86, - 0x25138a, - 0x390108, - 0x2ee30b, - 0x21dc0c, - 0x277d08, - 0x27cc06, - 0x2d0888, - 0x2f2c07, - 0x33a409, - 0x35024d, - 0x29ed06, - 0x2250c8, - 0x2bb609, - 0x2c71c8, - 0x283fc8, - 0x2c9ecc, - 0x2cab87, - 0x2cb7c7, - 0x26a545, - 0x2bdf87, - 0x3db748, - 0x2b9986, - 0x24b9cc, - 0x300288, - 0x2db2c8, - 0x307846, - 0x2af0c7, - 0x3dfd44, - 0x307588, - 0x2cf84c, - 0x28538c, - 0x3d9ec5, - 0x3c2e07, - 0x384386, - 0x2af046, - 0x24a948, - 0x21d284, - 0x34bb8b, - 0x27a34b, - 0x2fcfc6, - 0x3433c7, - 0x343ec5, - 0x272605, - 0x34bcc6, - 0x259305, - 0x3449c5, - 0x2d4287, - 0x20e989, - 0x269f04, - 0x25a2c5, - 0x2f6d85, - 0x35aac8, - 0x28d785, - 0x2cf209, - 0x2badc7, - 0x2badcb, - 0x2fbbc6, - 0x244109, - 0x3b65c8, - 0x290185, - 0x2cd408, - 0x287a08, - 0x253047, - 0x2b4247, - 0x389589, - 0x264187, - 0x29d389, - 0x2da70c, - 0x341088, - 0x2c0649, - 0x2c2f87, - 0x282289, - 0x33c3c7, - 0x21dd08, - 0x33a345, - 0x2f2186, - 0x2ca548, - 0x217488, - 0x2d5149, - 0x344a07, - 0x273005, - 0x3c3909, - 0x2f42c6, - 0x292a04, - 0x37b446, - 0x2af448, - 0x320807, - 0x215e48, - 0x34c509, - 0x33be47, - 0x2a4cc6, - 0x2880c4, - 0x226389, - 0x2d0d08, - 0x307707, - 0x367a06, - 0x215b86, - 0x33a784, - 0x34c706, - 0x239f83, - 0x32ac89, - 0x32b0c6, - 0x2a3705, - 0x2a5406, - 0x2d95c5, - 0x281188, - 0x347207, - 0x2306c6, - 0x287206, - 0x330f08, - 0x2a83c7, - 0x29ed45, - 0x2a2fc8, - 0x3aa048, - 0x390108, - 0x244545, - 0x2f2206, - 0x2bd9c9, - 0x2dec84, - 0x2d944b, - 0x225ecb, - 0x264f89, - 0x226283, - 0x257845, - 0x3ae4c6, - 0x246508, - 0x306ec4, - 0x3ae006, - 0x28ea49, - 0x2c93c5, - 0x2d41c6, - 0x2c1e86, - 0x222dc4, - 0x29958a, - 0x2a3648, - 0x217486, - 0x2cd045, - 0x343d47, - 0x3344c7, - 0x20c204, - 0x226107, - 0x2ba244, - 0x34ce46, - 0x210b43, - 0x26a705, - 0x2b6e45, - 0x23ef88, - 0x27f905, - 0x27aa89, - 0x2a9fc7, - 0x3073cb, - 0x2a9fcc, - 0x2aa5ca, - 0x350107, - 0x203d03, - 0x278808, - 0x244705, - 0x300885, - 0x359904, - 0x21dc06, - 0x27b986, - 0x34c747, - 0x23a80b, - 0x2a3044, - 0x355f44, - 0x2d4444, - 0x2d8ec6, - 0x202804, - 0x222c48, - 0x359705, - 0x21c145, - 0x36b7c7, - 0x288109, - 0x334285, - 0x39110a, - 0x3db9c9, - 0x2b174a, - 0x3cfe49, - 0x3545c4, - 0x31dc05, - 0x2c75c8, - 0x3a34cb, - 0x2dea45, - 0x24c386, - 0x241304, - 0x27afc6, - 0x33bcc9, - 0x2e9ac7, - 0x346d88, - 0x2a94c6, - 0x26c2c7, - 0x281788, - 0x377746, - 0x3c72c4, - 0x3817c7, - 0x382e85, - 0x392987, - 0x267784, - 0x2c0b86, - 0x30ad48, - 0x29ea88, - 0x2ff987, - 0x202808, - 0x29c6c5, - 0x226004, - 0x38f3c8, - 0x202904, - 0x217345, - 0x30af44, - 0x2109c7, - 0x28bdc7, - 0x2823c8, - 0x2dcb06, - 0x27f885, - 0x27a888, - 0x246848, - 0x2a6c09, - 0x2261c6, - 0x22f648, - 0x281d0a, - 0x36f888, - 0x309745, - 0x21b986, - 0x2a7208, - 0x39ba0a, - 0x219507, - 0x285f85, - 0x292c08, - 0x270fc4, - 0x252446, - 0x2cbb48, - 0x3d0d46, - 0x334c08, - 0x2d7ac7, - 0x3c7506, - 0x2c2844, - 0x237687, - 0x2bc004, - 0x33bc87, - 0x367e0d, - 0x237cc5, - 0x2d6b0b, - 0x285606, - 0x251e88, - 0x2427c4, - 0x3c50c6, - 0x27d886, - 0x2d0bc7, - 0x29e10d, - 0x304807, - 0x2bc5c8, - 0x284145, - 0x270648, - 0x2d4a86, - 0x29c748, - 0x238606, - 0x3036c7, - 0x282749, - 0x35a587, - 0x28afc8, - 0x34a005, - 0x22a1c8, - 0x2aef85, - 0x228e05, - 0x362b45, - 0x24dec3, - 0x204584, - 0x292e05, - 0x3a2709, - 0x367906, - 0x2e9788, - 0x2c2105, - 0x2bde47, - 0x371bca, - 0x2d4109, - 0x2e524a, - 0x2dfd48, - 0x22820c, - 0x282f0d, - 0x311883, - 0x334b08, - 0x206245, - 0x2f2d46, - 0x384f06, - 0x31e585, - 0x3de109, - 0x33d2c5, - 0x27a888, - 0x258546, - 0x369706, - 0x2a8cc9, - 0x3a9007, - 0x293506, - 0x371b48, - 0x3bbb48, - 0x2ed607, - 0x2c974e, - 0x2d4cc5, - 0x23b3c5, - 0x3d0c48, - 0x271e87, - 0x200e42, - 0x2c9b84, - 0x36838a, - 0x3077c8, - 0x287b46, - 0x2a0588, - 0x2a5506, - 0x288b88, - 0x2b52c8, - 0x228dc4, - 0x2be205, - 0x668c84, - 0x668c84, - 0x668c84, - 0x20aec3, - 0x215a06, - 0x27ad46, - 0x2a458c, - 0x202dc3, - 0x267786, - 0x21a604, - 0x281488, - 0x28e885, - 0x368486, - 0x2c6d08, - 0x2e0e46, - 0x230646, - 0x3c5608, - 0x2da147, - 0x263f49, - 0x3ae60a, - 0x266644, - 0x29d485, - 0x2e4305, - 0x2d7746, - 0x361ac6, - 0x2a50c6, - 0x3dc246, - 0x264084, - 0x26408b, - 0x264a44, - 0x244285, - 0x2b3a45, - 0x288486, - 0x201b48, - 0x282dc7, - 0x32b044, - 0x25b603, - 0x270ac5, - 0x37b307, - 0x282ccb, - 0x23ee87, - 0x2c6c08, - 0x2be347, - 0x26b746, - 0x25d588, - 0x2c51cb, - 0x301506, - 0x212849, - 0x2c5345, - 0x31f203, - 0x2d41c6, - 0x2d79c8, - 0x20c2c3, - 0x24c343, - 0x281786, - 0x2a5506, - 0x3759ca, - 0x27cc45, - 0x27d6cb, - 0x2a534b, - 0x213c03, - 0x20ea43, - 0x2ba1c4, - 0x370587, - 0x277d04, - 0x281484, - 0x2bb8c4, - 0x36fb88, - 0x2ccf88, - 0x214d49, - 0x2d7588, - 0x3b2d07, - 0x245806, - 0x2e93cf, - 0x2d4e06, - 0x2df404, - 0x2ccdca, - 0x37b207, - 0x2bc106, - 0x292a49, - 0x214cc5, - 0x23f0c5, - 0x214e06, - 0x22a303, - 0x271009, - 0x21db06, - 0x34c2c9, - 0x391686, - 0x26a705, - 0x35c905, - 0x204583, - 0x3706c8, - 0x32b787, - 0x3de2c4, - 0x281308, - 0x371dc4, - 0x359006, - 0x2bf706, - 0x23d646, - 0x2d9e09, - 0x300805, - 0x29ee06, - 0x2713c9, - 0x2d3e06, - 0x2e94c6, - 0x3a14c6, - 0x22bd85, - 0x30af46, - 0x3036c4, - 0x33a345, - 0x217484, - 0x2bcf46, - 0x298ac4, - 0x2109c3, - 0x285c05, - 0x233d88, - 0x3572c7, - 0x306f49, - 0x285e88, - 0x29f751, - 0x2c1f0a, - 0x2fcf07, - 0x357e46, - 0x21a604, - 0x2ca648, - 0x2ea008, - 0x29f90a, - 0x2cefcd, - 0x2a6dc6, - 0x3c5706, - 0x237746, - 0x21c147, - 0x2bc685, - 0x286c47, - 0x2813c5, - 0x2baf04, - 0x3c5e46, - 0x224dc7, - 0x270d0d, - 0x2a7147, - 0x37ef48, - 0x27ab89, - 0x21b886, - 0x35bb05, - 0x23c2c4, - 0x2af546, - 0x20c106, - 0x307946, - 0x2a0e08, - 0x21ad83, - 0x2465c3, - 0x349b05, - 0x31ec06, - 0x2b5285, - 0x2a96c8, - 0x2a3d8a, - 0x347344, - 0x281488, - 0x299408, - 0x2882c7, - 0x286589, - 0x2c6908, - 0x280747, - 0x2bbb46, - 0x3d0d4a, - 0x2af5c8, - 0x30c989, - 0x2b23c8, - 0x21ef89, - 0x357d07, - 0x312785, - 0x2a5906, - 0x2b9808, - 0x252008, - 0x224508, - 0x222dc8, - 0x244285, - 0x200d04, - 0x232708, - 0x241084, - 0x3cfc44, - 0x26a705, - 0x2949c7, - 0x287ec9, - 0x2d09c7, - 0x20f8c5, - 0x277b06, - 0x36f1c6, - 0x201c44, - 0x2a9006, - 0x27db04, - 0x291746, - 0x287c86, - 0x212e86, - 0x3c8785, - 0x2a9587, - 0x203d03, - 0x211609, - 0x330d08, - 0x2805c4, - 0x2805cd, - 0x29eb88, - 0x32a608, - 0x30c906, - 0x282849, - 0x2d4109, - 0x33b9c5, - 0x2a3e8a, - 0x291aca, - 0x2b444c, - 0x2b45c6, - 0x278406, - 0x2d5686, - 0x38ce89, - 0x2f2f86, - 0x21dd86, - 0x33d386, - 0x307588, - 0x202806, - 0x2de54b, - 0x294b45, - 0x21c145, - 0x279485, - 0x203e06, - 0x226043, - 0x23d5c6, - 0x2a70c7, - 0x2ca505, - 0x2d1c05, - 0x3b1385, - 0x310686, - 0x32fa44, - 0x32fa46, - 0x2ab289, - 0x203c8c, - 0x2bac48, - 0x22b284, - 0x30ac46, - 0x285706, - 0x2d79c8, - 0x2bbc48, - 0x203b89, - 0x343d47, - 0x356589, - 0x2726c6, - 0x22c144, - 0x2082c4, - 0x27f6c4, - 0x281788, - 0x287d0a, - 0x334206, - 0x3677c7, - 0x392c07, - 0x244205, - 0x36c944, - 0x28fe06, - 0x2bc6c6, - 0x21d2c3, - 0x330b47, - 0x20d088, - 0x33bb0a, - 0x22be48, - 0x20ad88, - 0x298b05, - 0x2a49c5, - 0x3564c5, - 0x2445c6, - 0x247486, - 0x33c885, - 0x32aec9, - 0x36c74c, - 0x2f4ec7, - 0x29f988, - 0x2521c5, - 0x668c84, - 0x265444, - 0x2d6e44, - 0x218706, - 0x2a650e, - 0x23f147, - 0x21c345, - 0x2dec0c, - 0x310b07, - 0x224d47, - 0x226fc9, - 0x219e49, - 0x285f85, - 0x330d08, - 0x2bd9c9, - 0x38ffc5, - 0x2ca448, - 0x2c0886, - 0x38f646, - 0x202c44, - 0x28ee48, - 0x21ba43, - 0x215604, - 0x270b45, - 0x396f07, - 0x2c2605, - 0x281bc9, - 0x2a118d, - 0x2b3046, - 0x3df784, - 0x3b9d08, - 0x20e7ca, - 0x21c847, - 0x367d45, - 0x215643, - 0x2a550e, - 0x3707cc, - 0x30b147, - 0x2a66c7, - 0x443960c7, - 0xaf286, - 0x647c4, - 0x203083, - 0x2f2fc5, - 0x2d6e45, - 0x2a0948, - 0x29dc09, - 0x22b186, - 0x277d04, - 0x2fce46, - 0x331bcb, - 0x2e844c, - 0x24df87, - 0x2de805, - 0x3a9f48, - 0x2ed3c5, - 0x2ccdc7, - 0x2f4cc7, - 0x245fc5, - 0x226043, - 0x20c584, - 0x2e4205, - 0x269e05, - 0x269e06, - 0x2a9dc8, - 0x224dc7, - 0x385206, - 0x33a686, - 0x362a86, - 0x225249, - 0x2d0f87, - 0x250f86, - 0x2e85c6, - 0x276d06, - 0x2b0ac5, - 0x20a586, - 0x39b0c5, - 0x28d808, - 0x29428b, - 0x28fb46, - 0x392c44, - 0x304e49, - 0x2a9fc4, - 0x2c0808, - 0x30e907, - 0x283ec4, - 0x2c5dc8, - 0x2cb5c4, - 0x2b0b04, - 0x274785, - 0x318886, - 0x36fac7, - 0x23db43, - 0x2a4d85, - 0x2fd1c4, - 0x23b406, - 0x33ba48, - 0x202705, - 0x293f49, - 0x350105, - 0x267788, - 0x21a4c7, - 0x32b1c8, - 0x2c5a07, - 0x241889, - 0x280886, - 0x33e906, - 0x2a78c4, - 0x355e85, - 0x31320c, - 0x279487, - 0x279c87, - 0x361708, - 0x2b3046, - 0x2a7004, - 0x34b0c4, - 0x389409, - 0x2d5786, - 0x270507, - 0x2d0804, - 0x326b06, - 0x38a805, - 0x2dc647, - 0x2de4c6, - 0x251249, - 0x2f0387, - 0x29bc87, - 0x2a8b46, - 0x326a45, - 0x27f408, - 0x21d988, - 0x245a06, - 0x202745, - 0x2cca86, - 0x20af03, - 0x2a07c9, - 0x2a4e4e, - 0x2c5748, - 0x371ec8, - 0x24580b, - 0x294186, - 0x385544, - 0x230644, - 0x2a4f4a, - 0x211987, - 0x251045, - 0x212849, - 0x2c9685, - 0x3cfc87, - 0x2305c4, - 0x3c7b07, - 0x318988, - 0x2d4906, - 0x2c0d09, - 0x2c6a0a, - 0x211906, - 0x29e6c6, - 0x2b39c5, - 0x398545, - 0x36ac07, - 0x245608, - 0x38a748, - 0x228dc6, - 0x35c985, - 0x36184e, - 0x2c70c4, - 0x245985, - 0x277489, - 0x2eab08, - 0x28e286, - 0x2a2acc, - 0x2a3990, - 0x2a614f, - 0x2a8148, - 0x350107, - 0x3c8785, - 0x292e05, - 0x36f949, - 0x292e09, - 0x2cfe06, - 0x2deac7, - 0x355d85, - 0x237c49, - 0x35e486, - 0x2f2dcd, - 0x27f589, - 0x281484, - 0x2c54c8, - 0x2327c9, - 0x3343c6, - 0x278a05, - 0x33e906, - 0x346c49, - 0x2d0688, - 0x206a05, - 0x281e04, - 0x2a2c8b, - 0x334285, - 0x246586, - 0x283246, - 0x3b4246, - 0x2875cb, - 0x294049, - 0x33a5c5, - 0x393807, - 0x2c1e86, - 0x231f46, - 0x281a88, - 0x224f09, - 0x37ed0c, - 0x37b108, - 0x31aac6, - 0x32dc83, - 0x22f306, - 0x241745, - 0x27e208, - 0x3d9d46, - 0x2dc888, - 0x380445, - 0x291805, - 0x21a608, - 0x3bba07, - 0x384e47, - 0x34c747, - 0x302a48, - 0x2d7848, - 0x2e9f06, - 0x2bcd87, - 0x21f707, - 0x2b3f4a, - 0x2168c3, - 0x203e06, - 0x22b3c5, - 0x213504, - 0x27ab89, - 0x241804, - 0x204844, - 0x2a4204, - 0x2a66cb, - 0x32b6c7, - 0x310645, - 0x29c3c8, - 0x277b06, - 0x277b08, - 0x27cb86, - 0x28ed85, - 0x28f045, - 0x290746, - 0x292408, - 0x292988, - 0x27ad46, - 0x29c20f, - 0x2a0290, - 0x3d0845, - 0x203d03, - 0x22c205, - 0x31bd08, - 0x292d09, - 0x390108, - 0x2de8c8, - 0x235288, - 0x32b787, - 0x2777c9, - 0x2dca88, - 0x291004, - 0x2a4088, - 0x35ab89, - 0x2bd387, - 0x34de44, - 0x2d0a88, - 0x2a934a, - 0x2fd446, - 0x2a6dc6, - 0x226089, - 0x2a3bc7, - 0x2d9c88, - 0x21fd08, - 0x33ad48, - 0x24ef85, - 0x3d3205, - 0x21c145, - 0x2d6e05, - 0x2bb447, - 0x226045, - 0x2ca505, - 0x3dde06, - 0x390047, - 0x3a3407, - 0x2a9646, - 0x2e0285, - 0x246586, - 0x241985, - 0x2c4d88, - 0x355d04, - 0x2d3e86, - 0x324604, - 0x2c5bc8, - 0x318c0a, - 0x27b4cc, - 0x23aa05, - 0x21c206, - 0x37eec6, - 0x202586, - 0x31ab44, - 0x3b9a05, - 0x27c447, - 0x2a3c49, - 0x2d9307, - 0x668c84, - 0x668c84, - 0x32b545, - 0x2dda04, - 0x2a204a, - 0x277986, - 0x2bd7c4, - 0x3c2d85, - 0x3bd405, - 0x2bc5c4, - 0x282e87, - 0x3c3a87, - 0x2d8ec8, - 0x26d5c8, - 0x206a09, - 0x372488, - 0x2a220b, - 0x2acc44, - 0x232045, - 0x3897c5, - 0x34c6c9, - 0x224f09, - 0x304d48, - 0x34cc48, - 0x288484, - 0x285745, - 0x2041c3, - 0x2d7705, - 0x29ee86, - 0x29da4c, - 0x20c006, - 0x278906, - 0x28e505, - 0x310708, - 0x2e86c6, - 0x357fc6, - 0x2a6dc6, - 0x22bbcc, - 0x389884, - 0x362bca, - 0x28e448, - 0x29d887, - 0x2fd0c6, - 0x22b247, - 0x2fca45, - 0x367a06, - 0x35ee86, - 0x372987, - 0x2c6704, - 0x210ac5, - 0x277484, - 0x2baf87, - 0x2776c8, - 0x27828a, - 0x280b87, - 0x2aa847, - 0x350087, - 0x2ed509, - 0x29da4a, - 0x22c103, - 0x357285, - 0x212ec3, - 0x2bb909, - 0x2d7c08, - 0x372247, - 0x390209, - 0x21da86, - 0x339f88, - 0x395385, - 0x24694a, - 0x343809, - 0x370209, - 0x3db607, - 0x2ea109, - 0x212d88, - 0x288d86, - 0x21c3c8, - 0x2d1f47, - 0x264187, - 0x3db9c7, - 0x2daf48, - 0x30aac6, - 0x2a9105, - 0x27c447, - 0x29e1c8, - 0x362a04, - 0x306044, - 0x293407, - 0x2b5647, - 0x2bd84a, - 0x288d06, - 0x32eeca, - 0x2c9ac7, - 0x2c6e87, - 0x210b84, - 0x29d444, - 0x2dc546, - 0x35c184, - 0x35c18c, - 0x30e845, - 0x2172c9, - 0x2ef004, - 0x2bc685, - 0x20e748, - 0x292a45, - 0x391106, - 0x292f44, - 0x2acb4a, - 0x2ef646, - 0x255fca, - 0x3d0007, - 0x215f85, - 0x22a305, - 0x24424a, - 0x292585, - 0x2a6cc6, - 0x241084, - 0x2ba346, - 0x36acc5, - 0x3d9e06, - 0x2ff98c, - 0x2e18ca, - 0x291bc4, - 0x245806, - 0x2a3bc7, - 0x2de444, - 0x307588, - 0x24c286, - 0x392a89, - 0x2c8349, - 0x341189, - 0x2d9606, - 0x2d2046, - 0x21c507, - 0x32ae08, - 0x2d1e49, - 0x32b6c7, - 0x29c546, - 0x26c347, - 0x237605, - 0x2c70c4, - 0x21c0c7, - 0x21f8c5, - 0x28a2c5, - 0x200cc7, - 0x245e88, - 0x3a9ec6, - 0x29f00d, - 0x2a0b4f, - 0x2a534d, - 0x202d84, - 0x233e86, - 0x2e1c88, - 0x33d345, - 0x2b4108, - 0x252f0a, - 0x281484, - 0x331e06, - 0x2abe07, - 0x2b7d47, - 0x2da209, - 0x21c385, - 0x2bc5c4, - 0x2be14a, - 0x2c64c9, - 0x2ea207, - 0x30b706, - 0x3343c6, - 0x285686, - 0x381886, - 0x2e158f, - 0x2e1b49, - 0x202806, - 0x389046, - 0x297e89, - 0x2bce87, - 0x2146c3, - 0x22bd46, - 0x212503, - 0x31e448, - 0x26c187, - 0x2a8349, - 0x2bf588, - 0x384f88, - 0x33c506, - 0x20bf49, - 0x2f4e05, - 0x22f244, - 0x312847, - 0x38cf05, - 0x202d84, - 0x361b48, - 0x211c44, - 0x2bcbc7, - 0x36c106, - 0x263645, - 0x2b23c8, - 0x33428b, - 0x331207, - 0x2444c6, - 0x2d4e84, - 0x3854c6, - 0x26a705, - 0x21f8c5, - 0x27f189, - 0x282a89, - 0x2641c4, - 0x264205, - 0x245845, - 0x2467c6, - 0x330e08, - 0x2c8e86, - 0x20cecb, - 0x3bc9ca, - 0x2c5b05, - 0x28f0c6, - 0x23eb85, - 0x24a285, - 0x292647, - 0x204088, - 0x292484, - 0x37fb46, - 0x292a06, - 0x212f47, - 0x31f1c4, - 0x27d886, - 0x3c2245, - 0x3c2249, - 0x2d2244, - 0x36cac9, - 0x27ad46, - 0x2cac48, - 0x245845, - 0x392d05, - 0x3d9e06, - 0x37ec09, - 0x219e49, - 0x278986, - 0x2eac08, - 0x2a12c8, - 0x23eb44, - 0x2be9c4, - 0x2be9c8, - 0x3b2b88, - 0x356689, - 0x29ee06, - 0x2a6dc6, - 0x33384d, - 0x3ae006, - 0x3218c9, - 0x268945, - 0x214e06, - 0x33aec8, - 0x32f985, - 0x21f744, - 0x26a705, - 0x2825c8, - 0x2a1e09, - 0x277544, - 0x2c0b86, - 0x30cb4a, - 0x30b048, - 0x2bd9c9, - 0x26ad4a, - 0x390186, - 0x2a0d08, - 0x2ccb85, - 0x2f0988, - 0x2fcac5, - 0x21d949, - 0x336449, - 0x20c642, - 0x2c5345, - 0x272346, - 0x27ac87, - 0x213505, - 0x3469c6, - 0x316908, - 0x2b3046, - 0x2c7489, - 0x279d86, - 0x281908, - 0x278d45, - 0x38e4c6, - 0x3037c8, - 0x281788, - 0x357c08, - 0x318488, - 0x20a584, - 0x20c243, - 0x2c76c4, - 0x280d86, - 0x237644, - 0x371e07, - 0x357ec9, - 0x2d4445, - 0x21fd06, - 0x22bd46, - 0x2a9c0b, - 0x2bc046, - 0x298d46, - 0x2d3f88, - 0x264a46, - 0x215d83, - 0x208503, - 0x2c70c4, - 0x22f545, - 0x244847, - 0x2776c8, - 0x2776cf, - 0x27c34b, - 0x330c08, - 0x2c0c06, - 0x330f0e, - 0x23b443, - 0x2447c4, - 0x2bbfc5, - 0x2bc446, - 0x28ff0b, - 0x294a86, - 0x221089, - 0x263645, - 0x23da88, - 0x3d29c8, - 0x219d0c, - 0x2a6706, - 0x2d7746, - 0x2e2d45, - 0x28ad88, - 0x27b4c5, - 0x34f108, - 0x2a2e4a, - 0x2a5789, - 0x668c84, - 0x2000c2, - 0x4a201242, - 0x200382, - 0x221dc4, - 0x209e82, - 0x306c44, - 0x208482, - 0x3dc3, - 0x2003c2, - 0x2090c2, - 0x9a048, - 0x29904, - 0x214a83, - 0x232dc3, - 0x308003, - 0xccc2, - 0x49582, - 0x23c803, - 0x21a3c3, - 0x242543, - 0xc782, - 0xc2c2, - 0x1b82, - 0x202703, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21a3c3, - 0x242543, - 0x241f83, - 0x2d3684, - 0x214a83, - 0x235b44, - 0x232dc3, - 0x2e3504, - 0x308003, - 0x2137c7, - 0x23c803, - 0x203dc3, - 0x31bf88, - 0x242543, - 0x27cfcb, - 0x2fdbc3, - 0x2431c6, - 0x233442, - 0x2f850b, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x242543, - 0x21a103, - 0x208a03, - 0x2000c2, - 0x9a048, - 0x399c45, - 0x21f948, - 0x2e3648, - 0x201242, - 0x343045, - 0x3c8847, - 0x203c42, - 0x242a07, - 0x200382, - 0x2555c7, - 0x3742c9, - 0x26d188, - 0x33abc9, - 0x20b342, - 0x3c7387, - 0x22dd84, - 0x3c8907, - 0x3bc8c7, - 0x25ac42, - 0x23c803, - 0x202382, - 0x208482, - 0x2003c2, - 0x214282, - 0x200902, - 0x2090c2, - 0x2df885, - 0x210205, - 0x1242, - 0x32dc3, - 0x214a83, - 0x232dc3, - 0x29a643, - 0x308003, - 0x206c03, - 0x21a3c3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0xa983, - 0x101, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21bc83, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x214903, - 0x4d4ae8c6, - 0x239c3, - 0xd50c5, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x1b02, - 0x9a048, - 0x12a4c3, - 0x3dc3, - 0x1b4103, - 0x455c4, - 0x14226c4, - 0xed7c5, - 0x2000c2, - 0x393bc4, - 0x214a83, - 0x232dc3, - 0x308003, - 0x231a43, + 0x466a3e85, + 0x46a15cc4, + 0x46faaa07, + 0x4723c0c7, + 0x4768aac6, + 0x47a86b45, + 0x47e9ea47, + 0x482dd548, + 0x487da407, + 0x48adcb49, + 0x48ed9845, + 0x4931d047, + 0x49697b86, + 0x27c4b, + 0x49b47b08, + 0x22800d, + 0x25c089, + 0x279d4b, + 0x27b8cb, + 0x2afecb, + 0x39b08b, + 0x325f8b, + 0x32624b, + 0x326709, + 0x32770b, + 0x3279cb, + 0x32850b, + 0x32910a, + 0x32964a, + 0x329c4c, + 0x32e6cb, + 0x32ec0a, + 0x34228a, + 0x34d34e, + 0x34e94e, + 0x34ecca, + 0x350b0a, + 0x351b4b, + 0x351e0b, + 0x35290b, + 0x372ecb, + 0x3734ca, + 0x37418b, + 0x37444a, + 0x3746ca, + 0x37494a, + 0x394a0b, + 0x39bbcb, + 0x39ed4e, + 0x39f0cb, + 0x3a65cb, + 0x3a73cb, + 0x3ab74a, + 0x3ab9c9, + 0x3abc0a, + 0x3ad9ca, + 0x3c514b, + 0x3d00cb, + 0x3d0aca, + 0x3d170b, + 0x3d7a4b, + 0x3e07cb, + 0x49e89188, + 0x4a290209, + 0x4a6a7249, + 0x4aaefcc8, + 0x35f145, + 0x204083, + 0x251f44, + 0x34e385, + 0x34d7c6, + 0x367645, + 0x28f384, + 0x3450c8, + 0x31f645, + 0x299784, + 0x203787, + 0x2a634a, + 0x37738a, + 0x365607, + 0x26b0c7, + 0x2e7ec7, + 0x288047, + 0x33a405, + 0x20e506, + 0x2f34c7, + 0x20fd84, + 0x3ba146, + 0x3ba046, + 0x3dccc5, + 0x389dc4, + 0x29ffc6, + 0x2a5407, + 0x2671c6, + 0x31a487, + 0x235e43, + 0x3a2246, + 0x238d85, + 0x287b87, + 0x26fe0a, + 0x237784, + 0x2219c8, + 0x39a2c9, + 0x2d6b87, + 0x3bba06, + 0x203f48, + 0x2f4989, + 0x3a2084, + 0x2d2a04, + 0x313005, + 0x21e388, + 0x2d6e47, + 0x2b7689, + 0x3690c8, + 0x31b8c6, + 0x266cc6, + 0x2a0b88, + 0x371c86, + 0x25ef05, + 0x28ab86, + 0x281f48, + 0x2870c6, + 0x255f0b, + 0x2be206, + 0x2a280d, + 0x205385, + 0x2b4286, + 0x21f585, + 0x2bc949, + 0x2e0cc7, + 0x3cd248, + 0x39dec6, + 0x2a1949, + 0x2c1246, + 0x26fd85, + 0x2a9606, + 0x2d5506, + 0x2db549, + 0x2c8186, + 0x2a6047, + 0x2d5bc5, + 0x208a43, 0x22d805, - 0x21bc83, - 0x21a8c3, - 0x21a3c3, - 0x24e283, - 0x242543, - 0x20e2c3, - 0x266603, - 0x207783, - 0x5c2, - 0x2aec2, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x2000c2, - 0x202703, - 0x201242, - 0x2a42, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21a3c3, - 0x242543, - 0x2090c2, - 0x9a048, - 0x308003, - 0x1b4103, - 0x9a048, - 0x1b4103, - 0x26f6c3, - 0x214a83, - 0x22fe44, - 0x232dc3, - 0x308003, - 0x206182, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x206182, - 0x2137c3, - 0x21a3c3, - 0x242543, - 0x2f7103, - 0x20e2c3, - 0x2000c2, - 0x201242, - 0x308003, - 0x21a3c3, - 0x242543, - 0x2431c5, - 0x14fc86, - 0x2d3684, - 0x233442, - 0x882, - 0x9a048, - 0x2a42, - 0x49582, - 0x2982, - 0x2000c2, - 0x139b05, - 0x1ce08, - 0x991c3, - 0x201242, - 0x3c604, - 0x51c6c486, - 0x8d04, - 0x10fe4b, - 0x34ac6, - 0xd1407, - 0x12eb09, - 0x232dc3, - 0x48248, - 0x4824b, - 0x486cb, - 0x48d4b, - 0x4908b, - 0x4934b, - 0x4978b, - 0x1d2f06, - 0x308003, - 0xf3605, - 0x68a44, - 0x210983, - 0x1182c7, - 0xe6d44, - 0x6cbc4, - 0x21a3c3, - 0x78a86, - 0x5684, - 0x1b4103, - 0x242543, - 0x2fe7c4, - 0x12bcc7, - 0x14f889, - 0x10fc08, - 0x1b44c4, - 0x1c8a44, - 0x365c6, - 0xa788, - 0x16a605, - 0x8649, - 0x2fb03, - 0x139b05, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x203dc3, - 0x242543, - 0x2fdbc3, - 0x233442, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21bac3, - 0x219a04, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x2e3504, - 0x308003, - 0x21a3c3, - 0x242543, - 0x2431c6, - 0x232dc3, - 0x308003, - 0x10e83, - 0x1b4103, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x139b05, - 0xd1407, - 0x3103, - 0x2fb03, - 0x9a048, - 0x308003, - 0x214a83, - 0x232dc3, - 0x308003, - 0x5cf43, - 0x21a3c3, - 0x242543, - 0x55214a83, - 0x232dc3, - 0x21a3c3, - 0x242543, - 0x9a048, - 0x2000c2, - 0x201242, - 0x214a83, - 0x308003, - 0x21a3c3, - 0x2003c2, - 0x242543, - 0x336987, - 0x2cd68b, - 0x20dcc3, - 0x2cfac8, - 0x32ab87, - 0x3de706, - 0x218c05, - 0x343189, - 0x242f48, - 0x3359c9, - 0x3359d0, - 0x37ab8b, - 0x2e7589, - 0x203103, - 0x2f8bc9, - 0x231506, - 0x23150c, - 0x335bc8, - 0x3db448, - 0x374789, - 0x2c368e, - 0x37408b, - 0x2ba58c, - 0x220dc3, - 0x28c68c, - 0x3d8f49, - 0x23bb47, - 0x232d0c, - 0x2b858a, - 0x24c0c4, - 0x2ee78d, - 0x28c548, - 0x3ba7cd, - 0x3a6cc6, - 0x2d368b, - 0x34fa09, - 0x3892c7, - 0x295946, - 0x267b49, - 0x33b64a, - 0x30c108, - 0x2fd7c4, - 0x2b5a07, - 0x3c51c7, - 0x204684, - 0x223804, - 0x201fc9, - 0x286ac9, - 0x3d9ac8, - 0x398bc5, - 0x20b285, - 0x2068c6, - 0x2ee649, - 0x25318d, - 0x24c488, - 0x2067c7, - 0x218c88, - 0x2355c6, - 0x239c04, - 0x284405, - 0x3cfb46, - 0x3d1e84, - 0x3d8e47, - 0x3e094a, - 0x20d384, - 0x211846, - 0x2124c9, - 0x2124cf, - 0x212a8d, - 0x213306, - 0x21ca10, - 0x21ce06, - 0x21df07, - 0x21e987, - 0x21e98f, - 0x21f1c9, - 0x225986, - 0x227207, - 0x227208, - 0x2275c9, - 0x3ba588, - 0x305c87, - 0x20ed43, - 0x3d87c6, - 0x29d1c8, - 0x2c394a, - 0x215849, - 0x243083, - 0x342f46, - 0x37f98a, - 0x2f9f87, - 0x23b98a, - 0x31458e, - 0x21f306, - 0x338547, - 0x238886, - 0x2435c6, - 0x3d300b, - 0x39964a, - 0x2cdccd, - 0x2d2107, - 0x266688, - 0x266689, - 0x26668f, - 0x3070cc, - 0x34b789, - 0x27e48e, - 0x2138ca, - 0x216406, - 0x2f4806, - 0x3adc8c, - 0x31fdcc, - 0x320308, - 0x35a487, - 0x235185, - 0x3c8ac4, - 0x28918e, - 0x3a6744, - 0x201247, - 0x39dcca, - 0x3ab1d4, - 0x3d548f, - 0x21eb48, - 0x3d8688, - 0x378c8d, - 0x378c8e, - 0x22cd09, - 0x22e548, - 0x22e54f, - 0x232a0c, - 0x232a0f, - 0x233bc7, - 0x23714a, - 0x3087cb, - 0x239808, - 0x23b107, - 0x25c7cd, - 0x3620c6, - 0x2ee946, - 0x23d449, - 0x22ba08, - 0x2433c8, - 0x2433ce, - 0x2b7687, - 0x3043c5, - 0x245385, - 0x202404, - 0x3de9c6, - 0x3d99c8, - 0x296d83, - 0x2e710e, - 0x25cb88, - 0x2aae8b, - 0x26f887, - 0x228c05, - 0x273506, - 0x2b2b07, - 0x31b348, - 0x36a409, - 0x3cd545, - 0x285c48, - 0x2209c6, - 0x3a618a, - 0x289089, - 0x232dc9, - 0x232dcb, - 0x25d908, - 0x204549, - 0x398c86, - 0x3c5a8a, - 0x2bfe4a, - 0x23734c, - 0x3488c7, - 0x26cf8a, - 0x3b1fcb, - 0x3b1fd9, - 0x324208, - 0x243245, - 0x25c986, - 0x2a0049, - 0x39f606, - 0x219aca, - 0x26e286, - 0x2196c4, - 0x2d604d, - 0x3458c7, - 0x2196c9, - 0x247105, - 0x247ac8, - 0x248009, - 0x24b904, - 0x24bfc7, - 0x24bfc8, - 0x24cc87, - 0x265c08, - 0x250dc7, - 0x2d8b85, - 0x257e8c, - 0x258349, - 0x33144a, - 0x3a8e89, - 0x2f8cc9, - 0x388e0c, - 0x25b4cb, - 0x25c008, - 0x25d0c8, - 0x260cc4, - 0x283b88, - 0x284d09, - 0x2b8647, - 0x212706, - 0x2a43c7, - 0x29fd49, - 0x24768b, - 0x36aa87, - 0x2947c7, - 0x3d0147, - 0x3ba744, - 0x3ba745, - 0x2e3205, - 0x358b4b, - 0x33d684, - 0x323a88, - 0x30060a, - 0x220a87, - 0x3caac7, - 0x28f6d2, - 0x291646, - 0x22f7c6, - 0x28870e, - 0x29ab46, - 0x299288, - 0x29a60f, - 0x3bab88, - 0x28a808, - 0x2dd1ca, - 0x2dd1d1, - 0x2a98ce, - 0x25514a, - 0x25514c, - 0x22e747, - 0x22e750, - 0x3c7108, - 0x2a9ac5, - 0x2b2e0a, - 0x3d1ecc, - 0x29c88d, - 0x3c7c86, - 0x3c7c87, - 0x3c7c8c, - 0x3d2b8c, - 0x21bc8c, - 0x3bd6cb, - 0x38b644, - 0x226204, - 0x2b6f89, - 0x34b147, - 0x37d009, - 0x2bfc89, - 0x2b8247, - 0x2b8406, - 0x2b8409, - 0x2b8803, - 0x2b314a, - 0x2961c7, - 0x3c8e0b, - 0x2cdb4a, - 0x22de04, - 0x32f4c6, - 0x280e09, - 0x35c004, - 0x2df48a, - 0x2e0685, - 0x2c7945, - 0x2c794d, - 0x2c7c8e, - 0x2c7805, - 0x335046, - 0x242dc7, - 0x22b78a, - 0x3a6a46, - 0x37bc84, - 0x3cdb87, - 0x2fab0b, - 0x265907, - 0x262944, - 0x3a39c6, - 0x3a39cd, - 0x2e568c, - 0x21a286, - 0x24c68a, - 0x34ca86, - 0x21e648, - 0x30c487, - 0x2d3b8a, - 0x23c486, - 0x27d903, - 0x2f3886, - 0x29d048, - 0x245aca, - 0x2dcc07, - 0x2dcc08, - 0x249ac4, - 0x28fc47, - 0x2f4348, - 0x291848, - 0x2bbdc8, - 0x2ffc0a, - 0x2ec0c5, - 0x2c1ac7, - 0x254f93, - 0x26b2c6, - 0x24aec8, - 0x221589, - 0x2428c8, - 0x33c58b, - 0x385308, - 0x2c02c4, - 0x21a706, - 0x320c06, - 0x3186c9, - 0x2d39c7, - 0x257f88, - 0x2a51c6, - 0x200bc4, - 0x208405, - 0x3a3188, - 0x344e4a, - 0x2d5cc8, - 0x2dad46, - 0x2a0f0a, - 0x269f88, - 0x2de248, - 0x2df708, - 0x2dff46, - 0x2e1e86, - 0x3a4d0c, - 0x2e2410, - 0x2cc145, - 0x2230c8, - 0x2230d0, - 0x3ba990, - 0x33584e, - 0x3a498e, - 0x3a4994, - 0x3a804f, - 0x3a8406, - 0x3dbe51, - 0x345213, - 0x345688, - 0x2035c5, - 0x2d0008, - 0x3a05c5, - 0x33f34c, - 0x229f09, - 0x3a6589, - 0x356947, - 0x26c649, - 0x39f1c7, - 0x334686, - 0x284207, - 0x204c05, - 0x20a9c3, - 0x210e83, - 0x213404, - 0x36adcd, - 0x3c304f, - 0x200c05, - 0x33f246, - 0x20cb87, - 0x399a87, - 0x208886, - 0x20888b, - 0x2aa785, - 0x259fc6, - 0x30be47, - 0x251ac9, - 0x229b46, - 0x3860c5, - 0x3c910b, - 0x3d6e86, - 0x21d685, - 0x241588, - 0x290b08, - 0x299b8c, - 0x299b90, - 0x2ac2c9, - 0x2c15c7, - 0x2b918b, + 0x395c07, + 0x25fac6, + 0x205289, + 0x33ed86, + 0x281686, + 0x226049, + 0x28a589, + 0x2aa947, + 0x207648, + 0x29b149, + 0x288608, + 0x3a7646, + 0x2e5285, + 0x27dd4a, + 0x281706, + 0x347446, + 0x2deb05, + 0x253708, + 0x2f5707, + 0x23114a, + 0x24df06, + 0x2e2785, + 0x3086c6, + 0x20d647, + 0x3bb8c7, + 0x21a3c5, + 0x26ff45, + 0x26c506, + 0x273b06, + 0x2b0d46, + 0x2ccc44, + 0x289b09, + 0x291a06, + 0x306f0a, + 0x30c148, + 0x31cd48, + 0x37738a, + 0x2ef805, + 0x2a5345, + 0x3cac88, + 0x2c7e88, + 0x2398c7, + 0x36ee86, + 0x339788, + 0x20ee87, + 0x27a408, + 0x2c6806, + 0x28bac8, + 0x29de06, + 0x283847, + 0x23b3c6, + 0x29ffc6, + 0x27438a, + 0x305f86, + 0x2e5289, + 0x2a7746, + 0x22910a, + 0x2463c9, + 0x2fd9c6, + 0x2c9144, + 0x2d274d, + 0x285e07, + 0x3325c6, + 0x2d0185, + 0x2c12c5, + 0x396906, + 0x2a9b89, + 0x2c09c7, + 0x282946, + 0x2ced06, + 0x28f409, + 0x288d84, + 0x23f644, + 0x3b53c8, + 0x237ac6, + 0x2a9708, + 0x322708, + 0x3a9f87, + 0x358b89, + 0x3c9f87, + 0x2bffca, + 0x2fee8f, + 0x2b230a, + 0x3e22c5, + 0x282185, + 0x21c3c5, + 0x229747, + 0x20d203, + 0x207848, + 0x355606, + 0x355709, + 0x2f3dc6, + 0x2db387, + 0x2a1709, + 0x3cd148, + 0x2debc7, + 0x325343, + 0x35f1c5, + 0x20d185, + 0x2cca8b, + 0x248a44, + 0x238344, + 0x27d506, + 0x325507, + 0x396e8a, + 0x24bd87, + 0x298787, + 0x285fc5, + 0x3d5c05, + 0x296ac9, + 0x29ffc6, + 0x24bc0d, + 0x273445, + 0x2c3c03, + 0x2059c3, + 0x3617c5, + 0x33a085, + 0x203f48, + 0x283287, + 0x23f3c6, + 0x2a6ec6, + 0x22bbc5, + 0x234287, + 0x25eb47, + 0x252287, + 0x2ad78a, + 0x3a2308, + 0x2ccc44, + 0x286e47, + 0x285187, + 0x363306, + 0x29d487, + 0x2ebd88, + 0x3d8348, + 0x29c3c6, + 0x26b308, + 0x2c8204, + 0x2f34c6, + 0x250dc6, + 0x3d5486, + 0x208006, + 0x218e84, + 0x288106, + 0x2cf246, + 0x2a0386, + 0x24bc06, + 0x205886, + 0x2a7e46, + 0x23f2c8, + 0x2c2a48, + 0x2e1e88, + 0x367848, + 0x3cac06, + 0x210ec5, + 0x22d7c6, + 0x2b8845, + 0x399107, + 0x295d45, + 0x2119c3, + 0x2e5f45, + 0x235fc4, + 0x2059c5, + 0x202a43, + 0x3c4bc7, + 0x399d08, + 0x31a546, + 0x34490d, + 0x282146, + 0x29f945, + 0x219643, + 0x2cc149, + 0x288f06, + 0x23b1c6, + 0x3b2144, + 0x2b2287, + 0x3611c6, + 0x23f845, + 0x270483, + 0x20b344, + 0x285346, + 0x20e604, + 0x275548, + 0x204609, + 0x32e489, + 0x2a950a, + 0x29738d, + 0x23e587, + 0x3c2cc6, + 0x21dd04, + 0x287dc9, + 0x28e308, + 0x290086, + 0x23abc6, + 0x29d487, + 0x2c98c6, + 0x226c46, + 0x25dfc6, + 0x3da10a, + 0x223708, + 0x2ef705, + 0x356c09, + 0x2d75ca, + 0x30cd48, + 0x2a46c8, + 0x299fc8, + 0x2b45cc, + 0x395905, + 0x2a7148, + 0x2c2d46, + 0x2e1446, + 0x2d5707, + 0x24bc85, + 0x28ad05, + 0x32e349, + 0x214207, + 0x3556c5, + 0x2284c7, + 0x2059c3, + 0x2d7a85, + 0x224148, + 0x2d9047, + 0x2a4589, + 0x2e5145, + 0x311404, + 0x2ab1c8, + 0x2eed47, + 0x2ded88, + 0x2206c8, + 0x2b5285, + 0x21f746, + 0x2a6fc6, + 0x3c2909, + 0x250ec7, + 0x2b8cc6, + 0x355347, + 0x208683, + 0x34da84, + 0x2dc405, + 0x2343c4, + 0x24b684, + 0x38fc47, + 0x26da47, + 0x282b04, + 0x2a43d0, + 0x207bc7, + 0x3d5c05, + 0x3b3c8c, + 0x220484, + 0x31e048, + 0x283749, + 0x3d78c6, + 0x31fc48, + 0x27d804, + 0x27d808, + 0x231746, + 0x274208, + 0x2a38c6, + 0x39b90b, + 0x330685, + 0x2dc288, + 0x213684, + 0x28988a, + 0x2a4589, + 0x23b2c6, + 0x2c2f48, + 0x2592c5, + 0x2cb744, + 0x31df46, + 0x252148, + 0x289188, + 0x333e86, + 0x389f44, + 0x27dcc6, + 0x3ca007, + 0x281387, + 0x29d48f, + 0x346f07, + 0x2fda87, + 0x388ac5, + 0x377ac5, + 0x2aa609, + 0x2f7786, + 0x38fe85, + 0x28a887, + 0x2d5988, + 0x302545, + 0x23b3c6, + 0x30bf88, + 0x2f424a, + 0x37e648, + 0x293287, + 0x2ff2c6, + 0x356bc6, + 0x2003c3, + 0x20c483, + 0x2d7789, + 0x29afc9, + 0x2dca46, + 0x2e5145, + 0x2b4448, + 0x2c2f48, + 0x2a3508, + 0x25e04b, + 0x344b47, + 0x3211c9, + 0x29d708, + 0x3505c4, + 0x3d50c8, + 0x295909, + 0x2b8fc5, + 0x229647, + 0x34db05, + 0x289088, + 0x2983cb, + 0x29e790, + 0x2b3e05, + 0x2135cc, + 0x23f585, + 0x25e883, + 0x2b6486, + 0x2ce3c4, + 0x23b686, + 0x2a5407, + 0x203d44, + 0x243208, + 0x20770d, + 0x3224c5, + 0x23e5c4, + 0x2b5684, + 0x2b5689, + 0x2adfc8, + 0x330b47, + 0x2317c8, + 0x289bc8, + 0x282c45, + 0x27ee47, + 0x282bc7, + 0x3559c7, + 0x26ff49, + 0x25e649, + 0x210706, + 0x302d46, + 0x28a946, + 0x326e85, + 0x3c5d04, + 0x3cc9c6, + 0x3d4e86, + 0x282c88, + 0x20d30b, + 0x237647, + 0x21dd04, + 0x361106, + 0x2ec0c7, + 0x2a7a45, + 0x324a85, + 0x267c04, + 0x25e5c6, + 0x3cca48, + 0x287dc9, + 0x261846, + 0x28e108, + 0x23f906, + 0x365f48, + 0x37904c, + 0x282b06, + 0x29f60d, + 0x29fa8b, + 0x2a6105, + 0x25ec87, + 0x2c8286, + 0x3bb788, + 0x210789, + 0x38a7c8, + 0x3d5c05, + 0x20fac7, + 0x288708, + 0x3c7c49, + 0x360e46, + 0x26174a, + 0x3bb508, + 0x38a60b, + 0x22398c, + 0x27d908, + 0x284906, + 0x27e848, + 0x2f3ec7, + 0x347049, + 0x35150d, + 0x29fec6, + 0x30ef48, + 0x2c2909, + 0x2ccd48, + 0x28bbc8, + 0x2cfb4c, + 0x2d0807, + 0x2d31c7, + 0x26fd85, + 0x2c54c7, + 0x2d5848, + 0x31dfc6, + 0x2704cc, + 0x301fc8, + 0x2dd8c8, + 0x23ae06, + 0x2b1f07, + 0x210904, + 0x367848, + 0x28d20c, + 0x29144c, + 0x3e2345, + 0x3dcd47, + 0x389ec6, + 0x2b1e86, + 0x2bcb08, + 0x21b284, + 0x2671cb, + 0x28d94b, + 0x2ff2c6, + 0x207587, + 0x3572c5, + 0x2781c5, + 0x267306, + 0x259285, + 0x248a05, + 0x2d65c7, + 0x2b2789, + 0x273cc4, + 0x23d405, + 0x2f8ac5, + 0x358908, + 0x2bf505, + 0x2d1d09, + 0x39e2c7, + 0x39e2cb, + 0x2fd706, + 0x23f009, + 0x389d08, + 0x3ae7c5, + 0x355ac8, + 0x25e688, + 0x286407, + 0x2b5a87, + 0x38fcc9, + 0x274147, + 0x295c49, + 0x2d11cc, + 0x2dca48, + 0x2c0dc9, + 0x2c4d07, + 0x289c89, + 0x367207, + 0x223a88, + 0x358d45, + 0x2f3446, + 0x2d01c8, + 0x21c488, + 0x2d7489, + 0x248a47, + 0x278bc5, + 0x3cde49, + 0x2fde86, + 0x297b84, + 0x33ff06, + 0x26ad88, + 0x2e6587, + 0x20d508, + 0x26b3c9, + 0x3a1a87, + 0x2a3646, + 0x25ed44, + 0x2e5fc9, + 0x27ecc8, + 0x23acc7, + 0x2702c6, + 0x20d246, + 0x3473c4, + 0x26b5c6, + 0x205943, + 0x330209, + 0x330646, + 0x2a4905, + 0x2a6ec6, + 0x2db905, + 0x288b88, + 0x33f3c7, + 0x23bb46, + 0x25de86, + 0x31cd48, + 0x2aa787, + 0x29ff05, + 0x2a41c8, + 0x3b1b88, + 0x3bb508, + 0x23f445, + 0x2f34c6, + 0x32e249, + 0x3c2784, + 0x2db78b, + 0x22694b, + 0x2ef609, + 0x2059c3, + 0x257b05, + 0x2ef4c6, + 0x241f88, + 0x30a604, + 0x31a546, + 0x2ad8c9, + 0x2ce1c5, + 0x2d6506, + 0x2eed46, + 0x203f44, + 0x29a14a, + 0x2a4848, + 0x21c486, + 0x375c45, + 0x357147, + 0x33a2c7, + 0x21f744, + 0x226b87, + 0x2bffc4, + 0x369146, + 0x207883, + 0x26ff45, + 0x2ba485, + 0x25b688, + 0x287005, + 0x282849, + 0x2abc07, + 0x36768b, + 0x2abc0c, + 0x2ac20a, + 0x3513c7, + 0x203843, + 0x280d88, + 0x23f605, + 0x3025c5, + 0x35f284, + 0x223986, + 0x283746, + 0x26b607, + 0x3a9d8b, + 0x218e84, + 0x309d04, + 0x2d6784, + 0x2db206, + 0x203d44, + 0x21e488, + 0x35f085, + 0x21a245, + 0x2a3447, + 0x25ed89, + 0x33a085, + 0x39690a, + 0x2d5ac9, + 0x2aceca, + 0x3da249, + 0x354004, + 0x2cedc5, + 0x2c99c8, + 0x3aaacb, + 0x313005, + 0x2ecd46, + 0x241c04, + 0x282d86, + 0x3a1909, + 0x2ec1c7, + 0x33ef48, + 0x297706, + 0x3c9f87, + 0x289188, + 0x37c006, + 0x3d5e84, + 0x386b47, + 0x388705, + 0x398187, + 0x29f484, 0x2c8206, - 0x305b4a, - 0x36ff8b, - 0x31b58a, - 0x398806, - 0x2f6fc5, - 0x32aa86, - 0x279f48, - 0x356a0a, - 0x37891c, - 0x2fdc8c, - 0x2fdf88, - 0x2431c5, - 0x382747, - 0x24a006, - 0x24aac5, - 0x2177c6, - 0x208a48, - 0x2c6747, - 0x2c3588, - 0x26b38a, - 0x3b954c, - 0x297009, - 0x3b97c7, - 0x285244, - 0x245446, - 0x28a38a, - 0x2bfd85, - 0x22348c, - 0x223b48, - 0x26a208, - 0x2aebcc, - 0x38878c, - 0x22d949, - 0x22db87, - 0x25494c, - 0x3082c4, - 0x3713ca, - 0x30de8c, - 0x24fdcb, - 0x25044b, - 0x252b06, - 0x256447, - 0x22e987, - 0x22e98f, - 0x30f351, - 0x2e8d92, - 0x258c0d, - 0x258c0e, - 0x258f4e, - 0x3a8208, - 0x3a8212, - 0x25be08, - 0x221bc7, - 0x24ec0a, - 0x2ac988, - 0x29ab05, - 0x2bb28a, - 0x21d187, - 0x2ef184, - 0x210883, - 0x236085, - 0x2dd447, - 0x30d3c7, - 0x29ca8e, - 0x352e8d, - 0x354009, - 0x302905, - 0x361043, - 0x34a886, - 0x25a5c5, - 0x2ab0c8, - 0x224249, - 0x25c9c5, - 0x25c9cf, - 0x2e0b07, - 0x218a85, - 0x27024a, - 0x3d0b06, - 0x312b09, - 0x381b4c, - 0x3ce889, - 0x2062c6, - 0x30040c, - 0x32dd86, - 0x30cfc8, - 0x3b1ec6, - 0x365486, - 0x2bc1c4, - 0x31d203, - 0x21124a, - 0x227e11, - 0x34b94a, - 0x23ea05, - 0x25b907, - 0x2559c7, - 0x2e6f04, - 0x2f444b, - 0x33aa48, - 0x2c55c6, - 0x361785, - 0x261f44, - 0x3828c9, - 0x2008c4, - 0x20e087, - 0x37a385, - 0x37a387, - 0x288945, - 0x3801c3, - 0x221a88, - 0x2d020a, - 0x23db43, - 0x399c8a, - 0x2a74c6, - 0x25c74f, - 0x2b7609, - 0x2e7090, - 0x305748, - 0x2db3c9, - 0x29df47, - 0x3a394f, - 0x3905c4, - 0x2e3584, - 0x203946, - 0x2344c6, - 0x2ef40a, - 0x254686, - 0x2b5e07, - 0x315048, - 0x315247, - 0x3166c7, - 0x31784a, - 0x316fcb, - 0x33bf85, - 0x2e89c8, - 0x201343, - 0x3bb3cc, - 0x3965cf, - 0x234f8d, - 0x258787, - 0x354149, - 0x357087, - 0x2401c8, - 0x3ab3cc, - 0x2c01c8, - 0x23e708, - 0x32c9ce, - 0x341b94, - 0x3420a4, - 0x36080a, - 0x37b90b, - 0x39f284, - 0x39f289, - 0x331e88, - 0x245d85, - 0x29688a, - 0x291087, - 0x2135c4, - 0x202703, - 0x214a83, - 0x235b44, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21bc83, - 0x23c803, - 0x2e2406, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x2141c3, + 0x30ca48, + 0x29fc48, + 0x33dec7, + 0x3801c8, + 0x29dec5, + 0x205804, + 0x377288, + 0x3802c4, + 0x21c345, + 0x30cc44, + 0x20ef87, + 0x291ac7, + 0x289dc8, + 0x2def06, + 0x286f85, + 0x282648, + 0x37e848, + 0x2a9449, + 0x226c46, + 0x2311c8, + 0x28970a, + 0x2a7ac8, + 0x308c85, + 0x22d9c6, + 0x2a9a48, + 0x20fb8a, + 0x265587, + 0x28e745, + 0x297d88, + 0x2b3a44, + 0x253786, + 0x2d3548, + 0x205886, + 0x33aa08, + 0x2d9e07, + 0x203686, + 0x2c9144, + 0x26a4c7, + 0x2c3304, + 0x3a18c7, + 0x23b00d, + 0x239945, + 0x2d8e4b, + 0x2916c6, + 0x252f48, + 0x2431c4, + 0x3c0706, + 0x285346, + 0x27eb87, + 0x29f2cd, + 0x305587, + 0x2c3b48, + 0x28bd45, + 0x296c88, + 0x2d6dc6, + 0x29df48, + 0x38ecc6, + 0x3b3a07, + 0x28a149, + 0x35fe07, + 0x290348, + 0x34c1c5, + 0x22bc48, + 0x2b1dc5, + 0x2d6d05, + 0x37d145, + 0x24dc03, + 0x208084, + 0x297f85, + 0x3a9a89, + 0x36ec46, + 0x2ebe88, + 0x2eefc5, + 0x2c5387, + 0x2e0fca, + 0x2d6449, + 0x2d540a, + 0x2e1f08, + 0x22830c, + 0x28a90d, + 0x314e43, + 0x33a908, + 0x20b305, + 0x2f4006, + 0x3ccfc6, + 0x2d2405, + 0x355449, + 0x348ec5, + 0x282648, + 0x258946, + 0x370286, + 0x2ab089, + 0x3b0b47, + 0x298686, + 0x2e0f48, + 0x3d5388, + 0x2efec7, + 0x2cf3ce, + 0x2d7005, + 0x3c7b45, + 0x205788, + 0x36f947, + 0x20d282, + 0x2cf804, + 0x23b58a, + 0x23ad88, + 0x25e7c6, + 0x2a1848, + 0x2a6fc6, + 0x25f708, + 0x2b8cc8, + 0x30b3c4, + 0x2c5745, + 0x602284, + 0x602284, + 0x602284, + 0x207783, + 0x20d0c6, + 0x282b06, + 0x2a5dcc, + 0x202503, + 0x2d75c6, + 0x207844, + 0x288e88, + 0x2ad705, + 0x23b686, + 0x2cc888, + 0x2e3246, + 0x23bac6, + 0x203d48, + 0x2dc487, + 0x273f09, + 0x3df7ca, + 0x26dbc4, + 0x295d45, + 0x2b7645, + 0x2d9a86, + 0x23e5c6, + 0x2a5b46, + 0x3d3f06, + 0x274044, + 0x27404b, + 0x266cc4, + 0x23f185, + 0x2b7cc5, + 0x3aa046, + 0x209648, + 0x28a7c7, + 0x3305c4, + 0x213c03, + 0x2b3545, + 0x33fdc7, + 0x28a6cb, + 0x25b587, + 0x2cc788, + 0x2c5887, + 0x2715c6, + 0x25c348, + 0x2cad4b, + 0x34e2c6, + 0x214a09, + 0x2caec5, + 0x325343, + 0x2d6506, + 0x2d9d08, + 0x215203, + 0x2a11c3, + 0x289186, + 0x2a6fc6, + 0x379eca, + 0x284945, + 0x28518b, + 0x2a6e0b, + 0x2163c3, + 0x206743, + 0x2bff44, + 0x2e0e07, + 0x27d904, + 0x25ef44, + 0x2c2bc4, + 0x2a7dc8, + 0x375b88, + 0x20c409, + 0x2d98c8, + 0x37d3c7, + 0x24bc06, + 0x2ebacf, + 0x2d7146, + 0x2e15c4, + 0x3759ca, + 0x33fcc7, + 0x2c3406, + 0x297bc9, + 0x20c385, + 0x25b7c5, + 0x20c4c6, + 0x22bd83, + 0x2b3a89, + 0x223886, + 0x26b189, + 0x396e86, + 0x26ff45, + 0x361bc5, + 0x206643, + 0x3131c8, + 0x330d07, + 0x355604, + 0x288d08, + 0x2e11c4, + 0x31c046, + 0x2b6486, + 0x23d846, + 0x2dc149, + 0x302545, + 0x29ffc6, + 0x277389, + 0x2d6146, + 0x2a7e46, + 0x3a8b46, + 0x22e405, + 0x30cc46, + 0x3b3a04, + 0x358d45, + 0x21c484, + 0x2c45c6, + 0x273404, + 0x207a43, + 0x28e3c5, + 0x234f88, + 0x366a47, + 0x30a689, + 0x28e648, + 0x2a0951, + 0x2eedca, + 0x2ff207, + 0x3d8686, + 0x207844, + 0x2d02c8, + 0x2e2e88, + 0x2a0b0a, + 0x2d1acd, + 0x2a9606, + 0x203e46, + 0x26a586, + 0x21a247, + 0x2c3c05, + 0x35c6c7, + 0x207705, + 0x39e404, + 0x206686, + 0x30ec47, + 0x2b378d, + 0x2a9987, + 0x344fc8, + 0x282949, + 0x22d8c6, + 0x360dc5, + 0x2393c4, + 0x26ae86, + 0x21f646, + 0x23af06, + 0x2a20c8, + 0x22cdc3, + 0x23e443, + 0x34bcc5, + 0x2d2a86, + 0x2b8c85, + 0x297908, + 0x2a55ca, + 0x33f504, + 0x288e88, + 0x299fc8, + 0x25ef47, + 0x28ed49, + 0x2cc488, + 0x287e47, + 0x2c2e46, + 0x20588a, + 0x26af08, + 0x32df09, + 0x2ae088, + 0x224a09, + 0x3d8547, + 0x35ce45, + 0x2a73c6, + 0x31de48, + 0x2530c8, + 0x2bbfc8, + 0x21e608, + 0x23f185, + 0x200d04, + 0x233908, + 0x241984, + 0x3da044, + 0x26ff45, + 0x2997c7, + 0x25eb49, + 0x27e987, + 0x2260c5, + 0x27d706, + 0x375446, + 0x209744, + 0x2ab3c6, + 0x2855c4, + 0x293ec6, + 0x25e906, + 0x215046, + 0x3d5c05, + 0x2977c7, + 0x203843, + 0x22b509, + 0x31cb48, + 0x287cc4, + 0x287ccd, + 0x29fd48, + 0x2fcd48, + 0x32de86, + 0x28a249, + 0x2d6449, + 0x3a1605, + 0x2a56ca, + 0x2a844a, + 0x2b5c8c, + 0x2b5e06, + 0x280986, + 0x2d79c6, + 0x393189, + 0x2f4246, + 0x223b06, + 0x348f86, + 0x367848, + 0x37e646, + 0x2e094b, + 0x299945, + 0x21a245, + 0x281485, + 0x3b5146, + 0x205843, + 0x23d7c6, + 0x2a9907, + 0x2d0185, + 0x27fbc5, + 0x2c12c5, + 0x301c46, + 0x336144, + 0x336146, + 0x2a9e49, + 0x3b4fcc, + 0x39e148, + 0x2520c4, + 0x30c946, + 0x2917c6, + 0x2d9d08, + 0x2c2f48, + 0x3b4ec9, + 0x357147, + 0x237809, + 0x278286, + 0x22c544, + 0x20af04, + 0x286dc4, + 0x289188, + 0x25e98a, + 0x33a006, + 0x36eb07, + 0x398407, + 0x23f105, + 0x2b7604, + 0x2958c6, + 0x2c3c46, + 0x21b2c3, + 0x31c987, + 0x2205c8, + 0x3a174a, + 0x22e4c8, + 0x34df48, + 0x273445, + 0x2a6205, + 0x237745, + 0x23f4c6, + 0x242546, + 0x25d405, + 0x330449, + 0x2b740c, + 0x307d87, + 0x2a0b88, + 0x251045, + 0x602284, + 0x267c84, + 0x2d9184, + 0x212d06, + 0x2a8d0e, + 0x25b847, + 0x21a445, + 0x3c270c, + 0x3d2347, + 0x30ebc7, + 0x30f7c9, + 0x221a89, + 0x28e745, + 0x31cb48, + 0x32e249, + 0x3bb3c5, + 0x2d00c8, + 0x2c1006, + 0x377506, + 0x2463c4, + 0x294908, + 0x204883, + 0x20ccc4, + 0x2b35c5, + 0x39db87, + 0x2e5e45, + 0x2895c9, + 0x29664d, + 0x2af506, + 0x213c44, + 0x36ee08, + 0x2b25ca, + 0x2144c7, + 0x34bb05, + 0x20cd03, + 0x2a6fce, + 0x3132cc, + 0x30ce47, + 0x2a8ec7, + 0x4539cd47, + 0xb20c6, + 0x27c44, + 0x215d03, + 0x2f4285, + 0x2d9185, + 0x2a1c08, + 0x29edc9, + 0x251fc6, + 0x27d904, + 0x2ff146, + 0x2398cb, + 0x2eab4c, + 0x24dcc7, + 0x2e0c05, + 0x3b1a88, + 0x2efc85, + 0x3759c7, + 0x307b87, + 0x2475c5, + 0x205843, + 0x21fac4, + 0x2e6445, + 0x273bc5, + 0x273bc6, + 0x2a2608, + 0x30ec47, + 0x3cd2c6, + 0x3472c6, + 0x37d086, + 0x30f0c9, + 0x27ef47, + 0x251e46, + 0x2eacc6, + 0x3cae06, + 0x2b4385, + 0x20e046, + 0x3b3245, + 0x2bf588, + 0x29940b, + 0x295606, + 0x398444, + 0x305bc9, + 0x2abc04, + 0x2c0f88, + 0x3116c7, + 0x28bac4, + 0x2cb948, + 0x2d1604, + 0x2b43c4, + 0x27a345, + 0x322506, + 0x2a7d07, + 0x249b03, + 0x2a3705, + 0x2ff4c4, + 0x3c7b86, + 0x3a1688, + 0x37e545, + 0x2990c9, + 0x3513c5, + 0x323488, + 0x2bc807, + 0x330748, + 0x2cb587, + 0x2fdb49, + 0x287f86, + 0x372946, + 0x29b284, + 0x309c45, + 0x31520c, + 0x281487, + 0x282047, + 0x23e208, + 0x2af506, + 0x2a9844, + 0x34a144, + 0x38fb49, + 0x2d7ac6, + 0x296b47, + 0x27e7c4, + 0x2ab4c6, + 0x3c1685, + 0x2dea47, + 0x2e08c6, + 0x261609, + 0x39b307, + 0x29d487, + 0x2aaf06, + 0x270205, + 0x286b08, + 0x223708, + 0x371f86, + 0x37e585, + 0x2e93c6, + 0x203803, + 0x2a1a89, + 0x2a58ce, + 0x2cb2c8, + 0x2e12c8, + 0x371d8b, + 0x299306, + 0x398304, + 0x23bac4, + 0x2a59ca, + 0x2134c7, + 0x251f05, + 0x214a09, + 0x2cf305, + 0x3da087, + 0x232144, + 0x204787, + 0x322608, + 0x2d6c46, + 0x2c8389, + 0x2cc58a, + 0x213446, + 0x29f886, + 0x2b7c45, + 0x39f685, + 0x37d947, + 0x246d48, + 0x3c15c8, + 0x30b3c6, + 0x361c45, + 0x23e34e, + 0x2ccc44, + 0x2a1b85, + 0x27d089, + 0x2f7588, + 0x2931c6, + 0x2a3ccc, + 0x2a51d0, + 0x2a894f, + 0x2aa508, + 0x3513c7, + 0x3d5c05, + 0x297f85, + 0x2a7b89, + 0x297f89, + 0x27ddc6, + 0x313087, + 0x309b45, + 0x337c49, + 0x363386, + 0x2f408d, + 0x286c89, + 0x25ef44, + 0x2cb048, + 0x2339c9, + 0x33a1c6, + 0x280f85, + 0x372946, + 0x33ee09, + 0x27e648, + 0x210ec5, + 0x289804, + 0x2a3e8b, + 0x33a085, + 0x242006, + 0x28ac46, + 0x22a986, + 0x25e24b, + 0x2991c9, + 0x347205, + 0x399007, + 0x2eed46, + 0x233086, + 0x289488, + 0x30ed89, + 0x344d8c, + 0x33fbc8, + 0x31e806, + 0x333e83, + 0x360186, + 0x2b58c5, + 0x285cc8, + 0x3e21c6, + 0x2dec88, + 0x24be05, + 0x293f85, + 0x2c0b88, + 0x3d5247, + 0x3ccf07, + 0x26b607, + 0x31fc48, + 0x2d9b88, + 0x2e2d86, + 0x2c4407, + 0x34d947, + 0x2b578a, + 0x238643, + 0x3b5146, + 0x23e2c5, + 0x215cc4, + 0x282949, + 0x2fdac4, + 0x2cbd84, + 0x2a3944, + 0x2a8ecb, + 0x330c47, + 0x23e585, + 0x29dbc8, + 0x27d706, + 0x27d708, + 0x284886, + 0x294845, + 0x294b05, + 0x296086, + 0x2971c8, + 0x297b08, + 0x282b06, + 0x29da0f, + 0x2a1550, + 0x205385, + 0x203843, + 0x22c605, + 0x321108, + 0x297e89, + 0x3bb508, + 0x312e88, + 0x385808, + 0x330d07, + 0x27d3c9, + 0x2dee88, + 0x2a4f84, + 0x2a37c8, + 0x3589c9, + 0x2c4a07, + 0x395d44, + 0x27ea48, + 0x29758a, + 0x2ff746, + 0x2a9606, + 0x226b09, + 0x2a5407, + 0x2dbfc8, + 0x2321c8, + 0x347988, + 0x259805, + 0x21ce85, + 0x21a245, + 0x2d9145, + 0x2c2747, + 0x205845, + 0x2d0185, + 0x203546, + 0x3bb447, + 0x3aaa07, + 0x297886, + 0x2e2445, + 0x242006, + 0x280e45, + 0x2c7d08, + 0x309ac4, + 0x2d61c6, + 0x353544, + 0x2cb748, + 0x32288a, + 0x28328c, + 0x2a6505, + 0x21a306, + 0x344f46, + 0x348d86, + 0x31e884, + 0x3cd585, + 0x284147, + 0x2a5489, + 0x2db647, + 0x602284, + 0x602284, + 0x330ac5, + 0x2dfe04, + 0x2a328a, + 0x27d586, + 0x2c0b04, + 0x3dccc5, + 0x2c1d85, + 0x2c3b44, + 0x28a887, + 0x3cdfc7, + 0x2db208, + 0x2e94c8, + 0x210ec9, + 0x388d08, + 0x29048b, + 0x2a7cc4, + 0x233185, + 0x38ff05, + 0x26b589, + 0x30ed89, + 0x305ac8, + 0x368f48, + 0x2e6bc4, + 0x291805, + 0x204083, + 0x2d9a45, + 0x2a0046, + 0x29ec0c, + 0x21f546, + 0x280e86, + 0x293445, + 0x301cc8, + 0x2eadc6, + 0x3d8806, + 0x2a9606, + 0x22e24c, + 0x38ffc4, + 0x37d1ca, + 0x293388, + 0x29ea47, + 0x2ff3c6, + 0x252087, + 0x2fed45, + 0x2702c6, + 0x363d86, + 0x377987, + 0x2cc284, + 0x20f085, + 0x27d084, + 0x39e487, + 0x27d2c8, + 0x28080a, + 0x288587, + 0x2ac487, + 0x351347, + 0x2efdc9, + 0x29ec0a, + 0x22c503, + 0x366a05, + 0x215083, + 0x2c2c09, + 0x2d9f48, + 0x388ac7, + 0x3bb609, + 0x223806, + 0x358e08, + 0x3c4b45, + 0x37e94a, + 0x2079c9, + 0x29c289, + 0x2d5707, + 0x2e2f89, + 0x214f48, + 0x25f906, + 0x21a4c8, + 0x27ff07, + 0x274147, + 0x2d5ac7, + 0x2dd548, + 0x30c7c6, + 0x297345, + 0x284147, + 0x29f388, + 0x37d004, + 0x306dc4, + 0x298587, + 0x2b9047, + 0x32e0ca, + 0x25f886, + 0x3c82ca, + 0x2cf747, + 0x2cca07, + 0x20f144, + 0x295d04, + 0x2de946, + 0x361444, + 0x36144c, + 0x311605, + 0x21c2c9, + 0x2f0e84, + 0x2c3c05, + 0x2b2548, + 0x297bc5, + 0x396906, + 0x2980c4, + 0x2ab98a, + 0x384806, + 0x24774a, + 0x3da407, + 0x20d645, + 0x22bd85, + 0x23f14a, + 0x247685, + 0x2a7b46, + 0x241984, + 0x2c00c6, + 0x37da05, + 0x3e2286, + 0x33decc, + 0x2e3cca, + 0x2a8544, + 0x24bc06, + 0x2a5407, + 0x2e0844, + 0x367848, + 0x2ecc46, + 0x398289, + 0x2cd009, + 0x2dcb49, + 0x2db946, + 0x280006, + 0x21a607, + 0x330388, + 0x27fe09, + 0x330c47, + 0x29dd46, + 0x3ca007, + 0x26a445, + 0x2ccc44, + 0x21a1c7, + 0x34db05, + 0x28f645, + 0x200cc7, + 0x247488, + 0x3b1a06, + 0x2a01cd, + 0x2a1e0f, + 0x2a6e0d, + 0x226104, + 0x235086, + 0x2e4088, + 0x348f45, + 0x2b5948, + 0x2862ca, + 0x25ef44, + 0x239b06, + 0x211787, + 0x218e87, + 0x2dc549, + 0x21a485, + 0x2c3b44, + 0x2c568a, + 0x2cc049, + 0x2e3087, + 0x30d406, + 0x33a1c6, + 0x291746, + 0x386c06, + 0x2e398f, + 0x2e3f49, + 0x37e646, + 0x38f786, + 0x32fa49, + 0x2c4507, + 0x220d03, + 0x22e3c6, + 0x20c483, + 0x2d22c8, + 0x2b0e07, + 0x2aa709, + 0x2b6308, + 0x3cd048, + 0x367346, + 0x21f489, + 0x307cc5, + 0x2a3504, + 0x35cf07, + 0x393205, + 0x226104, + 0x23e648, + 0x213784, + 0x2c4247, + 0x399c86, + 0x26c5c5, + 0x2ae088, + 0x33a08b, + 0x31d047, + 0x23f3c6, + 0x2d71c4, + 0x3aef86, + 0x26ff45, + 0x34db05, + 0x286889, + 0x28a489, + 0x274184, + 0x2741c5, + 0x24bc45, + 0x37e7c6, + 0x31cc48, + 0x2ce7c6, + 0x22040b, + 0x3d774a, + 0x2cb685, + 0x294b86, + 0x25b285, + 0x3c2205, + 0x256147, + 0x3b53c8, + 0x237804, + 0x385406, + 0x297b86, + 0x215107, + 0x325304, + 0x285346, + 0x229845, + 0x229849, + 0x280204, + 0x2b7789, + 0x282b06, + 0x2d08c8, + 0x24bc45, + 0x398505, + 0x3e2286, + 0x344c89, + 0x221a89, + 0x280f06, + 0x2f7688, + 0x296788, + 0x25b244, + 0x2c6604, + 0x2c6608, + 0x3326c8, + 0x237909, + 0x29ffc6, + 0x2a9606, + 0x33964d, + 0x31a546, + 0x378f09, + 0x201f45, + 0x20c4c6, + 0x347b08, + 0x336085, + 0x34d984, + 0x26ff45, + 0x289fc8, + 0x2a3049, + 0x27d144, + 0x2c8206, + 0x29c4ca, + 0x30cd48, + 0x32e249, + 0x270bca, + 0x3bb586, + 0x2a1fc8, + 0x375785, + 0x293608, + 0x2fedc5, + 0x2236c9, + 0x33bc49, + 0x21fb82, + 0x2caec5, + 0x277f06, + 0x282a47, + 0x215cc5, + 0x33eb86, + 0x319508, + 0x2af506, + 0x2c9889, + 0x282146, + 0x289308, + 0x24ef85, + 0x394886, + 0x3b3b08, + 0x289188, + 0x3d8448, + 0x31b948, + 0x20e044, + 0x21f783, + 0x2c9ac4, + 0x288786, + 0x26a484, + 0x2e1207, + 0x3d8709, + 0x2d6785, + 0x2321c6, + 0x22e3c6, + 0x2a244b, + 0x2c3346, + 0x273686, + 0x2d62c8, + 0x266cc6, + 0x20d443, + 0x20bb03, + 0x2ccc44, + 0x2310c5, + 0x23f747, + 0x27d2c8, + 0x27d2cf, + 0x28404b, + 0x31ca48, + 0x2c8286, + 0x31cd4e, + 0x23f583, + 0x23f6c4, + 0x2c32c5, + 0x2c39c6, + 0x2959cb, + 0x299886, + 0x30c009, + 0x26c5c5, + 0x249a48, + 0x209bc8, + 0x22194c, + 0x2a8f06, + 0x2d9a86, + 0x2e5145, + 0x290108, + 0x283285, + 0x3505c8, + 0x2a404a, + 0x2a7249, + 0x602284, 0x2000c2, - 0x202703, - 0x201242, - 0x214a83, - 0x235b44, - 0x232dc3, - 0x308003, - 0x21bc83, - 0x2e2406, - 0x21a3c3, - 0x242543, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x228503, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x2000c2, - 0x27ee03, - 0x201242, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x2086c2, - 0x215702, - 0x201242, - 0x214a83, - 0x208c02, - 0x2005c2, - 0x221dc4, - 0x306c44, - 0x223f82, - 0x219a04, + 0x4b212402, + 0x200382, + 0x20e704, + 0x20b982, + 0x217544, + 0x203182, + 0x5803, 0x2003c2, - 0x242543, - 0x2141c3, - 0x252b06, - 0x20c782, - 0x201b82, - 0x2221c2, - 0x57a07403, - 0x57e2e743, - 0x56246, - 0x56246, - 0x2d3684, - 0x203dc3, - 0x160d, - 0x1d984a, - 0x16300c, - 0x1d76cc, - 0xd4ecd, - 0x139b05, - 0x86209, - 0x8d2cc, - 0x29907, - 0xdb86, - 0x13dc8, - 0x1bf87, - 0x201c8, - 0x1ac0ca, - 0x10d707, - 0x58a8d505, - 0xe4f09, - 0x58c3480b, - 0x125c08, - 0x1558b, - 0x12c5c8, - 0x1c48c9, - 0x4060a, - 0x1b1b8e, - 0x1d158d, - 0x2cd0d, - 0x14426cb, - 0xe554a, - 0x8d04, - 0x5a106, - 0x19b808, - 0x79108, - 0x25687, - 0x1d35c5, - 0xc607, - 0x33249, - 0x15c087, - 0x106c8, - 0x26a89, - 0x4ce04, - 0x4e945, - 0x98e8e, - 0x12c207, - 0x59225a86, - 0x78d8d, - 0xd1288, - 0x59694f86, - 0x5a094f88, - 0x56f88, - 0x136b90, - 0x53f8c, - 0x61b47, - 0x62347, - 0x6a947, - 0x72047, - 0x6882, - 0x120687, - 0x19980c, - 0x13c945, - 0x107c07, - 0xac186, - 0xacdc9, - 0xaff88, - 0x6502, + 0x208502, + 0xae888, + 0x4cc4, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x7542, + 0x4b202, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x1fcc2, + 0x4642, + 0x72c2, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x217fc3, + 0x23e083, + 0x219ac3, + 0x24cd44, + 0x22ea43, + 0x236704, + 0x233fc3, + 0x2e5904, + 0x266a83, + 0x215f87, + 0x23cb03, + 0x205803, + 0x321388, + 0x23e083, + 0x293b0b, + 0x2ffec3, + 0x243bc6, + 0x22dc42, + 0x2fa00b, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23e083, + 0x221d43, + 0x210cc3, + 0x2000c2, + 0xae888, + 0x334f05, + 0x34db88, + 0x2f4fc8, + 0x212402, + 0x36a4c5, + 0x3ca147, + 0x2031c2, + 0x243407, + 0x200382, + 0x253d47, + 0x23a489, + 0x272888, + 0x347809, + 0x210382, + 0x3d5f47, + 0x32ad04, + 0x3ca207, + 0x3d7647, + 0x25a642, + 0x23cb03, + 0x20a942, + 0x203182, + 0x2003c2, + 0x205b42, + 0x200902, + 0x208502, + 0x2e1a45, + 0x227885, + 0x12402, + 0x33fc3, + 0x22ea43, + 0x233fc3, + 0x27e883, + 0x266a83, + 0x204903, + 0x217fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0xfe83, + 0x101, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x2191c3, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x217c83, + 0x4e4b1706, + 0x22383, + 0xd7405, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x5242, + 0xae888, + 0x12f603, + 0x5803, + 0x1c0443, + 0x46d04, + 0x147b604, + 0xf0085, + 0x2000c2, + 0x3993c4, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x247e03, + 0x22f845, + 0x2191c3, + 0x21e1c3, + 0x217fc3, + 0x24dfc3, + 0x23e083, + 0x208503, + 0x24cdc3, + 0x20aa43, 0x5c2, - 0x18d986, - 0x1b9ecb, - 0x1ba1c6, - 0x174d04, - 0x978c7, - 0x41a89, - 0xf0c09, - 0x1b1148, - 0x49582, - 0x193a49, - 0xd788, - 0xef24a, - 0x15adc9, - 0x1b4186, - 0xd8949, - 0xe54c7, - 0xe5c09, - 0xe7ac8, - 0xea3c7, - 0xec049, - 0xf0005, - 0xf1210, - 0x1b6786, - 0x97805, - 0x91487, - 0xec74d, - 0x41485, - 0xf8ac6, - 0xf92c7, - 0xfe7d8, - 0xd1608, - 0x13db8a, - 0xca42, - 0x5020a, - 0x60e4d, - 0x45c2, - 0xce946, - 0x11ec6, - 0xa1788, - 0xafd0a, - 0x472c8, - 0x6de89, - 0x115488, - 0x6eace, - 0x6e0c8, - 0x14a887, - 0x5a694ec4, - 0xae8cd, - 0x10a085, - 0x69148, - 0x34088, - 0x111b86, - 0xc2c2, - 0xc53c4, - 0xe2c06, - 0x365c6, - 0x5a8ef74b, - 0x1442, + 0x30242, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x2000c2, + 0x24ac43, + 0x212402, + 0xf982, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x217fc3, + 0x23e083, + 0x208502, + 0xae888, + 0x266a83, + 0x1c0443, + 0xae888, + 0x1c0443, + 0x276243, + 0x22ea43, + 0x2319c4, + 0x233fc3, + 0x266a83, + 0x209582, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x209582, + 0x215f83, + 0x217fc3, + 0x23e083, + 0x2f8e43, + 0x208503, + 0x2000c2, + 0x212402, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x243bc5, + 0x1375c6, + 0x24cd44, + 0x22dc42, + 0x882, + 0xae888, + 0xf982, + 0x4b202, + 0x2a82, + 0x2000c2, + 0x146bc5, + 0x1ae08, + 0x125203, + 0x212402, + 0x3c904, + 0x52d16f86, + 0x1384, + 0xc634b, + 0x3a806, + 0x7f3c7, + 0x1431c9, + 0x233fc3, + 0x49e88, + 0x49e8b, + 0x4a30b, + 0x4a9cb, + 0x4ad0b, + 0x4afcb, + 0x4b40b, + 0x1cb86, + 0x266a83, + 0xf48c5, + 0x2044, + 0x20ef43, + 0x11b787, + 0xe88c4, + 0x722c4, + 0x217fc3, + 0x81006, + 0x1583c4, + 0x1c0443, + 0x23e083, + 0x300ac4, + 0x131247, + 0x1371c9, + 0xc6108, + 0x1a2584, + 0x1ca344, + 0x134c46, + 0xff48, + 0x1480c5, + 0x124e89, + 0xe783, + 0x146bc5, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x205803, + 0x23e083, + 0x2ffec3, + 0x22dc42, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e703, + 0x21e484, + 0x217fc3, + 0x5803, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x2e5904, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x243bc6, + 0x233fc3, + 0x266a83, + 0xf443, + 0x1c0443, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x146bc5, + 0x7f3c7, + 0x15c3, + 0xe783, + 0xae888, + 0x266a83, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x612c3, + 0x217fc3, + 0x23e083, + 0x5622ea43, + 0x233fc3, + 0x217fc3, + 0x23e083, + 0xae888, + 0x2000c2, + 0x212402, + 0x22ea43, + 0x266a83, + 0x217fc3, + 0x2003c2, + 0x23e083, + 0x33c187, + 0x355d4b, + 0x211843, + 0x27da88, + 0x330107, + 0x229dc6, + 0x2d42c5, + 0x36a609, + 0x243948, + 0x381049, + 0x3ac290, + 0x38104b, + 0x215589, + 0x2015c3, + 0x2fa6c9, + 0x232646, + 0x23264c, + 0x334fc8, + 0x3dde48, + 0x26eac9, + 0x2c8b0e, + 0x23a24b, + 0x2c030c, + 0x233f03, + 0x284e8c, + 0x3e13c9, + 0x238447, + 0x233f0c, + 0x2bde8a, + 0x241ec4, + 0x38aa8d, + 0x284d48, + 0x219acd, + 0x292146, + 0x24cd4b, + 0x337349, + 0x38fa07, + 0x25f0c6, + 0x323849, + 0x35484a, + 0x30e748, + 0x2ffac4, + 0x3a8e87, + 0x3c0807, + 0x208184, + 0x2221c4, + 0x3b4809, + 0x35c549, + 0x3e1f48, + 0x2f2c85, + 0x2102c5, + 0x209a86, + 0x38a949, + 0x28654d, + 0x2ece48, + 0x209987, + 0x2d4348, + 0x26bdc6, + 0x22fa44, + 0x2a4d45, + 0x3d9f46, + 0x3dc104, + 0x3e12c7, + 0x204e8a, + 0x210e04, + 0x213386, + 0x214689, + 0x21468f, + 0x214c4d, + 0x215ac6, + 0x21aa10, + 0x21ae06, + 0x21b507, + 0x21bcc7, + 0x21bccf, + 0x21c689, + 0x224c46, + 0x225047, + 0x225048, + 0x225449, + 0x20f708, + 0x306a07, + 0x22b743, + 0x22e8c6, + 0x239148, + 0x2c8dca, + 0x20cf09, + 0x243a83, + 0x36a3c6, + 0x38524a, + 0x2fbb87, + 0x23828a, + 0x316c8e, + 0x21c7c6, + 0x32bc47, + 0x38ef46, + 0x243fc6, + 0x21cc8b, + 0x3a038a, + 0x35638d, + 0x2800c7, + 0x26dc08, + 0x26dc09, + 0x26dc0f, + 0x30a80c, + 0x265209, + 0x2bbbce, + 0x21608a, + 0x20dac6, + 0x3076c6, + 0x31a1cc, + 0x3df50c, + 0x325908, + 0x35fd07, + 0x39d4c5, + 0x3ca3c4, + 0x25fd0e, + 0x3ae384, + 0x37dd87, + 0x3a6d8a, + 0x3d7cd4, + 0x3db78f, + 0x21be88, + 0x22e788, + 0x39124d, + 0x39124e, + 0x22ed49, + 0x22fe88, + 0x22fe8f, + 0x233c0c, + 0x233c0f, + 0x234dc7, + 0x23718a, + 0x23874b, + 0x2395c8, + 0x23b807, + 0x260b4d, + 0x369646, + 0x38ac46, + 0x23d649, + 0x252848, + 0x243dc8, + 0x243dce, + 0x2bb387, + 0x305145, + 0x246ac5, + 0x206484, + 0x22a086, + 0x3e1e48, + 0x324643, + 0x2e8c8e, + 0x260f08, + 0x2acacb, + 0x276407, + 0x30b205, + 0x269c06, + 0x2b6ec7, + 0x321848, + 0x37d749, + 0x3d2cc5, + 0x28e408, + 0x228a46, + 0x3addca, + 0x25fc09, + 0x233fc9, + 0x233fcb, + 0x25c6c8, + 0x208049, + 0x2f2d46, + 0x2041ca, + 0x29d08a, + 0x23738c, + 0x375e07, + 0x27268a, + 0x331b0b, + 0x331b19, + 0x353148, + 0x243c45, + 0x260d06, + 0x211d89, + 0x3b2c46, + 0x22170a, + 0x275246, + 0x2d8384, + 0x2d838d, + 0x3b4447, + 0x368889, + 0x249285, + 0x2493c8, + 0x249c49, + 0x24bb44, + 0x24c247, + 0x24c248, + 0x24c507, + 0x26c188, + 0x251c87, + 0x2daec5, + 0x25828c, + 0x258749, + 0x31d28a, + 0x3b09c9, + 0x2fa7c9, + 0x38f54c, + 0x25accb, + 0x25c8c8, + 0x261448, + 0x264f04, + 0x28b548, + 0x28cb89, + 0x2bdf47, + 0x2148c6, + 0x2a3b07, + 0x2a0f49, + 0x354d4b, + 0x20b187, + 0x348647, + 0x3da547, + 0x219a44, + 0x219a45, + 0x2e5605, + 0x35e84b, + 0x349284, + 0x328308, + 0x30234a, + 0x228b07, + 0x3d0347, + 0x295192, + 0x293dc6, + 0x231346, + 0x34890e, + 0x294586, + 0x299e48, + 0x29aacf, + 0x219e88, + 0x28fb88, + 0x2df5ca, + 0x2df5d1, + 0x2ab64e, + 0x2550ca, + 0x2550cc, + 0x230087, + 0x230090, + 0x3d4f08, + 0x2ab845, + 0x2b71ca, + 0x3dc14c, + 0x29e08d, + 0x204906, + 0x204907, + 0x20490c, + 0x209d8c, + 0x2191cc, + 0x2c204b, + 0x3923c4, + 0x226c84, + 0x2ba749, + 0x34a1c7, + 0x382f89, + 0x29cec9, + 0x2bdb47, + 0x2bdd06, + 0x2bdd09, + 0x2be103, + 0x2af60a, + 0x323a87, + 0x3ca70b, + 0x35620a, + 0x32ad84, + 0x3c88c6, + 0x288809, + 0x3612c4, + 0x2e164a, + 0x2e2845, + 0x2cd7c5, + 0x2cd7cd, + 0x2cdb0e, + 0x2c9c05, + 0x33ae46, + 0x2437c7, + 0x2525ca, + 0x3ae686, + 0x381c04, + 0x35a607, + 0x2fc70b, + 0x26be87, + 0x2699c4, + 0x253306, + 0x25330d, + 0x2e724c, + 0x217e86, + 0x2ed04a, + 0x223486, + 0x220dc8, + 0x274707, + 0x2d5eca, + 0x2361c6, + 0x27ffc3, + 0x2f4b46, + 0x238fc8, + 0x37204a, + 0x2df007, + 0x2df008, + 0x25bfc4, + 0x295707, + 0x2fdf08, + 0x293fc8, + 0x2c30c8, + 0x33e14a, + 0x2ee705, + 0x2ee987, + 0x254f13, + 0x271146, + 0x20bc08, + 0x222a49, + 0x2432c8, + 0x3673cb, + 0x3cd3c8, + 0x2cab84, + 0x2c0c86, + 0x325e06, + 0x322349, + 0x2d5d07, + 0x258388, + 0x2a5c46, + 0x200bc4, + 0x3d5d85, + 0x3aa788, + 0x248e8a, + 0x2d8008, + 0x2dcf86, + 0x2a21ca, + 0x273d48, + 0x2e0648, + 0x2e18c8, + 0x2e2106, + 0x2e4286, + 0x3b048c, + 0x2e4810, + 0x2b8a85, + 0x219c88, + 0x21e910, + 0x219c90, + 0x3ac10e, + 0x3b010e, + 0x3b0114, + 0x3b934f, + 0x3b9706, + 0x3b6051, + 0x208253, + 0x2086c8, + 0x25f245, + 0x27dfc8, + 0x3a7c45, + 0x34aacc, + 0x22b989, + 0x3ae1c9, + 0x317147, + 0x237bc9, + 0x3b2807, + 0x33a486, + 0x2a4b47, + 0x202cc5, + 0x20fec3, + 0x20f443, + 0x215bc4, + 0x3dff8d, + 0x20bf4f, + 0x200c05, + 0x34a9c6, + 0x2200c7, + 0x334d47, + 0x37b8c6, + 0x37b8cb, + 0x2ac3c5, + 0x259986, + 0x30db47, + 0x252b89, + 0x225706, + 0x38c185, + 0x3c324b, + 0x205d06, + 0x226685, + 0x246248, + 0x296448, + 0x2ae3cc, + 0x2ae3d0, + 0x2b4f89, + 0x2c7007, + 0x2be80b, + 0x2ce086, + 0x3068ca, + 0x2a81cb, + 0x38160a, + 0x39f946, + 0x2f8d05, + 0x330006, + 0x28d548, + 0x31720a, + 0x390edc, + 0x2fff8c, + 0x300288, + 0x243bc5, + 0x387ac7, + 0x25d246, + 0x2bcc85, + 0x218386, + 0x37ba88, + 0x2cc2c7, + 0x2c8a08, + 0x27120a, + 0x3c110c, + 0x3248c9, + 0x3c1387, + 0x28d0c4, + 0x246b86, + 0x28f70a, + 0x29cfc5, + 0x221e4c, + 0x222508, + 0x2f6848, + 0x2b1a0c, + 0x31aa0c, + 0x32a8c9, + 0x32ab07, + 0x242dcc, + 0x22ac84, + 0x36fe0a, + 0x31114c, + 0x24e1cb, + 0x24f60b, + 0x2509c6, + 0x2541c7, + 0x2302c7, + 0x2302cf, + 0x312111, + 0x2eb492, + 0x25538d, + 0x25538e, + 0x2556ce, + 0x3b9508, + 0x3b9512, + 0x266448, + 0x223087, + 0x24fa4a, + 0x2af348, + 0x294545, + 0x2c258a, + 0x21b187, + 0x2f1004, + 0x20ee43, + 0x236c45, + 0x2df847, + 0x3aca87, + 0x29e28e, + 0x33dacd, + 0x350d49, + 0x31fb05, + 0x35f4c3, + 0x34ca46, + 0x259ec5, + 0x2acd08, + 0x227349, + 0x260d45, + 0x260d4f, + 0x2c6447, + 0x2154c5, + 0x276dca, + 0x205646, + 0x35d1c9, + 0x386ecc, + 0x3d2dc9, + 0x20b386, + 0x30214c, + 0x333f86, + 0x310088, + 0x331a06, + 0x36c7c6, + 0x2c34c4, + 0x3222c3, + 0x20de0a, + 0x22de51, + 0x26a90a, + 0x25b105, + 0x288207, + 0x255b47, + 0x2e8a84, + 0x2fe00b, + 0x347688, + 0x2cb146, + 0x23e285, + 0x268b84, + 0x24fc89, + 0x2008c4, + 0x2124c7, + 0x34d185, + 0x34d187, + 0x348b45, + 0x20bb83, + 0x222f48, + 0x27e1ca, + 0x249b03, + 0x334f4a, + 0x2a9d06, + 0x260acf, + 0x2bb309, + 0x2e8c10, + 0x3064c8, + 0x2dd9c9, + 0x29f107, + 0x25328f, + 0x3bb9c4, + 0x2e5984, + 0x21ac86, + 0x2356c6, + 0x23edca, + 0x247cc6, + 0x2b9447, + 0x317c48, + 0x317e47, + 0x3192c7, + 0x31ad0a, + 0x319bcb, + 0x358f85, + 0x2eb0c8, + 0x21a303, + 0x3ccbcc, + 0x39d24f, + 0x3c7e0d, + 0x258b87, + 0x350e89, + 0x2f5c87, + 0x28c3c8, + 0x3d7ecc, + 0x2caa88, + 0x366dc8, + 0x332bce, + 0x345b54, + 0x346064, + 0x365d0a, + 0x38188b, + 0x3b28c4, + 0x3b28c9, + 0x239b88, + 0x247385, + 0x32414a, + 0x2a5007, + 0x215d84, + 0x24ac43, + 0x22ea43, + 0x236704, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x2191c3, + 0x23cb03, + 0x2e4806, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x216983, + 0x2000c2, + 0x24ac43, + 0x212402, + 0x22ea43, + 0x236704, + 0x233fc3, + 0x266a83, + 0x2191c3, + 0x2e4806, + 0x217fc3, + 0x23e083, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x280203, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x2000c2, + 0x281bc3, + 0x212402, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x20cf02, + 0x20cdc2, + 0x212402, + 0x22ea43, + 0x204302, + 0x2005c2, + 0x20e704, + 0x217544, + 0x266002, + 0x21e484, + 0x2003c2, + 0x23e083, + 0x216983, + 0x2509c6, + 0x21fcc2, + 0x2072c2, + 0x223d42, + 0x58a13d83, + 0x58e30083, + 0x56486, + 0x56486, + 0x24cd44, + 0x205803, + 0x8acd, + 0x1e1cca, + 0x1cc04c, + 0x173cc, + 0xd720d, + 0x6e784, + 0x8f284, + 0x120384, + 0x146bc5, + 0x8e9c9, + 0xbf04c, + 0x1683c7, + 0x11fc6, + 0x16588, + 0x1a087, + 0x20ac8, + 0x1bdd8a, + 0x1109c7, + 0x59abd285, + 0xbd289, + 0x59c35a0b, + 0x129f08, + 0xcc4b, + 0x141488, + 0x167e89, + 0x8c80a, + 0x1316ce, + 0xbec4a, + 0xa4cd, + 0x2ed4d, + 0x14430cb, + 0xe710a, + 0x1384, + 0x59ac6, + 0xf988, + 0x10f508, + 0x35cc7, + 0x1dbc5, + 0x1fb47, + 0x34449, + 0x161347, + 0xec88, + 0x2afc9, + 0x3ea84, + 0xd3085, + 0x737ce, + 0x1410c7, + 0x5a224d46, + 0x4efcd, + 0x7f248, + 0x5a65ce86, + 0x5b05ce88, + 0x57388, + 0x13c390, + 0x5460c, + 0x68787, + 0x693c7, + 0x707c7, + 0x77c07, + 0x9a42, + 0x16e07, + 0x1a054c, + 0x5d4c5, + 0xb4e07, + 0xae286, + 0xafcc9, + 0xb3108, + 0xb5c2, + 0x5c2, + 0x193c86, + 0x1c2b0b, + 0x1c2e06, + 0x6f044, + 0x1b5ac7, + 0x33449, + 0x860c9, + 0x1bb208, + 0x4b202, + 0x199249, + 0x11a08, + 0xfb54a, + 0xe689, + 0x2a8c6, + 0xdac89, + 0xe7087, + 0xe77c9, + 0xea1c8, + 0xec607, + 0xee689, + 0xf1a45, + 0xf1e10, + 0x1d60c6, + 0x1b5a05, + 0x19dfc7, + 0xbd68d, + 0x41d85, + 0xfa5c6, + 0xfadc7, + 0x100ad8, + 0x7f5c8, + 0x14978a, + 0xd782, + 0x5b7928cb, + 0x4f3ca, + 0x5a04d, + 0x2442, + 0xd4d86, + 0x13a06, + 0xa2ac8, + 0xb2e8a, + 0x3dd48, + 0x74e49, + 0x118088, + 0x6f48e, + 0x75088, + 0x14ca47, + 0x5ba5cdc4, + 0xb170d, + 0x1095c5, + 0x2748, + 0x35288, + 0x1145c6, + 0x4642, + 0xcaf44, + 0xe5006, + 0x134c46, + 0x5bd8490b, + 0x3602, 0x401, 0x81, - 0xb8f08, - 0x5bc87, - 0x150503, - 0x59a37f04, - 0x59e9b383, + 0xbe588, + 0x5bb87, + 0x93783, + 0x5aa37e84, + 0x5ae9c0c3, 0xc1, - 0xf586, + 0x25d86, 0xc1, 0x201, - 0xf586, - 0x150503, - 0x66603, - 0x647c4, - 0x1e7c7, - 0x7787, - 0x15c27c5, - 0x4e684, - 0x13d707, - 0x1242, - 0x24c0c4, - 0x214a83, - 0x24d9c4, - 0x221dc4, - 0x21a3c3, - 0x221445, - 0x214903, - 0x22b983, - 0x208805, - 0x207783, - 0x1243, - 0x5ba14a83, - 0x232dc3, - 0x4d9c4, - 0x7083, - 0x308003, + 0x25d86, + 0x93783, + 0x18b7c8, + 0x4cdc3, + 0x27c44, + 0x20f47, + 0xaa47, + 0x1571585, + 0x4e584, + 0x149307, + 0x12402, + 0x241ec4, + 0x22ea43, + 0x24d704, + 0x20e704, + 0x217fc3, + 0x222905, + 0x217c83, + 0x235403, + 0x37b845, + 0x20aa43, + 0x1be83, + 0x5ce2ea43, + 0x233fc3, + 0x4d704, + 0x33c3, + 0x266a83, 0x200181, - 0x1a8c3, - 0x23c803, - 0x306c44, - 0x219a04, - 0x21a3c3, - 0x4e283, - 0x242543, - 0x20e2c3, - 0x9a048, + 0x1e1c3, + 0x23cb03, + 0x217544, + 0x21e484, + 0x217fc3, + 0x4dfc3, + 0x23e083, + 0x208503, + 0xae888, 0x2000c2, - 0x202703, - 0x201242, - 0x214a83, - 0x232dc3, - 0x228503, + 0x24ac43, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x280203, 0x2005c2, - 0x221dc4, - 0x21bc83, - 0x23c803, - 0x21a3c3, - 0x203dc3, - 0x242543, - 0x207783, - 0x196504, - 0x9a048, - 0x106947, - 0x1242, - 0x1a3105, - 0x540cf, - 0xe0986, - 0x144ca88, - 0x1160ce, - 0x5ca345c2, - 0x297ac8, - 0x35c5c6, - 0x24e806, - 0x395e87, - 0x5ce00c82, - 0x5d2b7488, - 0x20bd4a, - 0x2615c8, + 0x20e704, + 0x2191c3, + 0x23cb03, + 0x217fc3, + 0x205803, + 0x23e083, + 0x20aa43, + 0x19d184, + 0xae888, + 0x10a087, + 0x12402, + 0x1aa705, + 0x5474f, + 0xf10c6, + 0x1454408, + 0x118cce, + 0x5de2a502, + 0x32f688, + 0x361886, + 0x24e706, + 0x39cb07, + 0x5e200c82, + 0x5e6bb188, + 0x21f28a, + 0x268208, 0x200ac2, - 0x3c8c49, - 0x33bfc7, - 0x212686, - 0x2217c9, - 0x2c1c04, - 0x3c8b46, - 0x2cc7c4, - 0x20e904, - 0x257889, - 0x30dbc6, - 0x265445, - 0x266245, - 0x22d547, - 0x2dbd87, - 0x34c8c4, - 0x31e606, - 0x2ff485, - 0x210845, - 0x23eac5, - 0x3bd9c7, - 0x26f6c5, - 0x248489, - 0x343fc5, - 0x31b484, - 0x3a6987, - 0x36344e, - 0x2031c9, - 0x2885c9, - 0x348706, - 0x23f9c8, - 0x36f2cb, - 0x2a5a0c, - 0x322686, - 0x2ba447, - 0x2eee85, - 0x3270ca, - 0x3d9bc9, - 0x345c89, - 0x295146, - 0x30bc05, - 0x245705, - 0x36a209, - 0x23ec4b, - 0x2c2246, - 0x352686, - 0x2067c4, - 0x2ecd46, - 0x304448, - 0x3c1e46, - 0x2e3e06, - 0x3dd908, - 0x2019c7, - 0x201d49, - 0x205a85, - 0x9a048, - 0x3cd4c4, - 0x316c44, - 0x20b105, - 0x3403c9, - 0x220747, - 0x22074b, - 0x22284a, - 0x228585, - 0x5d60c282, - 0x2cda07, - 0x5da29cc8, - 0x295387, - 0x301345, - 0x348aca, - 0x1242, - 0x27c58b, - 0x27d98a, - 0x248906, - 0x20a803, - 0x206c8d, - 0x3c4c4c, - 0x3c534d, - 0x230585, - 0x27bbc5, - 0x296dc7, - 0x3d1149, - 0x20bc46, - 0x254505, - 0x37b708, - 0x2ce983, - 0x2e3948, - 0x2ecc48, - 0x383fc7, - 0x3b8a88, - 0x3c0809, - 0x2fd2c7, - 0x2cd207, - 0x3de588, - 0x23ae04, - 0x23ae07, - 0x3a6bc8, - 0x360f06, - 0x3c0ecf, - 0x22a907, - 0x31e106, - 0x22dcc5, - 0x222343, - 0x246287, - 0x387fc3, - 0x24d046, - 0x24e586, - 0x24f0c6, - 0x293d45, - 0x265c03, - 0x3936c8, - 0x38a109, - 0x39bf8b, - 0x24f248, - 0x250a85, - 0x252305, - 0x5de2dec2, - 0x2842c9, - 0x221e47, - 0x25a045, - 0x257787, - 0x258ac6, - 0x381745, - 0x25a40b, - 0x25c004, - 0x261185, - 0x2612c7, - 0x276806, - 0x276c45, - 0x283d87, - 0x2847c7, - 0x2a7484, - 0x28d0ca, - 0x28dbc8, - 0x2ccc09, - 0x23f285, - 0x205886, - 0x30460a, - 0x266146, - 0x2ed087, - 0x26d30d, - 0x2aa2c9, - 0x391c45, - 0x363847, - 0x289708, - 0x303588, - 0x3286c7, - 0x384d06, - 0x21abc7, - 0x24dbc3, - 0x30db44, - 0x37d485, - 0x3a7747, - 0x3b0d49, - 0x229588, - 0x2ecf85, - 0x2425c4, - 0x247ec5, - 0x24f40d, + 0x3ca549, + 0x358fc7, + 0x214846, + 0x222c89, + 0x2eeac4, + 0x3ca446, + 0x2e9104, + 0x2029c4, + 0x257b49, + 0x310e86, + 0x267c85, + 0x26b845, + 0x22f587, + 0x2de387, + 0x26b784, + 0x2d2486, + 0x301785, + 0x20ee05, + 0x25b1c5, + 0x2c2347, + 0x276245, + 0x24a0c9, + 0x37eb85, + 0x321984, + 0x3ae5c7, + 0x3b3fce, + 0x207289, + 0x3487c9, + 0x371246, + 0x2405c8, + 0x37554b, + 0x2a74cc, + 0x326f06, + 0x2c01c7, + 0x2f0d05, + 0x3163ca, + 0x3e2049, + 0x201189, + 0x206a86, + 0x30d905, + 0x246e45, + 0x389a89, + 0x25b34b, + 0x2ef106, + 0x353806, + 0x209984, + 0x303a46, + 0x3051c8, + 0x3cbf46, + 0x267846, + 0x203048, + 0x205107, + 0x206809, + 0x208e85, + 0xae888, + 0x3d2c44, + 0x319844, + 0x210145, + 0x343c49, + 0x221287, + 0x22128b, + 0x22434a, + 0x228745, + 0x5ea087c2, + 0x3560c7, + 0x5ee2b748, + 0x206cc7, + 0x303085, + 0x35d60a, + 0x12402, + 0x28428b, + 0x28544a, + 0x24a546, + 0x20ffc3, + 0x21114d, + 0x3ca98c, + 0x203a8d, + 0x232105, + 0x3363c5, + 0x324687, + 0x206309, + 0x21f186, + 0x247b45, + 0x3401c8, + 0x2d4dc3, + 0x2f52c8, + 0x303948, + 0x3a2107, + 0x3c5d88, + 0x3c76c9, + 0x2ff5c7, + 0x3558c7, + 0x371408, + 0x38bcc4, + 0x38bcc7, + 0x292048, + 0x366406, + 0x3cb14f, + 0x265747, + 0x2d1f86, + 0x32ac45, + 0x223ec3, + 0x2479c7, + 0x38e083, + 0x24c6c6, + 0x24e486, + 0x24ff06, + 0x298ec5, + 0x26c183, + 0x398ec8, + 0x390849, + 0x3a290b, + 0x250088, + 0x251945, + 0x253645, + 0x5f2ba882, + 0x2a4c09, + 0x223307, + 0x259a05, + 0x257a47, + 0x258ec6, + 0x386ac5, + 0x259d0b, + 0x25c8c4, + 0x267dc5, + 0x267f07, + 0x27c586, + 0x27c9c5, + 0x28b987, + 0x28c147, + 0x2a9cc4, + 0x2bee4a, + 0x292b08, + 0x375809, + 0x25b985, + 0x3585c6, + 0x30538a, + 0x26d6c6, + 0x236047, + 0x272a0d, + 0x2abf09, + 0x397445, + 0x2603c7, + 0x32d088, + 0x3b38c8, + 0x20a107, + 0x20e3c6, + 0x22cc07, + 0x24d903, + 0x310e04, + 0x383405, + 0x3af807, + 0x3bae09, + 0x2f5e08, + 0x235f45, + 0x362784, + 0x250245, + 0x25ca8d, 0x200cc2, - 0x2bca46, - 0x2eaf06, - 0x308cca, - 0x39a786, - 0x3a3345, - 0x26d6c5, - 0x26d6c7, - 0x3a5fcc, - 0x256e0a, - 0x28f246, - 0x2e1d85, - 0x2ecb86, - 0x28f507, - 0x291246, - 0x293c4c, - 0x221909, - 0x5e20fa07, - 0x29a9c5, - 0x29a9c6, - 0x29ae08, - 0x2c4005, - 0x2aab45, - 0x2ab848, - 0x2aba4a, - 0x5e67b8c2, - 0x5ea09e42, - 0x355fc5, - 0x237643, - 0x326008, - 0x228703, - 0x2abcc4, - 0x312c4b, - 0x36f688, - 0x2b9648, - 0x5ef03cc9, - 0x2b1009, - 0x2b19c6, - 0x2b2788, - 0x2b2989, - 0x2b3806, - 0x2b3985, - 0x246c06, - 0x2b4749, - 0x2c8947, - 0x38e386, - 0x20af47, - 0x345fc7, - 0x207584, - 0x5f2d1909, - 0x24ad08, - 0x2b7388, - 0x2257c7, - 0x2d5946, - 0x3d0f49, - 0x24e7c7, - 0x24a58a, - 0x32ed08, - 0x3bb707, - 0x3d0606, - 0x2f0e0a, - 0x23df48, - 0x2ea985, - 0x227b85, - 0x3cbc87, - 0x3190c9, - 0x31cf0b, - 0x351f08, - 0x344049, - 0x24fb47, - 0x2c2bcc, - 0x2c3bcc, - 0x2c3eca, - 0x2c414c, - 0x2cc348, - 0x2cc548, - 0x2cc744, - 0x2ce109, - 0x2ce349, - 0x2ce58a, - 0x2ce809, - 0x2ceb87, - 0x3bec0c, - 0x3d2406, - 0x26ccc8, - 0x266206, - 0x38fe86, - 0x391b47, - 0x3a1088, - 0x3debcb, - 0x295247, - 0x257549, - 0x25ba49, - 0x2844c7, - 0x2cca04, - 0x200fc7, - 0x2f0806, - 0x20e486, - 0x24c845, - 0x2f7d48, - 0x26c544, - 0x26c546, - 0x256ccb, - 0x2b3449, - 0x235686, - 0x2e4009, - 0x20b1c6, - 0x345048, - 0x210543, - 0x30bd85, - 0x21a9c9, - 0x21c7c5, - 0x30e1c4, - 0x275d46, - 0x235a05, - 0x254306, - 0x319a07, - 0x247946, - 0x22c2cb, - 0x3c5987, - 0x3a28c6, - 0x2730c6, - 0x22d606, - 0x34c889, - 0x3b604a, - 0x2c58c5, - 0x3d6f8d, - 0x2abb46, - 0x23c346, - 0x2e6f86, - 0x21e5c5, - 0x2f1507, - 0x228ec7, - 0x27390e, - 0x23c803, - 0x2d5909, - 0x297289, - 0x22d287, - 0x26bbc7, - 0x2919c5, - 0x367b05, - 0x5f60210f, - 0x2db607, - 0x2db7c8, - 0x2dbb84, - 0x2dc046, - 0x5fa45402, - 0x2e01c6, - 0x2e2406, - 0x29744e, - 0x2e378a, - 0x207106, - 0x2b7c0a, - 0x3c7709, - 0x2fbe85, - 0x2ee188, - 0x3cbb46, - 0x2b7188, - 0x202ac8, - 0x277fcb, - 0x395f85, - 0x26f748, - 0x3dda4c, - 0x301207, - 0x24eb46, - 0x30c2c8, - 0x3de888, - 0x5fe30a42, - 0x21504b, - 0x205c89, - 0x28d989, - 0x21c647, - 0x3b5dc8, - 0x603d32c8, - 0x20934b, - 0x349bc9, - 0x25b18d, - 0x202908, - 0x2f1008, - 0x60604042, - 0x20d5c4, - 0x60a2aec2, - 0x3cd9c6, - 0x60e01282, - 0x2fbc8a, - 0x2a3806, - 0x34bd48, - 0x3c6908, - 0x3d9746, - 0x2ba946, - 0x3054c6, - 0x2ab045, - 0x239e44, - 0x6122ae04, - 0x359946, - 0x276247, - 0x6160d8c7, - 0x278b4b, - 0x295589, - 0x27bc0a, - 0x26d804, - 0x2f3b08, - 0x38e14d, - 0x2fc409, - 0x2fc648, - 0x2fc8c9, - 0x2fe7c4, - 0x2aae04, - 0x38d205, - 0x346f0b, - 0x36f606, - 0x359785, - 0x236209, - 0x31e6c8, - 0x22af84, - 0x327249, - 0x24a345, - 0x2dbdc8, - 0x2cd8c7, - 0x2889c8, - 0x281006, - 0x3ba447, - 0x2e6b09, - 0x3c9289, - 0x21d705, - 0x3682c5, - 0x61a1e342, - 0x31b244, - 0x21fe85, - 0x395d86, - 0x346905, - 0x244b07, - 0x359a45, - 0x276844, - 0x3487c6, - 0x254587, - 0x238f46, - 0x30a945, - 0x217108, - 0x35c7c5, - 0x21a847, - 0x2277c9, - 0x2b358a, - 0x264cc7, - 0x264ccc, - 0x265406, - 0x2423c9, - 0x31f045, - 0x369188, - 0x211ec3, - 0x398c45, - 0x3b9285, - 0x27b207, - 0x61e08dc2, - 0x2f8087, - 0x2eea86, - 0x38dc46, - 0x2f6146, - 0x3de7c6, - 0x230988, - 0x2d0145, - 0x31e1c7, - 0x31e1cd, - 0x210883, - 0x3d28c5, - 0x270007, - 0x2f83c8, - 0x26fbc5, - 0x214408, - 0x37cf06, - 0x2e50c7, - 0x2d4605, - 0x396006, - 0x393c45, - 0x20ba0a, - 0x310586, - 0x2645c7, - 0x2c9485, - 0x3a8a87, - 0x3cdb04, - 0x30e146, - 0x3cba85, - 0x39a18b, - 0x2f0689, - 0x27ef0a, - 0x21d788, - 0x314248, - 0x31968c, - 0x31adc7, - 0x330a08, - 0x335d88, - 0x3382c5, - 0x358dca, - 0x361049, - 0x62203242, - 0x2945c6, - 0x25c9c4, - 0x2fa949, - 0x35d749, - 0x2451c7, - 0x29b947, - 0x2bfb09, - 0x2ffe08, - 0x2ffe0f, - 0x21b5c6, - 0x2e4bcb, - 0x259dc5, - 0x259dc7, - 0x37bd49, - 0x20c8c6, - 0x3271c7, - 0x2e9105, - 0x230484, - 0x2f5006, - 0x220904, - 0x2f9c47, - 0x321c88, - 0x6270bb08, + 0x2ce4c6, + 0x2f7986, + 0x30820a, + 0x3a0e06, + 0x3aa945, + 0x2e95c5, + 0x2e95c7, + 0x3adc0c, + 0x25720a, + 0x294d06, + 0x2e4185, + 0x303886, + 0x294fc7, + 0x296986, + 0x298dcc, + 0x222dc9, + 0x5f626207, + 0x29ae85, + 0x29ae86, + 0x29bb48, + 0x2ca185, + 0x2ac785, + 0x2ad148, + 0x2ad34a, + 0x5fa295c2, + 0x5fe0b942, + 0x309d85, + 0x26a483, + 0x32a308, + 0x210503, + 0x2ad5c4, + 0x35d30b, + 0x2a78c8, + 0x384648, + 0x6034b7c9, + 0x2b48c9, + 0x2b51c6, + 0x2b6b48, + 0x2b6d49, + 0x2b7a86, + 0x2b7c05, + 0x248486, + 0x2b8589, + 0x2cd607, + 0x394746, + 0x21b347, + 0x2014c7, + 0x213f04, + 0x6067f8c9, + 0x2bcec8, + 0x2bb088, + 0x200e07, + 0x2d7c86, + 0x205a89, + 0x24e6c7, + 0x3c250a, + 0x3c8108, + 0x2131c7, + 0x2180c6, + 0x2a114a, + 0x32a708, + 0x2f7405, + 0x225a05, + 0x3d12c7, + 0x3264c9, + 0x32878b, + 0x39be48, + 0x37ec09, + 0x250487, + 0x2c94cc, + 0x2c9d4c, + 0x2ca04a, + 0x2ca2cc, + 0x2d3d88, + 0x2d3f88, + 0x2d4184, + 0x2d4549, + 0x2d4789, + 0x2d49ca, + 0x2d4c49, + 0x2d4fc7, + 0x3c91cc, + 0x3dc686, + 0x2723c8, + 0x26d786, + 0x3957c6, + 0x397347, + 0x3a8708, + 0x22a28b, + 0x206b87, + 0x257809, + 0x288349, + 0x2a4e07, + 0x2e9344, + 0x269087, + 0x39b786, + 0x2128c6, + 0x2ed205, + 0x2f9848, + 0x317044, + 0x317046, + 0x2570cb, + 0x2af909, + 0x385c06, + 0x267a49, + 0x210206, + 0x249088, + 0x20eb03, + 0x30da85, + 0x219849, + 0x214445, + 0x3b9e84, + 0x3d25c6, + 0x308005, + 0x20a686, + 0x31d587, + 0x355006, + 0x22c6cb, + 0x2040c7, + 0x3a9c46, + 0x278c86, + 0x22f646, + 0x26b749, + 0x3b5e0a, + 0x2cb445, + 0x205e0d, + 0x2ad446, + 0x239446, + 0x2e8b06, + 0x220d45, + 0x2f2107, + 0x30b4c7, + 0x2794ce, + 0x23cb03, + 0x2d7c49, + 0x324b49, + 0x22f2c7, + 0x271a47, + 0x2703c5, + 0x294145, + 0x60bb494f, + 0x2ddc07, + 0x2dddc8, + 0x2de184, + 0x2de646, + 0x60e46b42, + 0x2e2386, + 0x2e4806, + 0x3b564e, + 0x2f510a, + 0x2bb906, + 0x218d4a, + 0x203889, + 0x23c7c5, + 0x312d08, + 0x33dd86, + 0x2ba948, + 0x36aac8, + 0x28238b, + 0x39cc05, + 0x2762c8, + 0x20318c, + 0x302f47, + 0x24f986, + 0x30e908, + 0x229f48, + 0x6123bec2, + 0x20c70b, + 0x209089, + 0x2bf709, + 0x21a747, + 0x3c3088, + 0x6161cf48, + 0x21d84b, + 0x34bd89, + 0x28be0d, + 0x3802c8, + 0x2a1348, + 0x61a09282, + 0x228644, + 0x61e30242, + 0x3b9cc6, + 0x62200e42, + 0x2fd7ca, + 0x364486, + 0x267388, + 0x3cea88, + 0x3e1bc6, + 0x2c06c6, + 0x306246, + 0x2acc85, + 0x239dc4, + 0x62768e04, + 0x35f2c6, + 0x277a47, + 0x62a810c7, + 0x24ed8b, + 0x206ec9, + 0x33640a, + 0x2f4dc4, + 0x2e9708, + 0x39450d, + 0x2fe709, + 0x2fe948, + 0x2febc9, + 0x300ac4, + 0x266344, + 0x393505, + 0x33f0cb, + 0x2a7846, + 0x35f105, + 0x236dc9, + 0x2d2548, + 0x2aa9c4, + 0x316549, + 0x3c22c5, + 0x2de3c8, + 0x355f87, + 0x348bc8, + 0x288a06, + 0x20f5c7, + 0x2e8689, + 0x3c33c9, + 0x226705, + 0x23b4c5, + 0x62e13242, + 0x321744, + 0x232345, + 0x39ca06, + 0x33eac5, + 0x23fa07, + 0x35f3c5, + 0x27c5c4, + 0x371306, + 0x247bc7, + 0x238e46, 0x30c645, - 0x30c787, - 0x324389, - 0x20d184, - 0x241048, - 0x62bd0448, - 0x2e6f04, - 0x31d648, - 0x295a04, - 0x3b6349, - 0x21e505, - 0x62e33442, - 0x21b605, - 0x2dd945, - 0x289548, - 0x233a07, - 0x632008c2, - 0x22af45, - 0x2de0c6, - 0x243906, - 0x31b208, - 0x338fc8, - 0x3468c6, - 0x34afc6, - 0x306a09, - 0x38db86, - 0x20c78b, - 0x3c2705, - 0x2ac8c6, - 0x3c4a88, - 0x33f6c6, - 0x224786, - 0x216bca, - 0x2df94a, - 0x248a45, - 0x30ce07, - 0x274586, - 0x63603642, - 0x270147, - 0x33c305, - 0x304584, - 0x304585, - 0x2f3a06, - 0x272c47, - 0x203945, - 0x2dfac4, - 0x352248, - 0x224845, - 0x37ae87, - 0x3ca445, - 0x20b945, - 0x2d2904, - 0x2d2909, - 0x2ff2c8, - 0x23a5c6, - 0x35aa06, - 0x302d06, - 0x63bd5b08, - 0x311d07, - 0x31234d, - 0x312f0c, - 0x313509, - 0x313749, - 0x63f75442, - 0x3d4a03, - 0x2010c3, - 0x2f08c5, - 0x3a784a, - 0x338e86, - 0x23cec5, - 0x31a504, - 0x31a50b, - 0x32d64c, - 0x32df0c, - 0x32e215, - 0x32f70d, - 0x33208f, - 0x332452, - 0x3328cf, - 0x332c92, - 0x333113, - 0x3335cd, - 0x333b8d, - 0x333f0e, - 0x33480e, - 0x334e0c, - 0x3351cc, - 0x33560b, - 0x33668e, - 0x336f92, - 0x338c4c, - 0x3391d0, - 0x34cfd2, - 0x34e08c, - 0x34e74d, - 0x34ea8c, - 0x351591, - 0x35280d, - 0x3546cd, - 0x354cca, - 0x354f4c, - 0x35890c, - 0x35948c, - 0x359e8c, - 0x35df93, - 0x35e710, - 0x35eb10, - 0x35f10d, - 0x35f70c, - 0x360549, - 0x36224d, - 0x362593, - 0x364111, - 0x364913, - 0x36560f, - 0x3659cc, - 0x365ccf, - 0x36608d, - 0x36668f, - 0x366a50, - 0x3674ce, - 0x36b40e, - 0x36ba90, - 0x36d08d, - 0x36da0e, - 0x36dd8c, - 0x36ed53, - 0x37268e, - 0x372c10, - 0x373011, - 0x37344f, - 0x373813, - 0x374fcd, - 0x37530f, - 0x3756ce, - 0x375c50, - 0x376049, - 0x3773d0, - 0x3778cf, - 0x377f4f, - 0x378312, - 0x3792ce, - 0x37a00d, - 0x37a54d, - 0x37a88d, - 0x37bf8d, - 0x37c2cd, - 0x37c610, - 0x37ca0b, - 0x37d24c, - 0x37d5cc, - 0x37dbcc, - 0x37dece, - 0x38d350, - 0x38f7d2, - 0x38fc4b, - 0x39078e, - 0x390b0e, - 0x39138e, - 0x39190b, - 0x64391d96, - 0x39268d, - 0x393214, - 0x393f0d, - 0x3955d5, - 0x3978cd, - 0x39824f, - 0x398e0f, - 0x39c24f, - 0x39c60e, - 0x39c98d, - 0x39e251, - 0x3a084c, - 0x3a0b4c, - 0x3a0e4b, - 0x3a128c, - 0x3a1ccf, - 0x3a2092, - 0x3a2bcd, - 0x3a470c, - 0x3a500c, - 0x3a530d, - 0x3a564f, - 0x3a5a0e, - 0x3a750c, - 0x3a7acd, - 0x3a7e0b, - 0x3a8c4c, - 0x3a954d, - 0x3a988e, - 0x3a9c09, - 0x3abb53, - 0x3ac94d, - 0x3ad04d, - 0x3ad64c, - 0x3ae88e, - 0x3aef8f, - 0x3af34c, - 0x3af64d, - 0x3af98f, - 0x3afd4c, - 0x3b034c, - 0x3b080c, - 0x3b0b0c, - 0x3b35cd, - 0x3b3912, - 0x3b45cc, - 0x3b48cc, - 0x3b4bd1, - 0x3b500f, - 0x3b53cf, - 0x3b5793, - 0x3b6f8e, - 0x3b730f, - 0x3b76cc, - 0x647b7d8e, - 0x3b810f, - 0x3b84d6, - 0x3bae52, - 0x3bcccc, - 0x3bdb8f, - 0x3be20d, - 0x3c94cf, - 0x3c988c, - 0x3c9b8d, - 0x3c9ecd, - 0x3cb4ce, - 0x3cc38c, - 0x3ceecc, - 0x3cf1d0, - 0x3d3d91, - 0x3d41cb, - 0x3d460c, - 0x3d490e, - 0x3d6011, - 0x3d644e, - 0x3d67cd, - 0x3dbc0b, - 0x3dc88f, - 0x3dd454, - 0x23c782, - 0x23c782, - 0x23e083, - 0x23c782, - 0x23e083, - 0x23c782, - 0x203802, - 0x246c45, - 0x3d5d0c, - 0x23c782, - 0x23c782, - 0x203802, - 0x23c782, - 0x29b485, - 0x2b3585, - 0x23c782, - 0x23c782, - 0x201542, - 0x29b485, - 0x32fec9, - 0x363e0c, - 0x23c782, - 0x23c782, - 0x23c782, - 0x23c782, - 0x246c45, - 0x23c782, - 0x23c782, - 0x23c782, - 0x23c782, - 0x201542, - 0x32fec9, - 0x23c782, - 0x23c782, - 0x23c782, - 0x2b3585, - 0x23c782, - 0x2b3585, - 0x363e0c, - 0x3d5d0c, - 0x202703, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21a3c3, - 0x242543, - 0x1d904f, - 0x145988, - 0x1a704, - 0x3dc3, - 0x86808, - 0x1cc203, - 0x2000c2, - 0x65601242, - 0x240983, - 0x224c84, - 0x207083, - 0x384584, - 0x22f7c6, - 0x310c83, - 0x310c44, - 0x2f0b05, - 0x23c803, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x21e2ca, - 0x252b06, - 0x390e8c, - 0x9a048, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x2137c3, - 0x2e2406, - 0x21a3c3, - 0x242543, - 0x2141c3, - 0x2fb03, - 0xac508, - 0x661d2145, - 0x47d47, - 0x139b05, - 0x156c9, - 0x1742, - 0x13a14a, - 0x66fa0505, - 0x139b05, - 0x29907, - 0x6dfc8, - 0x9c4e, - 0x8b392, - 0x9630b, - 0x10d806, - 0x6728d505, - 0x6768d50c, - 0x13d547, - 0x17e707, - 0x12364a, - 0x3be50, - 0x146145, - 0x10fe4b, - 0x79108, - 0x25687, - 0x2490b, - 0x33249, - 0x46e07, - 0x15c087, - 0xc2487, - 0x34a06, - 0x106c8, - 0x67c28886, - 0x47207, - 0x18ec46, - 0x78d8d, - 0xf3c90, - 0x680aac82, - 0xd1288, - 0x40350, - 0x17f5cc, - 0x687825cd, - 0x5a988, - 0x5ae0b, - 0x6b187, - 0x70749, - 0x56306, - 0x9b008, - 0x3ee42, - 0x9218a, - 0x157647, - 0x107c07, - 0xacdc9, - 0xaff88, - 0xf3605, - 0x18d986, - 0x1ba1c6, - 0xfd84e, - 0xaf88e, - 0x3874f, - 0x41a89, - 0xf0c09, - 0x91d0b, - 0xb3b4f, - 0xbd08c, - 0xca18b, - 0x131388, - 0x171887, - 0x197088, - 0xb580b, - 0xb5bcc, - 0xb5fcc, - 0xb63cc, - 0xb66cd, - 0x1b1148, - 0x52e82, - 0x193a49, - 0x112988, - 0x19fe8b, - 0xd5b46, - 0xdda8b, - 0x136acb, - 0xe884a, - 0xea585, - 0xf1210, - 0xf5c86, - 0x184806, - 0x97805, - 0x91487, - 0xe0448, - 0xf92c7, - 0xf9587, - 0x12c807, - 0xc7346, - 0x1cd80a, - 0x99eca, - 0x11ec6, - 0xb130d, - 0x472c8, - 0x115488, - 0x115cc9, - 0xc0545, - 0x1aec8c, - 0xb68cb, - 0x86fc9, - 0x1ccb44, - 0x111949, - 0x111b86, - 0x4cec6, - 0x3c686, - 0x1b82, - 0x365c6, - 0x13dacb, - 0x129187, - 0x11ac47, - 0x1442, - 0xd7445, - 0x27e04, - 0x101, - 0x4fd83, - 0x67a37806, - 0x9b383, - 0x382, - 0x26bc4, - 0xac2, - 0xd3684, - 0x882, - 0x31c2, - 0x16c2, - 0x20f82, - 0x86c2, - 0x8d502, - 0xd42, - 0x167c2, - 0x373c2, - 0x5582, - 0x2a42, - 0x4e782, - 0x32dc3, - 0x942, - 0x3c42, - 0xdec2, - 0x5dc2, - 0x642, - 0x315c2, - 0x6502, - 0x5bc2, - 0xf42, - 0x5c2, - 0x1bc83, - 0x4582, - 0x7882, - 0x49582, - 0x1e42, - 0x2042, - 0x8282, - 0x23502, - 0x17c2, - 0x9e82, - 0x3f82, - 0x6c9c2, - 0x15402, - 0x1a3c3, - 0x602, - 0x30a42, - 0x2902, - 0x1ad42, - 0x1d685, - 0xa882, - 0x14b42, - 0x3d383, - 0x682, - 0xca42, - 0x45c2, - 0x7842, - 0x2f82, - 0x8c2, - 0xc2c2, - 0x1b82, - 0x1805, - 0x68a03802, - 0x68edf283, - 0xf283, - 0x69203802, - 0xf283, - 0x74c47, - 0x201503, - 0x2000c2, - 0x214a83, - 0x232dc3, - 0x228503, - 0x2005c3, - 0x2137c3, - 0x21a3c3, - 0x203dc3, - 0x242543, - 0x29b3c3, - 0xc0584, - 0x19405, - 0x104305, - 0x3a83, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x228503, - 0x23c803, - 0x21a3c3, - 0x203dc3, - 0x1b4103, - 0x242543, - 0x214a83, - 0x232dc3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x200181, - 0x23c803, - 0x21a3c3, - 0x24e283, - 0x242543, - 0x69944, - 0x202703, - 0x214a83, - 0x232dc3, - 0x218bc3, - 0x228503, - 0x2c26c3, - 0x208943, - 0x2a37c3, - 0x216243, - 0x308003, - 0x221dc4, - 0x21a3c3, - 0x242543, - 0x207783, - 0x204244, - 0x24f603, - 0x20dc3, - 0x29cfc3, - 0x328fc8, - 0x2f0e44, - 0x20020a, - 0x235406, - 0x124184, - 0x3a71c7, - 0x21ec8a, - 0x21b489, - 0x3bb287, - 0x3c024a, - 0x202703, - 0x35604b, - 0x216189, - 0x2f4245, - 0x3b0647, - 0x1242, - 0x214a83, - 0x20fcc7, - 0x263bc5, - 0x2cc8c9, - 0x232dc3, - 0x373ec6, - 0x2cb983, - 0xeeb03, - 0x118f86, - 0x98186, - 0x1d3bc7, - 0x212286, - 0x220fc5, - 0x205b47, - 0x316507, - 0x6bf08003, - 0x34e2c7, - 0x23c783, - 0x3d3905, - 0x221dc4, - 0x26f3c8, - 0x385acc, - 0x2b8d05, - 0x2aa446, - 0x20fb87, - 0x3b9887, - 0x3a2a07, - 0x248b48, - 0x317ccf, - 0x21b6c5, - 0x240a87, - 0x28e747, - 0x276e0a, - 0x37b549, - 0x3dd185, - 0x3212ca, - 0xc4ac6, - 0xc0a07, - 0x2cba05, - 0x2f6684, - 0x3d9686, - 0x101406, - 0x37f847, - 0x252d87, - 0x33b388, - 0x218405, - 0x263ac6, - 0x156ec8, - 0x2e3d85, - 0xe3f46, - 0x3268c5, - 0x28ce44, - 0x24a407, - 0x2307ca, - 0x23ab88, - 0x288e06, - 0x137c3, - 0x2ec0c5, - 0x320506, - 0x3bee46, - 0x297706, - 0x23c803, - 0x3a2e47, - 0x28e6c5, - 0x21a3c3, - 0x2e8b0d, - 0x203dc3, - 0x33b488, - 0x213484, - 0x276b05, - 0x2abd06, - 0x205406, - 0x2ac7c7, - 0x25b047, - 0x350ac5, - 0x242543, - 0x271d87, - 0x371989, - 0x2708c9, - 0x384a4a, - 0x215542, - 0x3d38c4, - 0x2fb304, - 0x2f7c07, - 0x2f7f48, - 0x2fa3c9, - 0x3d2789, - 0x2fadc7, - 0x109049, - 0x362f06, - 0xfd5c6, - 0x2fe7c4, - 0x22cf8a, - 0x302448, - 0x305389, - 0x305946, - 0x2bc745, - 0x23aa48, - 0x2d5dca, - 0x32bf03, - 0x2043c6, - 0x2faec7, - 0x35a785, - 0x3b4045, - 0x2432c3, - 0x23e804, - 0x227b45, - 0x2848c7, - 0x2ff405, - 0x2ff846, - 0x111e85, - 0x2071c3, - 0x2071c9, - 0x2768cc, - 0x2c61cc, - 0x3444c8, - 0x2ab3c7, - 0x30d588, - 0x10e747, - 0x30eaca, - 0x30f18b, - 0x2162c8, - 0x205508, - 0x22b686, - 0x302bc5, - 0x25d70a, - 0x2df2c5, - 0x233442, - 0x2d44c7, - 0x253c46, - 0x376785, - 0x310949, - 0x2d0405, - 0x372185, - 0x3c2409, - 0x320446, - 0x201348, - 0x3d39c3, - 0x20aa46, - 0x275c86, - 0x31cd05, - 0x31cd09, - 0x2c4709, - 0x25d487, - 0x11cb84, - 0x31cb87, - 0x3d2689, + 0x214048, + 0x361a85, + 0x21e147, + 0x225209, + 0x2afa4a, + 0x266f07, + 0x266f0c, + 0x267c46, + 0x23df09, + 0x248085, + 0x2d2ec8, + 0x202443, + 0x2f2d05, + 0x3c0e45, + 0x282fc7, + 0x63201242, + 0x2f9b87, + 0x2f0906, + 0x3862c6, + 0x2f2586, + 0x229e86, + 0x23be08, + 0x27e105, + 0x2d2047, + 0x2d204d, + 0x20ee43, + 0x3dcb45, + 0x276b87, + 0x2f9ec8, + 0x276745, + 0x216bc8, + 0x382e86, + 0x29c107, + 0x2d6945, + 0x39cc86, + 0x399445, + 0x21ef4a, + 0x301b46, + 0x274587, + 0x2ce285, + 0x310687, + 0x35a584, + 0x3b9e06, + 0x312c45, + 0x33544b, + 0x39b609, + 0x281cca, + 0x226788, + 0x393f88, + 0x31408c, + 0x3d8d07, + 0x31c848, + 0x31ecc8, + 0x32b9c5, + 0x35c18a, + 0x35f4c9, + 0x63600ec2, + 0x20b086, + 0x260d44, + 0x2fc549, + 0x240e89, + 0x246907, + 0x27bfc7, + 0x29cd49, + 0x33e348, + 0x33e34f, + 0x22d606, + 0x2e6ccb, + 0x256845, + 0x256847, + 0x381cc9, + 0x21fe06, + 0x3164c7, + 0x2eb805, + 0x232004, + 0x307ec6, + 0x206244, + 0x3ba247, + 0x3792c8, + 0x63b0d808, + 0x30fa05, + 0x30fb47, + 0x3532c9, + 0x20c4c4, + 0x241948, + 0x63e653c8, + 0x2e8a84, + 0x2f6dc8, + 0x25f184, + 0x206109, + 0x220c85, + 0x6422dc42, + 0x22d645, + 0x2dfd45, + 0x2600c8, + 0x234c07, + 0x646008c2, + 0x3c7a85, + 0x2e04c6, + 0x24d186, + 0x321708, + 0x31f148, + 0x33ea86, + 0x34a046, + 0x30a149, + 0x386206, + 0x21fccb, + 0x229d05, + 0x2af286, + 0x368048, + 0x34ae46, + 0x2bc246, + 0x2178ca, + 0x2e1b0a, + 0x23eb45, + 0x29c787, + 0x27a146, + 0x64a034c2, + 0x276cc7, + 0x367145, + 0x305304, + 0x305305, + 0x2f4cc6, + 0x278807, + 0x21ac85, + 0x240f44, + 0x2c3708, + 0x2bc305, + 0x37a987, + 0x3808c5, 0x21ee85, - 0x39f48, - 0x349845, - 0x353885, - 0x39b489, - 0x204b42, - 0x357204, - 0x209282, - 0x204582, - 0x2ed985, - 0x323f08, - 0x2c0485, - 0x2ced43, - 0x2ced45, - 0x2e03c3, - 0x20a742, - 0x2b4384, - 0x269f03, + 0x245744, + 0x245749, + 0x3015c8, + 0x359586, + 0x358846, + 0x363f06, + 0x64fcfc08, + 0x3d8b87, + 0x31474d, + 0x314f0c, + 0x315509, + 0x315749, + 0x65379942, + 0x3d7403, + 0x20e483, + 0x39b845, + 0x3af90a, + 0x33e946, + 0x2365c5, + 0x31e244, + 0x31e24b, + 0x33384c, + 0x33410c, + 0x334415, + 0x335e0d, + 0x337e8f, + 0x338252, + 0x3386cf, + 0x338a92, + 0x338f13, + 0x3393cd, + 0x33998d, + 0x339d0e, + 0x33a60e, + 0x33ac0c, + 0x33afcc, + 0x33b40b, + 0x33be8e, + 0x33c792, + 0x33e70c, + 0x3403d0, + 0x34e4d2, + 0x34f54c, + 0x34fc0d, + 0x34ff4c, + 0x3524d1, + 0x35398d, + 0x35ae4d, + 0x35b44a, + 0x35b6cc, + 0x35e60c, + 0x35ee0c, + 0x35f70c, + 0x362e93, + 0x363610, + 0x363a10, + 0x36460d, + 0x364c0c, + 0x365a49, + 0x3697cd, + 0x369b13, + 0x36b451, + 0x36bc53, + 0x36c94f, + 0x36cd0c, + 0x36d00f, + 0x36d3cd, + 0x36d9cf, + 0x36dd90, + 0x36e80e, + 0x37198e, + 0x3722d0, + 0x37318d, + 0x373b0e, + 0x373e8c, + 0x374fd3, + 0x37768e, + 0x377c10, + 0x378011, + 0x37844f, + 0x378813, + 0x3794cd, + 0x37980f, + 0x379bce, + 0x37a150, + 0x37a549, + 0x37bc90, + 0x37c18f, + 0x37c80f, + 0x37cbd2, + 0x37f68e, + 0x3804cd, + 0x380a0d, + 0x380d4d, + 0x381f0d, + 0x38224d, + 0x382590, + 0x38298b, + 0x3831cc, + 0x38354c, + 0x383b4c, + 0x383e4e, + 0x393650, + 0x395112, + 0x39558b, + 0x395f8e, + 0x39630e, + 0x396b8e, + 0x39710b, + 0x65797596, + 0x397e8d, + 0x398a14, + 0x39970d, + 0x39c255, + 0x39ea0d, + 0x39f38f, + 0x39fb4f, + 0x3a2bcf, + 0x3a2f8e, + 0x3a330d, + 0x3a4891, + 0x3a7ecc, + 0x3a81cc, + 0x3a84cb, + 0x3a890c, + 0x3a904f, + 0x3a9412, + 0x3aa1cd, + 0x3abe8c, + 0x3acc4c, + 0x3acf4d, + 0x3ad28f, + 0x3ad64e, + 0x3af5cc, + 0x3afb8d, + 0x3afecb, + 0x3b078c, + 0x3b108d, + 0x3b13ce, + 0x3b1749, + 0x3b2dd3, + 0x3b688d, + 0x3b6f8d, + 0x3b758c, + 0x3b7c0e, + 0x3b830f, + 0x3b86cc, + 0x3b89cd, + 0x3b8d0f, + 0x3b90cc, + 0x3ba40c, + 0x3ba8cc, + 0x3babcc, + 0x3bbb8d, + 0x3bbed2, + 0x3bc64c, + 0x3bc94c, + 0x3bcc51, + 0x3bd08f, + 0x3bd44f, + 0x3bd813, + 0x3be60e, + 0x3be98f, + 0x3bed4c, + 0x65bbf40e, + 0x3bf78f, + 0x3bfb56, + 0x3c1bd2, + 0x3c440c, + 0x3c4d8f, + 0x3c540d, + 0x3cec8f, + 0x3cf04c, + 0x3cf34d, + 0x3cf68d, + 0x3d0d4e, + 0x3d19cc, + 0x3d420c, + 0x3d4510, + 0x3d6791, + 0x3d6bcb, + 0x3d700c, + 0x3d730e, + 0x3d91d1, + 0x3d960e, + 0x3d998d, + 0x3de2cb, + 0x3debcf, + 0x3dfa54, + 0x23ca82, + 0x23ca82, + 0x203183, + 0x23ca82, + 0x203183, + 0x23ca82, + 0x201082, + 0x2484c5, + 0x3d8ecc, + 0x23ca82, + 0x23ca82, + 0x201082, + 0x23ca82, + 0x29c945, + 0x2afa45, + 0x23ca82, + 0x23ca82, + 0x208a02, + 0x29c945, + 0x336689, + 0x36b14c, + 0x23ca82, + 0x23ca82, + 0x23ca82, + 0x23ca82, + 0x2484c5, + 0x23ca82, + 0x23ca82, + 0x23ca82, + 0x23ca82, + 0x208a02, + 0x336689, + 0x23ca82, + 0x23ca82, + 0x23ca82, + 0x2afa45, + 0x23ca82, + 0x2afa45, + 0x36b14c, + 0x3d8ecc, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x217fc3, + 0x23e083, + 0x1e14cf, + 0x1b4508, + 0x6704, + 0x5803, + 0x8efc8, + 0x1d1843, + 0x2000c2, + 0x66a12402, + 0x241283, + 0x25a584, + 0x2033c3, + 0x38a0c4, + 0x231346, + 0x222743, + 0x3d2484, + 0x3517c5, + 0x23cb03, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x226e0a, + 0x2509c6, + 0x39668c, + 0xae888, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x215f83, + 0x2e4806, + 0x217fc3, + 0x23e083, + 0x216983, + 0xe783, + 0xaeec8, + 0x675dc3c5, + 0x49647, + 0x146bc5, + 0xcd89, + 0x8c02, + 0x1c73ca, + 0x683a7b85, + 0x146bc5, + 0x1683c7, + 0x74f88, + 0xb74e, + 0x90d92, + 0x123bcb, + 0x110ac6, + 0x686bd285, + 0x68abf28c, + 0x149147, + 0x178d87, + 0x127eca, + 0x3c290, + 0x1645, + 0xc634b, + 0x10f508, + 0x35cc7, + 0xbc3cb, + 0x34449, + 0x48687, + 0x161347, + 0xef347, + 0x35c06, + 0xec88, + 0x69036fc6, + 0x3dc87, + 0x176b06, + 0x4efcd, + 0xe9890, + 0x694293c2, + 0x7f248, + 0x8c550, + 0x184e8c, + 0x69b8794d, + 0x5a388, + 0x5a80b, + 0x71007, + 0x96d89, + 0x56546, + 0x9bd48, + 0x5b542, + 0x1b21ca, + 0x65a87, + 0xb4e07, + 0xafcc9, + 0xb3108, + 0xf48c5, + 0x193c86, + 0x1c2e06, + 0xffb4e, + 0xef90e, + 0x18ee0f, + 0x33449, + 0x860c9, + 0x1b1d4b, + 0xb538f, + 0xc470c, + 0xcfe0b, + 0x11d1c8, + 0x16f747, + 0x194c88, + 0x1a8c8b, + 0xb920c, + 0xb960c, + 0xb9a0c, + 0xb9d0d, + 0x1bb208, + 0x50d42, + 0x199249, + 0x15d048, + 0x1de00b, + 0xd7e86, + 0xdfe8b, + 0x13c2cb, + 0xeaf4a, + 0xec7c5, + 0xf1e10, + 0xf6a46, + 0x155146, + 0x1b5a05, + 0x19dfc7, + 0xe2608, + 0xfadc7, + 0xfb087, + 0x1416c7, + 0xccec6, + 0x1b9b0a, + 0xae70a, + 0x13a06, + 0xb4bcd, + 0x3dd48, + 0x118088, + 0x1188c9, + 0xc7c05, + 0x1b800c, + 0xb9f0b, + 0x15ca49, + 0x1d1204, + 0x114389, + 0x1145c6, + 0x156786, + 0x3c986, + 0x72c2, + 0x134c46, + 0x1496cb, + 0x11e987, + 0x11eb47, + 0x3602, + 0xd9785, + 0x2de44, + 0x101, + 0x506c3, + 0x68e6a646, + 0x9c0c3, + 0x382, + 0x2b104, + 0xac2, + 0x4cd44, + 0x882, + 0x7282, + 0x6c02, + 0x10bf02, + 0xcf02, + 0xbd282, + 0xd42, + 0x161e82, + 0x37402, + 0xda02, + 0xf982, + 0x4e682, + 0x33fc3, + 0x942, + 0x31c2, + 0xfa02, + 0x91c2, + 0x642, + 0x32702, + 0xb5c2, + 0x8fc2, + 0xf782, + 0x5c2, + 0x191c3, + 0x4b82, + 0x22c2, + 0x4b202, + 0x6902, + 0x2702, + 0xa682, + 0x4202, + 0x8c82, + 0xb982, + 0x193b42, + 0x720c2, + 0xcac2, + 0x17fc3, + 0x602, + 0x3bec2, + 0x2542, + 0x35c2, + 0x26685, + 0x4fc2, + 0x42c42, + 0x3d583, + 0x682, + 0xd782, + 0x2442, + 0xab02, + 0xee42, + 0x8c2, + 0x4642, + 0x72c2, + 0x8cc5, + 0x69e01082, + 0x6a2e82c3, + 0x1ac3, + 0x6a601082, + 0x1ac3, + 0x7a807, + 0x2089c3, + 0x2000c2, + 0x22ea43, + 0x233fc3, + 0x280203, + 0x2005c3, + 0x215f83, + 0x217fc3, + 0x205803, + 0x23e083, + 0x2bd443, + 0xc7c44, + 0x16acc5, + 0x105085, + 0x10103, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x280203, + 0x23cb03, + 0x217fc3, + 0x205803, + 0x1c0443, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x200181, + 0x23cb03, + 0x217fc3, + 0x24dfc3, + 0x23e083, + 0x2f44, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x275243, + 0x280203, + 0x2d2a83, + 0x2381c3, + 0x2a49c3, + 0x20d903, + 0x266a83, + 0x20e704, + 0x217fc3, + 0x23e083, + 0x20aa43, + 0x207d44, + 0x25cc83, + 0x33f03, + 0x238f43, + 0x32dac8, + 0x2a1184, + 0x20020a, + 0x385986, + 0x1530c4, + 0x3bc307, + 0x21bfca, + 0x22d4c9, + 0x3c7247, + 0x3c9c8a, + 0x24ac43, + 0x309e0b, + 0x20d849, + 0x2fde05, + 0x3ba707, + 0x12402, + 0x22ea43, + 0x2264c7, + 0x224685, + 0x2e9209, + 0x233fc3, + 0x23a086, + 0x2d3383, + 0xf0983, + 0x11bf06, + 0x8886, + 0x226c7, + 0x228c86, + 0x30bf45, + 0x208f47, + 0x319107, + 0x6d266a83, + 0x34f787, + 0x23ca83, + 0x21df05, + 0x20e704, + 0x275f48, + 0x3c410c, + 0x2be385, + 0x2ac086, + 0x226387, + 0x3c1447, + 0x269207, + 0x277008, + 0x31b18f, + 0x22d705, + 0x241387, + 0x211647, + 0x3caf0a, + 0x340009, + 0x32e945, + 0x34ef0a, + 0xdd286, + 0xc8087, + 0x2d3405, + 0x2f83c4, + 0x3e1b06, + 0x14e1c6, + 0x385107, + 0x250c47, + 0x3c5f48, + 0x212a05, + 0x224586, + 0x168688, + 0x2677c5, + 0x67986, + 0x2f5b85, + 0x267704, + 0x3c2387, + 0x23bc4a, + 0x2a6688, + 0x25f986, + 0x15f83, + 0x2ee705, + 0x354bc6, + 0x3c9406, + 0x3b5906, + 0x23cb03, + 0x3aa447, + 0x2115c5, + 0x217fc3, + 0x2eb20d, + 0x205803, + 0x3c6048, + 0x215c44, + 0x27c885, + 0x2ad606, + 0x358146, + 0x2af187, + 0x2a4a07, + 0x28dfc5, + 0x23e083, + 0x36f847, + 0x38a449, + 0x325009, + 0x3624ca, + 0x201b42, + 0x21dec4, + 0x304f84, + 0x2f9707, + 0x2f9a48, + 0x2fbfc9, + 0x3dca09, + 0x2fc9c7, + 0x108589, + 0x229446, + 0xff8c6, + 0x300ac4, + 0x22efca, + 0x304b08, + 0x306109, + 0x3066c6, + 0x2c3cc5, + 0x2a6548, + 0x2d810a, + 0x204343, + 0x207ec6, + 0x2fcac7, + 0x30f6c5, + 0x3c0385, + 0x243cc3, + 0x2ddf84, + 0x2259c5, + 0x28c247, + 0x301705, + 0x2f72c6, + 0x121dc5, + 0x288d83, + 0x2bb9c9, + 0x27c64c, + 0x2cbd4c, + 0x37f088, + 0x2a9f87, + 0x310848, + 0x111507, + 0x31188a, + 0x311f4b, + 0x20d988, + 0x358248, + 0x2524c6, + 0x31fdc5, + 0x25c4ca, + 0x2e8305, + 0x22dc42, + 0x2d6807, + 0x269f86, + 0x37b205, + 0x3d2189, + 0x27e3c5, + 0x388a05, + 0x229a09, + 0x325a46, + 0x37de88, + 0x270103, + 0x228dc6, + 0x3d2506, + 0x32dc85, + 0x32dc89, + 0x2ca889, + 0x25c247, + 0x120f44, + 0x320f47, + 0x3dc909, + 0x21c1c5, + 0x39ec8, + 0x37e245, + 0x371145, + 0x3b3609, + 0x201802, + 0x366984, + 0x20d2c2, + 0x204b82, + 0x320245, + 0x352e48, + 0x2c7b45, + 0x2d5183, + 0x2d5185, + 0x2e2583, + 0x20e202, + 0x2b5bc4, + 0x273cc3, 0x200a82, - 0x3b17c4, - 0x309703, - 0x20cb42, - 0x2c0503, - 0x211e44, - 0x305ac3, - 0x255544, - 0x205142, - 0x2140c3, - 0x21ab03, - 0x2071c2, - 0x294ec2, - 0x2c4549, - 0x205b02, - 0x28bec4, - 0x206542, - 0x23a8c4, - 0x362ec4, - 0x3b4384, - 0x201b82, - 0x22b2c2, - 0x22db03, - 0x29cec3, - 0x3269c4, - 0x3aa684, - 0x2dae84, - 0x2ea884, - 0x31bcc3, - 0x312743, - 0x2c4a44, - 0x31f184, - 0x31f2c6, - 0x21d642, - 0x1242, - 0x41483, - 0x201242, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x6c05, + 0x2c1704, + 0x308c43, + 0x204ac2, + 0x2c7bc3, + 0x213984, + 0x306843, + 0x253cc4, + 0x207742, + 0x216883, + 0x218e43, + 0x2018c2, + 0x25cdc2, + 0x2ca6c9, + 0x208f02, + 0x291bc4, + 0x208742, + 0x3a9e44, + 0x229404, + 0x22aac4, + 0x2072c2, + 0x23d882, + 0x32aa83, + 0x26ac43, + 0x270184, + 0x2c7504, + 0x2ecac4, + 0x2fcc44, + 0x3210c3, + 0x35ce03, + 0x2dd204, + 0x3252c4, + 0x325406, + 0x226642, + 0x12402, + 0x41d83, + 0x212402, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x110c5, 0x2000c2, - 0x202703, - 0x214a83, - 0x232dc3, - 0x209b03, - 0x308003, - 0x221dc4, - 0x2c4804, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x2141c3, - 0x2fedc4, - 0x297a83, - 0x2ad843, - 0x37a2c4, - 0x349646, - 0x210603, - 0x139b05, - 0x17e707, - 0x2d2c43, - 0x6da46f08, - 0x2532c3, - 0x2bb143, - 0x25cc03, - 0x2137c3, - 0x3c0ac5, - 0x1b0603, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x20a883, - 0x22ee03, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21bc83, - 0x21a3c3, - 0x2801c4, - 0x1b4103, - 0x242543, - 0x24a004, - 0x139b05, - 0x2c8f85, - 0x17e707, - 0x201242, - 0x2052c2, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x203983, + 0x266a83, + 0x20e704, + 0x2ca984, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x216983, + 0x3010c4, + 0x32f643, + 0x2b0743, + 0x380784, + 0x37e046, + 0x20ebc3, + 0x146bc5, + 0x178d87, + 0x226dc3, + 0x6ee10c08, + 0x24cbc3, + 0x2c1183, + 0x21df43, + 0x215f83, + 0x3c7985, + 0x1ba6c3, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x210043, + 0x230743, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x2191c3, + 0x217fc3, + 0x2878c4, + 0x1c0443, + 0x23e083, + 0x25d244, + 0x146bc5, + 0x2ce8c5, + 0x178d87, + 0x212402, + 0x204542, 0x200382, - 0x208482, - 0x3dc3, + 0x203182, + 0x5803, 0x2003c2, - 0x4f04, - 0x214a83, - 0x235b44, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x20e2c3, - 0x2d3684, - 0x9a048, - 0x214a83, - 0x203dc3, - 0x3a83, - 0x122504, - 0x24c0c4, - 0x9a048, - 0x214a83, - 0x24d9c4, - 0x221dc4, - 0x203dc3, - 0x204042, - 0x1b4103, - 0x242543, - 0x22b983, - 0x3e804, - 0x208805, - 0x233442, - 0x325e43, - 0x68b49, - 0xe5986, - 0x149948, + 0x157c44, + 0x22ea43, + 0x236704, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x5803, + 0x23e083, + 0x208503, + 0x24cd44, + 0xae888, + 0x22ea43, + 0x205803, + 0x10103, + 0x126d84, + 0x241ec4, + 0xae888, + 0x22ea43, + 0x24d704, + 0x20e704, + 0x205803, + 0x209282, + 0x1c0443, + 0x23e083, + 0x235403, + 0xddf84, + 0x37b845, + 0x22dc42, + 0x32a143, + 0x2149, + 0xe7546, + 0x17e348, 0x2000c2, - 0x9a048, - 0x201242, - 0x232dc3, - 0x308003, + 0xae888, + 0x212402, + 0x233fc3, + 0x266a83, 0x2005c2, - 0x3dc3, - 0x242543, - 0x7c42, + 0x5803, + 0x23e083, + 0xa882, 0x82, 0xc2, - 0x1c0407, - 0x142c09, - 0x7aec3, - 0x9a048, - 0x20f43, - 0x713233c7, - 0x14a83, - 0x944c8, - 0x32dc3, - 0x108003, - 0x1ab9c6, - 0x1bc83, - 0x92788, - 0xcae48, - 0xcff06, - 0x3c803, - 0xd8cc8, - 0x44b83, - 0x714eb886, - 0xf1c05, - 0x32fc7, - 0x1a3c3, - 0x11003, - 0x42543, - 0xeb02, - 0x17cd0a, - 0x2cc3, - 0xeda43, - 0x10a104, - 0x117acb, - 0x118088, - 0x90602, - 0x14540c7, - 0x15636c7, - 0x14cee08, - 0x14cf583, - 0x143acb, - 0xb342, - 0x12bcc7, - 0x11b504, + 0x1c9e47, + 0x14b509, + 0x3043, + 0xae888, + 0x10bec3, + 0x72727c47, + 0x2ea43, + 0xaf88, + 0x33fc3, + 0x66a83, + 0x3fec6, + 0x191c3, + 0x56288, + 0xd0ac8, + 0x7dec6, + 0x729a7285, + 0x3cb03, + 0xdb008, + 0x3fa83, + 0x72cedbc6, + 0xf2ec5, + 0x124d04, + 0x341c7, + 0x17fc3, + 0x3443, + 0x3e083, + 0x1b02, + 0x182c8a, + 0x9c43, + 0x732c3f4c, + 0x120303, + 0x5d884, + 0x11af8b, + 0x11b548, + 0x95f42, + 0x17ff03, + 0x1454747, + 0x15b4247, + 0x14d5248, + 0x157ff03, + 0x18b7c8, + 0x156ecb, + 0x10382, + 0x131247, + 0x181584, 0x2000c2, - 0x201242, - 0x235b44, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x2137c3, - 0x21a3c3, - 0x242543, - 0x215d43, - 0x20e2c3, - 0x2fb03, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, + 0x212402, + 0x236704, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x215f83, + 0x217fc3, + 0x23e083, + 0x20d403, + 0x208503, + 0xe783, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, 0x602, - 0x3a83, - 0x108003, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x2137c3, - 0x21a3c3, - 0x242543, - 0x20c782, + 0x10103, + 0x66a83, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x215f83, + 0x217fc3, + 0x23e083, + 0x21fcc2, 0x2000c1, 0x2000c2, 0x200201, - 0x332182, - 0x9a048, - 0x21ca05, + 0x337f82, + 0xae888, + 0x21aa05, 0x200101, - 0x14a83, - 0x2fe44, - 0x201301, + 0x2ea43, + 0x319c4, + 0x201381, 0x200501, - 0x205dc1, - 0x246bc2, - 0x387fc4, - 0x246bc3, + 0x201281, + 0x248442, + 0x38e084, + 0x248443, 0x200041, 0x200801, 0x200181, 0x200701, - 0x302fc7, - 0x30e38f, - 0x3ccc06, + 0x35c3c7, + 0x30fccf, + 0x39af46, 0x2004c1, - 0x322546, + 0x326dc6, 0x200bc1, 0x200581, - 0x3affce, + 0x3de50e, 0x2003c1, - 0x242543, + 0x23e083, 0x200a81, - 0x34c105, - 0x20eb02, - 0x2431c5, + 0x32b305, + 0x201b02, + 0x243bc5, 0x200401, 0x200741, 0x2007c1, - 0x233442, + 0x22dc42, 0x200081, - 0x201341, - 0x204f01, - 0x201b41, - 0x201441, - 0x50849, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x214903, - 0x214a83, - 0x308003, - 0x90548, - 0x23c803, - 0x21a3c3, - 0x7283, - 0x242543, - 0x14f62c8, - 0x1e0603, - 0xa788, - 0x139b05, - 0x9a048, - 0x3dc3, - 0x139b05, - 0xcd184, - 0xd1488, - 0x455c4, - 0xcf487, - 0xd3b05, - 0x50849, - 0x11d287, - 0x14f62ca, - 0x9a048, - 0x1b4103, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x220dc3, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x2e3504, - 0x242543, - 0x24f8c5, - 0x2d0204, - 0x214a83, - 0x232dc3, - 0x308003, - 0x209e82, - 0x21a3c3, - 0x242543, - 0xe2c3, - 0xac60a, - 0xe8006, - 0x102804, - 0x122046, - 0x202703, - 0x214a83, - 0x232dc3, - 0x308003, - 0x21a3c3, - 0x242543, - 0x201242, - 0x214a83, - 0x2303c9, - 0x232dc3, - 0x2aa909, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x78a84, - 0x3dc3, - 0x242543, - 0x2fe5c8, - 0x23c207, - 0x208805, - 0xdbc48, - 0x1d4408, - 0x1c0407, - 0xf81ca, - 0x6f98b, - 0x122787, - 0x3f888, - 0xd174a, - 0xf648, - 0x142c09, - 0x27a07, - 0x1fa87, - 0x3ec8, - 0x944c8, - 0x40d4f, - 0x3ad45, - 0x947c7, - 0x1ab9c6, - 0x3cd87, - 0x1dd2c6, - 0x92788, - 0x99786, - 0x1147, - 0x2fc9, - 0x18ab07, - 0x179dc9, - 0xc2749, - 0xc8d06, - 0xcae48, - 0xdbf05, - 0x7b74a, - 0xd8cc8, - 0x44b83, - 0xe07c8, - 0x32fc7, - 0x95d05, - 0x51590, - 0x11003, - 0x1b4103, - 0x2e47, - 0x1acc5, - 0xf9888, - 0x66605, - 0xeda43, - 0x1cb7c8, - 0xee06, - 0x32109, - 0xb2b87, - 0x68e0b, - 0x6cc44, - 0x111444, - 0x117acb, - 0x118088, - 0x118e87, - 0x139b05, - 0x214a83, - 0x232dc3, - 0x228503, - 0x242543, - 0x23e343, - 0x308003, - 0x1b4103, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x91e4b, + 0x207d01, + 0x20a8c1, + 0x202341, + 0x201c41, + 0x51709, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x217c83, + 0x22ea43, + 0x266a83, + 0x95e88, + 0x23cb03, + 0x217fc3, + 0x91043, + 0x23e083, + 0x76ef8008, + 0x1e0f83, + 0xff48, + 0x10402, + 0xb9c3, + 0x293c2, + 0x72c2, + 0x146bc5, + 0xae888, + 0x11fe87, + 0x5803, + 0x146bc5, + 0x175d84, + 0x7f448, + 0x46d04, + 0x17fe07, + 0x1c4104, + 0xd5e45, + 0x51709, + 0x1424c7, + 0x5aa4a, + 0x14f800a, + 0xae888, + 0x1c0443, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x233f03, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x2e5904, + 0x23e083, + 0x24a845, + 0x27e1c4, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20b982, + 0x217fc3, + 0x23e083, + 0x8503, + 0xaefca, + 0xea706, + 0x11fa04, + 0x1268c6, + 0x24ac43, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x217fc3, + 0x23e083, + 0x212402, + 0x22ea43, + 0x231f49, + 0x233fc3, + 0x2ac549, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x81004, + 0x5803, + 0x23e083, + 0x3008c8, + 0x239307, + 0x37b845, + 0xde248, + 0x1d6e08, + 0x1c9e47, + 0xf9cca, + 0x7650b, + 0x127007, + 0x40488, + 0x7f70a, + 0x25e48, + 0x14b509, + 0x25887, + 0x14dcc7, + 0x1b5208, + 0xaf88, + 0x4164f, + 0xa6845, + 0x148647, + 0x3fec6, + 0x36487, + 0x12ea86, + 0x56288, + 0x9a346, + 0x17dc87, + 0x1c1989, + 0x1cd6c7, + 0x19c009, + 0xc9049, + 0xce646, + 0xd0ac8, + 0xde505, + 0x8350a, + 0xdb008, + 0x3fa83, + 0xe2988, + 0x341c7, + 0x156b05, + 0x61950, + 0x3443, + 0x1c0443, + 0x17db07, + 0x2cd05, + 0xfb388, + 0x6db85, + 0x120303, + 0x1d1048, + 0xb2c06, + 0x33249, + 0xb6f47, + 0x240b, + 0x72344, + 0x113c44, + 0x11af8b, + 0x11b548, + 0x11be07, + 0x146bc5, + 0x22ea43, + 0x233fc3, + 0x280203, + 0x23e083, + 0x23e883, + 0x266a83, + 0x1c0443, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x1b1e8b, 0x2000c2, - 0x201242, - 0x242543, + 0x212402, + 0x23e083, 0xd42, - 0x9e82, - 0x7782, - 0x9a048, - 0x1b3089, - 0x1242, + 0xb982, + 0x83c2, + 0xae888, + 0x1357c9, + 0x18b7c8, + 0x12402, 0x2000c2, - 0x201242, + 0x212402, 0x200382, 0x2005c2, - 0x210942, - 0x21a3c3, - 0x13f246, + 0x204482, + 0x217fc3, + 0x14a9c6, 0x2003c2, - 0x3e804, + 0xddf84, 0x2000c2, - 0x202703, - 0x201242, - 0x214a83, - 0x232dc3, + 0x24ac43, + 0x212402, + 0x22ea43, + 0x233fc3, 0x200382, - 0x308003, - 0x21bc83, - 0x23c803, - 0x219a04, - 0x21a3c3, - 0x2125c3, - 0x3dc3, - 0x242543, - 0x30a104, - 0x207783, - 0x308003, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x203dc3, - 0x242543, - 0x3bd187, - 0x214a83, - 0x27b0c7, - 0x397206, - 0x216c83, - 0x21bb43, - 0x308003, - 0x206c03, - 0x221dc4, - 0x28a404, - 0x3383c6, - 0x213a43, - 0x21a3c3, - 0x242543, - 0x24f8c5, - 0x2af384, - 0x323b43, - 0x2ce043, - 0x2d44c7, - 0x2cd845, - 0x68703, - 0x214a83, - 0x232dc3, - 0x308003, - 0x23c803, - 0x21a3c3, - 0x6e544, - 0x242543, - 0x14583, - 0x7c30988c, - 0x53547, - 0xe4846, - 0x91487, - 0x67f05, - 0x202b02, - 0x247403, - 0x214f03, - 0x202703, - 0x7ce14a83, - 0x208c02, - 0x232dc3, - 0x207083, - 0x308003, - 0x221dc4, - 0x2059c3, - 0x21b6c3, - 0x23c803, - 0x219a04, - 0x7d20ce02, - 0x21a3c3, - 0x242543, - 0x2308c3, - 0x21bd03, - 0x21a443, - 0x20c782, - 0x207783, - 0x9a048, - 0x308003, - 0x3a83, - 0x2135c4, - 0x202703, - 0x201242, - 0x214a83, - 0x235b44, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x21bc83, - 0x3473c4, - 0x306c44, - 0x2e2406, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x2141c3, - 0x253c46, - 0x34c8b, - 0x28886, - 0xec90a, - 0x11b94a, - 0x9a048, - 0x2136c4, - 0x7e614a83, - 0x2026c4, - 0x232dc3, - 0x270744, - 0x308003, - 0x2f3983, - 0x23c803, - 0x21a3c3, - 0x1b4103, - 0x242543, - 0x4cbc3, - 0x347f8b, - 0x3ca20a, - 0x3e010c, - 0xebe48, + 0x266a83, + 0x2191c3, + 0x23cb03, + 0x21e484, + 0x217fc3, + 0x213cc3, + 0x5803, + 0x23e083, + 0x25d884, + 0x20aa43, + 0x266a83, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x205803, + 0x23e083, + 0x3c48c7, + 0x22ea43, + 0x282e87, + 0x394e06, + 0x208483, + 0x20fa03, + 0x266a83, + 0x204903, + 0x20e704, + 0x28f784, + 0x32bac6, + 0x208243, + 0x217fc3, + 0x23e083, + 0x24a845, + 0x2b21c4, + 0x3283c3, + 0x356703, + 0x2d6807, + 0x355f05, + 0x1d03, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x23cb03, + 0x217fc3, + 0x75504, + 0x23e083, + 0x16d43, + 0x7e308dcc, + 0x4e803, + 0x192c07, + 0xe6946, + 0x19dfc7, + 0x157585, + 0x222b02, + 0x23de83, + 0x20c5c3, + 0x24ac43, + 0x7ee2ea43, + 0x204302, + 0x233fc3, + 0x2033c3, + 0x266a83, + 0x20e704, + 0x3433c3, + 0x22d703, + 0x23cb03, + 0x21e484, + 0x7f216102, + 0x217fc3, + 0x23e083, + 0x204ac3, + 0x219243, + 0x218043, + 0x21fcc2, + 0x20aa43, + 0xae888, + 0x266a83, + 0x10103, + 0x215d84, + 0x24ac43, + 0x212402, + 0x22ea43, + 0x236704, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x2191c3, + 0x33f584, + 0x217544, + 0x2e4806, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x216983, + 0x269f86, + 0x3a9cb, + 0x36fc6, + 0xbd84a, + 0x11f48a, + 0xae888, + 0x215e84, + 0x8062ea43, + 0x37e504, + 0x233fc3, + 0x296d84, + 0x266a83, + 0x2f4c43, + 0x23cb03, + 0x217fc3, + 0x1c0443, + 0x23e083, + 0x54543, + 0x34a60b, + 0x3cf9ca, + 0x3e0a8c, + 0xee488, 0x2000c2, - 0x201242, + 0x212402, 0x200382, - 0x22d805, - 0x221dc4, - 0x209e82, - 0x23c803, - 0x306c44, - 0x208482, + 0x22f845, + 0x20e704, + 0x20b982, + 0x23cb03, + 0x217544, + 0x203182, 0x2003c2, - 0x2090c2, - 0x20c782, - 0x2703, - 0x15702, - 0x2cb209, - 0x365308, - 0x307e89, - 0x2073c9, - 0x20b40a, - 0x210f0a, - 0x206082, - 0x2167c2, - 0x1242, - 0x214a83, - 0x22ba02, - 0x240c46, - 0x377dc2, - 0x208d42, - 0x26fd0e, - 0x21410e, - 0x27e307, - 0x21a347, - 0x24dc82, - 0x232dc3, - 0x308003, - 0x210d82, + 0x208502, + 0x21fcc2, + 0x4ac43, + 0xcdc2, + 0x2d0e89, + 0x36c648, + 0x266909, + 0x213d49, + 0x2184ca, + 0x30aaca, + 0x209482, + 0x361e82, + 0x12402, + 0x22ea43, + 0x22c982, + 0x241546, + 0x37c682, + 0x2013c2, + 0x27688e, + 0x2168ce, + 0x217f47, + 0x211c42, + 0x233fc3, + 0x266a83, + 0x20f342, 0x2005c2, - 0x1bac3, - 0x235d4f, - 0x21fb02, - 0x2b8887, - 0x3520c7, - 0x2bc287, - 0x2e9ccc, - 0x2dc18c, - 0x20c304, - 0x38d04a, - 0x214042, - 0x201e42, - 0x2c5104, + 0xe703, + 0x23690f, + 0x241882, + 0x2c3587, + 0x2ec3c7, + 0x2de787, + 0x2e2b4c, + 0x2f024c, + 0x21f844, + 0x39334a, + 0x216802, + 0x206902, + 0x2cac84, 0x200702, - 0x2cc342, - 0x2dc3c4, - 0x20fe82, - 0x202042, - 0x1a8c3, - 0x299807, - 0x23a705, - 0x223502, - 0x23cd04, - 0x203f82, - 0x2eba08, - 0x21a3c3, - 0x376b08, - 0x2029c2, - 0x20c4c5, - 0x396e06, - 0x242543, - 0x20a882, - 0x2fa607, - 0xeb02, - 0x39e785, - 0x3c2f45, - 0x206442, - 0x20b382, - 0x33a90a, - 0x35094a, - 0x23c7c2, - 0x2a4284, - 0x203282, - 0x3d3788, - 0x20a5c2, - 0x359208, - 0xf01, - 0x314447, - 0x3149c9, - 0x2b7402, - 0x319985, - 0x3b9c45, - 0x2184cb, - 0x33894c, - 0x22c088, - 0x32bb08, - 0x21d642, - 0x2ac882, + 0x2c23c2, + 0x2f0484, + 0x214882, + 0x202702, + 0x1e1c3, + 0x29a3c7, + 0x30eac5, + 0x204202, + 0x236404, + 0x393b42, + 0x2edd48, + 0x217fc3, + 0x37b588, + 0x203242, + 0x21fa05, + 0x39da86, + 0x23e083, + 0x204fc2, + 0x2fc207, + 0x1b02, + 0x34bbc5, + 0x3dce85, + 0x20b502, + 0x206c82, + 0x34754a, + 0x28de4a, + 0x23cac2, + 0x2a39c4, + 0x200f02, + 0x21dd88, + 0x207ac2, + 0x31c248, + 0x1501, + 0x316b47, + 0x3175c9, + 0x2bb102, + 0x31d505, + 0x36ed45, + 0x212acb, + 0x32c04c, + 0x22c488, + 0x331088, + 0x226642, + 0x2af242, 0x2000c2, - 0x9a048, - 0x201242, - 0x214a83, + 0xae888, + 0x212402, + 0x22ea43, 0x200382, - 0x208482, - 0x3dc3, + 0x203182, + 0x5803, 0x2003c2, - 0x242543, - 0x2090c2, + 0x23e083, + 0x208502, 0x2000c2, - 0x139b05, - 0x7fa01242, - 0x1099c4, - 0x37e85, - 0x80708003, - 0x21a8c3, - 0x209e82, - 0x21a3c3, - 0x3b68c3, - 0x80a42543, - 0x2f7103, - 0x274d46, - 0x160e2c3, - 0x139b05, - 0x13f10b, - 0x9a048, - 0x7ff02e08, - 0x5c1c7, - 0x802c108a, - 0x6ddc7, - 0x97805, - 0x2a54d, - 0x8e242, - 0x118682, + 0x146bc5, + 0x81a12402, + 0x108f04, + 0x37e05, + 0x82a66a83, + 0x21e1c3, + 0x20b982, + 0x217fc3, + 0x3d6203, + 0x82e3e083, + 0x2f8e43, + 0x27a906, + 0x1608503, + 0x146bc5, + 0x14a88b, + 0xae888, + 0x81f64008, + 0x68f47, + 0x822c6aca, + 0x74d87, + 0x1b5a05, + 0x82600f89, + 0x2c10d, + 0x3fcc2, + 0x11bb42, 0xe01, - 0xad28a, - 0x150787, - 0x20c04, - 0x20c43, - 0x3c704, - 0x81202842, - 0x81600ac2, - 0x81a01182, - 0x81e02d02, - 0x82206b42, - 0x826086c2, - 0x17e707, - 0x82a01242, - 0x82e2ec02, - 0x8321f2c2, - 0x83602a42, - 0x214103, - 0xca04, - 0x22dcc3, - 0x83a0e442, - 0x5a988, - 0x83e015c2, - 0x4e2c7, - 0x1ad887, - 0x84200042, - 0x84600d82, - 0x84a00182, - 0x84e06182, - 0x85200f42, - 0x856005c2, - 0xf4185, - 0x24dec3, - 0x35c004, - 0x85a00702, - 0x85e14d42, - 0x86206002, - 0x7a04b, - 0x86600c42, - 0x86e01f42, - 0x87209e82, - 0x87610942, - 0x87a1d542, - 0x87e00bc2, - 0x88202382, - 0x8866c9c2, - 0x88a0ce02, - 0x88e03142, - 0x89208482, - 0x89637242, - 0x89a510c2, - 0x89e43802, - 0x5684, - 0x310543, - 0x8a200ec2, - 0x8a610e82, - 0x8aa0e742, - 0x8ae006c2, - 0x8b2003c2, - 0x8b600a82, - 0xf6bc8, - 0x91fc7, - 0x8ba141c2, - 0x8be06142, - 0x8c2090c2, - 0x8c6023c2, - 0x1aec8c, - 0x8ca02c02, - 0x8ce25b82, - 0x8d20f482, - 0x8d603642, - 0x8da00f02, - 0x8de0b582, - 0x8e201342, - 0x8e607302, - 0x8ea76002, - 0x8ee76542, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x23703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x86a059c3, - 0x223703, - 0x3c0b44, - 0x307d86, - 0x306403, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x374689, - 0x215702, - 0x39b6c3, - 0x2c2a43, - 0x2894c5, - 0x207083, - 0x2059c3, - 0x223703, - 0x267d83, - 0x211243, - 0x3c4409, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x2059c3, - 0x223703, - 0x215702, - 0x215702, - 0x2059c3, - 0x223703, - 0x8f614a83, - 0x232dc3, - 0x207603, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x9a048, - 0x201242, - 0x214a83, - 0x21a3c3, - 0x242543, - 0x141842, - 0x214a83, - 0x232dc3, - 0x308003, - 0x901192c2, - 0x23c803, - 0x21a3c3, - 0x3dc3, - 0x242543, - 0x1301, - 0x24c0c4, - 0x201242, - 0x214a83, + 0x107784, + 0xb018a, + 0x8dc87, + 0x10bb84, + 0x3ca03, + 0x3ca04, + 0x83603d82, + 0x83a00ac2, + 0x83e03502, + 0x84202e42, + 0x846074c2, + 0x84a0cf02, + 0x178d87, + 0x84e12402, + 0x85211d02, + 0x8561c782, + 0x85a0f982, + 0x2168c3, + 0x1ff44, + 0x28c543, + 0x85e12882, + 0x5a388, + 0x86207c82, + 0x4e007, + 0x1b77c7, + 0x86600042, + 0x86a00d82, + 0x86e00182, + 0x87209582, + 0x8760f782, + 0x87a005c2, + 0xfdd45, + 0x24dc03, + 0x3612c4, + 0x87e00702, + 0x8820a342, + 0x88601582, + 0x8d64b, + 0x88a00c42, + 0x89206a02, + 0x8960b982, + 0x89a04482, + 0x89e15782, + 0x8a200bc2, + 0x8a60a942, + 0x8aa720c2, + 0x8ae16102, + 0x8b201602, + 0x8b603182, + 0x8ba37282, + 0x8be05402, + 0x8c209ec2, + 0x1583c4, + 0x3169c3, + 0x8c634e42, + 0x8ca0f442, + 0x8ce03742, + 0x8d2006c2, + 0x8d6003c2, + 0x8da00a82, + 0xf8908, + 0x1b2007, + 0x8de16982, + 0x8e205302, + 0x8e608502, + 0x8ea0a1c2, + 0x1b800c, + 0x8ee03d02, + 0x8f224e42, + 0x8f601942, + 0x8fa034c2, + 0x8fe0e482, + 0x90203b02, + 0x90607d02, + 0x90a16382, + 0x90e7bcc2, + 0x9127c2c2, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x88f433c3, + 0x2220c3, + 0x3c7a04, + 0x266806, + 0x307183, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x26e9c9, + 0x20cdc2, + 0x3b3843, + 0x2c9343, + 0x260045, + 0x2033c3, + 0x3433c3, + 0x2220c3, + 0x2b8a83, + 0x20de03, + 0x3679c9, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x20cdc2, + 0x20cdc2, + 0x3433c3, + 0x2220c3, + 0x91a2ea43, + 0x233fc3, + 0x213f83, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0xae888, + 0x212402, + 0x22ea43, + 0x217fc3, + 0x23e083, + 0x6e842, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x924f6e82, + 0x23cb03, + 0x217fc3, + 0x5803, + 0x23e083, + 0x1381, + 0x241ec4, + 0x212402, + 0x22ea43, 0x200983, - 0x232dc3, - 0x24d9c4, - 0x228503, - 0x308003, - 0x221dc4, - 0x21bc83, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x22b983, - 0x208805, - 0x211243, - 0x207783, + 0x233fc3, + 0x24d704, + 0x280203, + 0x266a83, + 0x20e704, + 0x2191c3, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x235403, + 0x37b845, + 0x20de03, + 0x20aa43, 0x882, - 0x3dc3, - 0x201242, - 0x214a83, - 0x2059c3, - 0x21a3c3, - 0x242543, + 0x5803, + 0x212402, + 0x22ea43, + 0x3433c3, + 0x217fc3, + 0x23e083, 0x2000c2, - 0x202703, - 0x9a048, - 0x214a83, - 0x232dc3, - 0x308003, - 0x22f7c6, - 0x221dc4, - 0x21bc83, - 0x219a04, - 0x21a3c3, - 0x242543, - 0x2141c3, - 0x29904, - 0x214a83, - 0x239c3, - 0x232dc3, - 0x9e82, - 0x21a3c3, - 0x242543, - 0x2aec2, - 0x2982, - 0x147ee07, - 0x1807, - 0x214a83, - 0x28886, - 0x232dc3, - 0x308003, - 0xedf86, - 0x21a3c3, - 0x242543, - 0x328e48, - 0x32b949, - 0x33e209, - 0x34ae08, - 0x399488, - 0x399489, - 0x322c0a, - 0x3602ca, - 0x39424a, - 0x39abca, - 0x3ca20a, - 0x3d818b, - 0x30838d, - 0x23fd4f, - 0x35d210, - 0x361d4d, - 0x37d8cc, - 0x39a90b, - 0x6dfc8, - 0x11d548, - 0x19d705, - 0x1486107, - 0xd7445, + 0x24ac43, + 0xae888, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x231346, + 0x20e704, + 0x2191c3, + 0x21e484, + 0x217fc3, + 0x23e083, + 0x216983, + 0x4cc4, + 0x161e82, + 0x22ea43, + 0x22383, + 0x233fc3, + 0xb982, + 0x217fc3, + 0x23e083, + 0x30242, + 0x2a82, + 0x1481bc7, + 0x8cc7, + 0x22ea43, + 0x36fc6, + 0x233fc3, + 0x266a83, + 0xf07c6, + 0x217fc3, + 0x23e083, + 0x32d948, + 0x330ec9, + 0x341dc9, + 0x34cfc8, + 0x3a01c8, + 0x3a01c9, + 0x32748a, + 0x3657ca, + 0x399a4a, + 0x3a124a, + 0x3cf9ca, + 0x3db28b, + 0x26604d, + 0x230b0f, + 0x240950, + 0x3692cd, + 0x38384c, + 0x3a0f8b, + 0x74f88, + 0xf6cc8, + 0xbe1c5, + 0x148e8c7, + 0xd9785, 0x2000c2, - 0x2cd685, - 0x202003, - 0x93601242, - 0x232dc3, - 0x308003, - 0x27e7c7, - 0x25cc03, - 0x23c803, - 0x21a3c3, - 0x24e283, - 0x2125c3, - 0x206a03, - 0x203dc3, - 0x242543, - 0x252b06, - 0x233442, - 0x207783, - 0x9a048, + 0x355d45, + 0x21e183, + 0x95a12402, + 0x233fc3, + 0x266a83, + 0x232b87, + 0x21df43, + 0x23cb03, + 0x217fc3, + 0x24dfc3, + 0x213cc3, + 0x210ec3, + 0x205803, + 0x23e083, + 0x2509c6, + 0x22dc42, + 0x20aa43, + 0xae888, 0x2000c2, - 0x202703, - 0x201242, - 0x214a83, - 0x232dc3, - 0x308003, - 0x221dc4, - 0x23c803, - 0x21a3c3, - 0x242543, - 0x20e2c3, - 0x1807, - 0xb342, - 0x68b44, - 0x151c306, + 0x24ac43, + 0x212402, + 0x22ea43, + 0x233fc3, + 0x266a83, + 0x20e704, + 0x23cb03, + 0x217fc3, + 0x23e083, + 0x208503, + 0x8cc7, + 0x10382, + 0x2144, + 0x1517446, 0x2000c2, - 0x201242, - 0x308003, - 0x23c803, - 0x242543, + 0x212402, + 0x266a83, + 0x23cb03, + 0x23e083, } // children is the list of nodes' children, the parent's wildcard bit and the @@ -9554,597 +9614,606 @@ var children = [...]uint32{ 0x40000000, 0x50000000, 0x60000000, - 0x17ec5f5, - 0x17f05fb, - 0x17f45fc, - 0x18185fd, - 0x1970606, - 0x198865c, - 0x199c662, - 0x19b4667, - 0x19d466d, - 0x19f4675, - 0x1a0c67d, - 0x1a2c683, - 0x1a3068b, - 0x1a5868c, + 0x17d05ee, + 0x17d45f4, + 0x17d85f5, + 0x17fc5f6, + 0x19545ff, + 0x196c655, + 0x198065b, + 0x1998660, + 0x19b8666, + 0x19d866e, + 0x19f0676, + 0x1a1067c, + 0x1a14684, + 0x1a3c685, + 0x1a4068f, + 0x1a58690, 0x1a5c696, - 0x1a74697, - 0x1a7869d, - 0x1a7c69e, - 0x1ab869f, - 0x1abc6ae, - 0x1ac06af, - 0x61ac86b0, - 0x21ad06b2, - 0x1b186b4, - 0x1b1c6c6, - 0x1b406c7, - 0x1b446d0, + 0x1a60697, + 0x1aa0698, + 0x1aa46a8, + 0x1aa86a9, + 0x21aac6aa, + 0x61ab46ab, + 0x21abc6ad, + 0x1b046af, + 0x1b086c1, + 0x1b2c6c2, + 0x1b306cb, + 0x1b446cc, 0x1b486d1, - 0x1b5c6d2, - 0x1b606d7, - 0x1b806d8, - 0x1bb06e0, - 0x1bcc6ec, - 0x1bf46f3, - 0x1c046fd, - 0x1c08701, - 0x1ca0702, - 0x1cb4728, - 0x1cc872d, - 0x1d00732, - 0x1d10740, - 0x1d24744, - 0x1d3c749, - 0x1de074f, - 0x1fe4778, - 0x1fe87f9, - 0x20547fa, - 0x20c0815, - 0x20d8830, - 0x20ec836, - 0x20f083b, - 0x20f883c, - 0x210c83e, - 0x2110843, - 0x2130844, - 0x218084c, - 0x2184860, - 0x22188861, - 0x21a4862, - 0x21a8869, - 0x21ac86a, - 0x21d086b, - 0x2214874, - 0x2218885, - 0x6221c886, - 0x2238887, - 0x226488e, - 0x2270899, - 0x228089c, - 0x23348a0, - 0x23388cd, - 0x223488ce, - 0x2234c8d2, - 0x223548d3, - 0x23ac8d5, - 0x23b08eb, - 0x23b48ec, - 0x28dc8ed, - 0x28e0a37, - 0x22988a38, - 0x2298ca62, - 0x22990a63, - 0x2299ca64, - 0x229a0a67, - 0x229aca68, - 0x229b0a6b, - 0x229b4a6c, - 0x229b8a6d, - 0x229bca6e, - 0x229c0a6f, - 0x229cca70, - 0x229d0a73, - 0x229dca74, - 0x229e0a77, - 0x229e4a78, - 0x229e8a79, - 0x229f4a7a, - 0x229f8a7d, - 0x22a04a7e, - 0x22a08a81, - 0x22a0ca82, + 0x1b686d2, + 0x1b986da, + 0x1bb46e6, + 0x1bdc6ed, + 0x1bec6f7, + 0x1bf06fb, + 0x1c886fc, + 0x1c9c722, + 0x1cb0727, + 0x1ce872c, + 0x1cf873a, + 0x1d0c73e, + 0x1d24743, + 0x1dc8749, + 0x1ffc772, + 0x20007ff, + 0x206c800, + 0x20d881b, + 0x20f0836, + 0x210483c, + 0x2108841, + 0x2110842, + 0x2124844, + 0x2128849, + 0x214884a, + 0x2198852, + 0x219c866, + 0x221a0867, + 0x21c0868, + 0x21c4870, + 0x21c8871, + 0x21f0872, + 0x621f487c, + 0x223887d, + 0x223c88e, + 0x6224088f, + 0x225c890, + 0x228c897, + 0x229c8a3, + 0x22ac8a7, + 0x23608ab, + 0x23648d8, + 0x223748d9, + 0x223788dd, + 0x223808de, + 0x23d88e0, + 0x23dc8f6, + 0x23e08f7, + 0x29348f8, + 0x2938a4d, + 0x62940a4e, + 0x229e8a50, + 0x229eca7a, + 0x229f0a7b, + 0x229fca7c, + 0x22a00a7f, + 0x22a0ca80, 0x22a10a83, - 0x2a14a84, + 0x22a14a84, 0x22a18a85, - 0x22a24a86, - 0x22a28a89, - 0x2a2ca8a, - 0x2a34a8b, - 0x62a40a8d, - 0x2a84a90, - 0x22aa4aa1, - 0x22aa8aa9, - 0x22aacaaa, - 0x22ab0aab, - 0x22ab8aac, - 0x22abcaae, - 0x2ac0aaf, - 0x22ac4ab0, - 0x22ac8ab1, - 0x22accab2, - 0x22ad0ab3, - 0x2ad8ab4, - 0x2ae0ab6, - 0x2ae4ab8, - 0x2b00ab9, - 0x2b18ac0, - 0x2b1cac6, - 0x2b2cac7, - 0x2b38acb, - 0x2b6cace, - 0x2b74adb, - 0x22b78add, - 0x2b90ade, - 0x22b98ae4, - 0x22b9cae6, - 0x22ba4ae7, - 0x2ca0ae9, - 0x22ca4b28, - 0x2cacb29, - 0x2cb0b2b, - 0x22cb4b2c, - 0x2cb8b2d, - 0x2ce0b2e, - 0x2ce4b38, - 0x2ce8b39, - 0x2cecb3a, - 0x2d04b3b, - 0x2d18b41, - 0x2d40b46, - 0x2d60b50, - 0x2d64b58, - 0x62d68b59, - 0x2d9cb5a, - 0x2da0b67, - 0x22da4b68, - 0x2da8b69, - 0x2dd0b6a, - 0x2dd4b74, - 0x2df8b75, - 0x2dfcb7e, - 0x2e10b7f, - 0x2e14b84, - 0x2e18b85, - 0x2e38b86, - 0x2e54b8e, + 0x22a1ca86, + 0x22a20a87, + 0x22a2ca88, + 0x22a30a8b, + 0x22a3ca8c, + 0x22a40a8f, + 0x22a44a90, + 0x22a48a91, + 0x22a54a92, + 0x22a58a95, + 0x22a64a96, + 0x22a68a99, + 0x22a6ca9a, + 0x22a70a9b, + 0x2a74a9c, + 0x22a78a9d, + 0x22a84a9e, + 0x22a88aa1, + 0x2a8caa2, + 0x2a94aa3, + 0x62aa0aa5, + 0x2ae4aa8, + 0x22b04ab9, + 0x22b08ac1, + 0x22b0cac2, + 0x22b10ac3, + 0x22b14ac4, + 0x22b1cac5, + 0x22b20ac7, + 0x2b24ac8, + 0x22b44ac9, + 0x22b48ad1, + 0x22b4cad2, + 0x22b50ad3, + 0x22b54ad4, + 0x22b58ad5, + 0x2b60ad6, + 0x2b68ad8, + 0x2b6cada, + 0x2b88adb, + 0x2ba0ae2, + 0x2ba4ae8, + 0x2bb4ae9, + 0x2bc0aed, + 0x2bf4af0, + 0x2bfcafd, + 0x22c00aff, + 0x2c18b00, + 0x22c20b06, + 0x22c24b08, + 0x22c2cb09, + 0x2d28b0b, + 0x22d2cb4a, + 0x2d34b4b, + 0x2d38b4d, + 0x22d3cb4e, + 0x2d40b4f, + 0x2d68b50, + 0x2d6cb5a, + 0x2d70b5b, + 0x2d88b5c, + 0x2d9cb62, + 0x2dc4b67, + 0x2de4b71, + 0x2de8b79, + 0x62decb7a, + 0x2e20b7b, + 0x2e24b88, + 0x22e28b89, + 0x2e2cb8a, + 0x2e54b8b, 0x2e58b95, - 0x22e5cb96, - 0x2e60b97, - 0x2e64b98, - 0x2e68b99, - 0x2e70b9a, - 0x2e84b9c, - 0x2e88ba1, - 0x2e8cba2, - 0x2eb4ba3, - 0x2eb8bad, - 0x2f2cbae, - 0x2f30bcb, - 0x2f34bcc, - 0x2f54bcd, - 0x2f6cbd5, - 0x2f70bdb, - 0x2f84bdc, - 0x2f9cbe1, - 0x2fbcbe7, - 0x2fd4bef, - 0x2fd8bf5, - 0x2ff4bf6, - 0x3010bfd, - 0x3014c04, - 0x3040c05, - 0x3060c10, - 0x3080c18, - 0x30e4c20, + 0x2e7cb96, + 0x2e80b9f, + 0x2e94ba0, + 0x2e98ba5, + 0x2e9cba6, + 0x2ebcba7, + 0x2ed8baf, + 0x2edcbb6, + 0x22ee0bb7, + 0x2ee4bb8, + 0x2ee8bb9, + 0x2eecbba, + 0x2ef4bbb, + 0x2f08bbd, + 0x2f0cbc2, + 0x2f10bc3, + 0x2f38bc4, + 0x2f3cbce, + 0x2fb0bcf, + 0x2fb4bec, + 0x2fb8bed, + 0x2fd8bee, + 0x2ff0bf6, + 0x2ff4bfc, + 0x3008bfd, + 0x3020c02, + 0x3040c08, + 0x3058c10, + 0x305cc16, + 0x3078c17, + 0x3094c1e, + 0x3098c25, + 0x30c4c26, + 0x30e4c31, 0x3104c39, - 0x3120c41, - 0x3124c48, - 0x313cc49, - 0x3180c4f, - 0x3200c60, - 0x3230c80, - 0x3234c8c, - 0x3240c8d, - 0x3260c90, - 0x3264c98, - 0x3288c99, - 0x3290ca2, - 0x32ccca4, - 0x3320cb3, - 0x3324cc8, - 0x3328cc9, - 0x3404cca, - 0x2340cd01, - 0x23410d03, - 0x23414d04, - 0x3418d05, - 0x2341cd06, - 0x23420d07, - 0x3424d08, - 0x23428d09, - 0x23438d0a, - 0x2343cd0e, - 0x23440d0f, - 0x23444d10, - 0x23448d11, - 0x2344cd12, - 0x3464d13, - 0x3488d19, - 0x34a8d22, - 0x3b14d2a, - 0x3b20ec5, - 0x3b40ec8, - 0x3d00ed0, - 0x3dd0f40, - 0x3e40f74, - 0x3e98f90, - 0x3f80fa6, - 0x3fd8fe0, - 0x4014ff6, - 0x4111005, - 0x41dd044, - 0x4275077, - 0x430509d, - 0x43690c1, - 0x45a10da, - 0x4659168, - 0x4725196, - 0x47711c9, - 0x47f91dc, - 0x48351fe, - 0x488520d, - 0x48fd221, - 0x6490123f, - 0x64905240, - 0x64909241, - 0x4985242, - 0x49e1261, - 0x4a5d278, - 0x4ad5297, - 0x4b552b5, - 0x4bc12d5, - 0x4ced2f0, - 0x4d4533b, - 0x64d49351, - 0x4de1352, - 0x4de9378, - 0x24ded37a, - 0x4e7537b, - 0x4ec139d, - 0x4f293b0, - 0x4fd13ca, - 0x50993f4, - 0x5101426, - 0x5215440, - 0x65219485, - 0x6521d486, - 0x5279487, - 0x52d549e, - 0x53654b5, - 0x53e14d9, - 0x54254f8, - 0x5509509, - 0x553d542, - 0x559d54f, - 0x5611567, - 0x5699584, - 0x56d95a6, - 0x57495b6, - 0x6574d5d2, - 0x57755d3, - 0x57795dd, - 0x57a95de, - 0x57c55ea, - 0x58095f1, - 0x5819602, - 0x5831606, - 0x58a960c, - 0x58b162a, - 0x58cd62c, - 0x58e1633, - 0x58fd638, - 0x592963f, - 0x592d64a, - 0x593564b, - 0x594964d, - 0x5969652, - 0x597965a, - 0x598565e, - 0x59c1661, - 0x59c9670, - 0x59dd672, - 0x5a05677, - 0x5a11681, - 0x5a19684, - 0x5a41686, - 0x5a65690, - 0x5a7d699, - 0x5a8169f, - 0x5a896a0, - 0x5a9d6a2, - 0x5b456a7, - 0x5b496d1, - 0x5b4d6d2, - 0x5b516d3, - 0x5b756d4, - 0x5b996dd, - 0x5bb56e6, - 0x5bc96ed, - 0x5bdd6f2, - 0x5be56f7, - 0x5bed6f9, - 0x5bf56fb, - 0x5c0d6fd, - 0x5c1d703, - 0x5c21707, - 0x5c3d708, - 0x64c570f, - 0x64fd931, - 0x652993f, - 0x654594a, - 0x6565951, - 0x6585959, - 0x65c9961, - 0x65d1972, - 0x265d5974, - 0x265d9975, - 0x65e1976, - 0x67cd978, - 0x267d19f3, - 0x67d59f4, - 0x267d99f5, - 0x267e99f6, - 0x267f19fa, - 0x267fd9fc, - 0x68019ff, - 0x26809a00, - 0x6811a02, - 0x6821a04, - 0x6849a08, - 0x6885a12, - 0x6889a21, - 0x68c1a22, - 0x68e5a30, - 0x743da39, - 0x7441d0f, - 0x7445d10, - 0x27449d11, - 0x744dd12, - 0x27451d13, - 0x7455d14, - 0x27461d15, - 0x7465d18, - 0x7469d19, - 0x2746dd1a, - 0x7471d1b, - 0x27479d1c, - 0x747dd1e, - 0x7481d1f, - 0x27491d20, - 0x7495d24, - 0x7499d25, - 0x749dd26, - 0x74a1d27, - 0x274a5d28, - 0x74a9d29, - 0x74add2a, - 0x74b1d2b, - 0x74b5d2c, - 0x274bdd2d, - 0x74c1d2f, - 0x74c5d30, - 0x74c9d31, - 0x274cdd32, - 0x74d1d33, - 0x274d9d34, - 0x274ddd36, - 0x74f9d37, - 0x7511d3e, - 0x7555d44, + 0x3168c41, + 0x3188c5a, + 0x31a8c62, + 0x31acc6a, + 0x31c4c6b, + 0x3208c71, + 0x3288c82, + 0x32b8ca2, + 0x32bccae, + 0x32c8caf, + 0x32e8cb2, + 0x32eccba, + 0x3310cbb, + 0x3318cc4, + 0x3354cc6, + 0x33a8cd5, + 0x33accea, + 0x33b0ceb, + 0x3494cec, + 0x2349cd25, + 0x234a0d27, + 0x234a4d28, + 0x34a8d29, + 0x234acd2a, + 0x234b0d2b, + 0x34b4d2c, + 0x234b8d2d, + 0x234c8d2e, + 0x234ccd32, + 0x234d0d33, + 0x234d4d34, + 0x234d8d35, + 0x234dcd36, + 0x34f4d37, + 0x3518d3d, + 0x3538d46, + 0x3ba4d4e, + 0x3bb0ee9, + 0x3bd0eec, + 0x3d90ef4, + 0x3e60f64, + 0x3ed0f98, + 0x3f28fb4, + 0x4010fca, + 0x4069004, + 0x40a501a, + 0x41a1029, + 0x426d068, + 0x430509b, + 0x43950c1, + 0x43f90e5, + 0x46310fe, + 0x46e918c, + 0x47b51ba, + 0x48011ed, + 0x4889200, + 0x48c5222, + 0x4915231, + 0x498d245, + 0x64991263, + 0x64995264, + 0x64999265, + 0x4a15266, + 0x4a71285, + 0x4aed29c, + 0x4b652bb, + 0x4be52d9, + 0x4c512f9, + 0x4d7d314, + 0x4dd535f, + 0x64dd9375, + 0x4e71376, + 0x4e7939c, + 0x24e7d39e, + 0x4f0539f, + 0x4f513c1, + 0x4fb93d4, + 0x50613ee, + 0x5129418, + 0x519144a, + 0x52a5464, + 0x652a94a9, + 0x652ad4aa, + 0x53094ab, + 0x53654c2, + 0x53f54d9, + 0x54714fd, + 0x54b551c, + 0x559952d, + 0x55cd566, + 0x562d573, + 0x56a158b, + 0x57295a8, + 0x57695ca, + 0x57d95da, + 0x657dd5f6, + 0x58055f7, + 0x5809601, + 0x5839602, + 0x585560e, + 0x5899615, + 0x58a9626, + 0x58c162a, + 0x5939630, + 0x594164e, + 0x595d650, + 0x5971657, + 0x598d65c, + 0x59b9663, + 0x59bd66e, + 0x59c566f, + 0x59d9671, + 0x59f9676, + 0x5a0967e, + 0x5a15682, + 0x5a51685, + 0x5a59694, + 0x5a6d696, + 0x5a9569b, + 0x5aa16a5, + 0x5aa96a8, + 0x5ad16aa, + 0x5af56b4, + 0x5b0d6bd, + 0x5b116c3, + 0x5b196c4, + 0x5b2d6c6, + 0x5bd56cb, + 0x5bd96f5, + 0x5bdd6f6, + 0x5be16f7, + 0x5c056f8, + 0x5c29701, + 0x5c4570a, + 0x5c59711, + 0x5c6d716, + 0x5c7571b, + 0x5c7d71d, + 0x5c8571f, + 0x5c9d721, + 0x5cad727, + 0x5cb172b, + 0x5ccd72c, + 0x6555733, + 0x658d955, + 0x65b9963, + 0x65d596e, + 0x65f5975, + 0x661597d, + 0x6659985, + 0x6661996, + 0x26665998, + 0x26669999, + 0x667199a, + 0x687199c, + 0x26875a1c, + 0x6879a1d, + 0x2687da1e, + 0x2688da1f, + 0x26895a23, + 0x268a1a25, + 0x68a5a28, + 0x268a9a29, + 0x268b1a2a, + 0x68b9a2c, + 0x68c9a2e, + 0x68f1a32, + 0x692da3c, + 0x6931a4b, + 0x6969a4c, + 0x698da5a, + 0x74e5a63, + 0x74e9d39, + 0x74edd3a, + 0x274f1d3b, + 0x74f5d3c, + 0x274f9d3d, + 0x74fdd3e, + 0x27509d3f, + 0x750dd42, + 0x7511d43, + 0x27515d44, + 0x7519d45, + 0x27521d46, + 0x7525d48, + 0x7529d49, + 0x27539d4a, + 0x753dd4e, + 0x7541d4f, + 0x7545d50, + 0x7549d51, + 0x2754dd52, + 0x7551d53, + 0x7555d54, 0x7559d55, - 0x757dd56, - 0x7589d5f, - 0x758dd62, - 0x7591d63, - 0x7755d64, - 0x27759dd5, - 0x27761dd6, - 0x27765dd8, - 0x27769dd9, - 0x7771dda, - 0x784dddc, - 0x27859e13, - 0x2785de16, - 0x27861e17, - 0x27865e18, - 0x7869e19, - 0x7895e1a, - 0x78a1e25, - 0x78a5e28, - 0x78c9e29, - 0x78d5e32, - 0x78f5e35, - 0x78f9e3d, - 0x7931e3e, - 0x7be1e4c, - 0x7c9def8, - 0x7ca1f27, - 0x7ca5f28, - 0x7cb9f29, - 0x7cbdf2e, - 0x7cf1f2f, - 0x7d29f3c, - 0x27d2df4a, - 0x7d49f4b, - 0x7d71f52, - 0x7d75f5c, - 0x7d99f5d, - 0x7db5f66, - 0x7dddf6d, - 0x7dedf77, - 0x7df1f7b, - 0x7df5f7c, - 0x7e2df7d, - 0x7e39f8b, - 0x7e61f8e, - 0x7ee1f98, - 0x27ee5fb8, - 0x7ef5fb9, - 0x7f05fbd, - 0x7f21fc1, - 0x7f41fc8, - 0x7f45fd0, - 0x7f59fd1, - 0x7f6dfd6, - 0x7f71fdb, - 0x7f75fdc, - 0x7f79fdd, - 0x7f99fde, - 0x8041fe6, - 0x8046010, - 0x8062011, - 0x808a018, - 0x808e022, - 0x8096023, - 0x80ba025, - 0x80c202e, - 0x80d6030, - 0x80f6035, - 0x811203d, - 0x8122044, - 0x813a048, - 0x817204e, - 0x817605c, - 0x824a05d, + 0x755dd56, + 0x27565d57, + 0x7569d59, + 0x756dd5a, + 0x7571d5b, + 0x27575d5c, + 0x7579d5d, + 0x27581d5e, + 0x27585d60, + 0x75a1d61, + 0x75b9d68, + 0x75fdd6e, + 0x7601d7f, + 0x7625d80, + 0x7631d89, + 0x7635d8c, + 0x7639d8d, + 0x77fdd8e, + 0x27801dff, + 0x27809e00, + 0x2780de02, + 0x27811e03, + 0x7819e04, + 0x78f5e06, + 0x27901e3d, + 0x27905e40, + 0x27909e41, + 0x2790de42, + 0x7911e43, + 0x793de44, + 0x7949e4f, + 0x794de52, + 0x7971e53, + 0x797de5c, + 0x799de5f, + 0x79a1e67, + 0x79d9e68, + 0x7c89e76, + 0x7d45f22, + 0x7d49f51, + 0x7d4df52, + 0x7d61f53, + 0x7d65f58, + 0x7d99f59, + 0x7dd1f66, + 0x27dd5f74, + 0x7df1f75, + 0x7e19f7c, + 0x7e1df86, + 0x7e41f87, + 0x7e5df90, + 0x7e85f97, + 0x7e95fa1, + 0x7e99fa5, + 0x7e9dfa6, + 0x7ed5fa7, + 0x7ee1fb5, + 0x7f09fb8, + 0x7f95fc2, + 0x27f99fe5, + 0x7f9dfe6, + 0x7fadfe7, + 0x27fb1feb, + 0x7fc1fec, + 0x7fddff0, + 0x7ffdff7, + 0x8001fff, + 0x8016000, + 0x802a005, + 0x802e00a, + 0x803200b, + 0x803600c, + 0x805600d, + 0x80fe015, + 0x810203f, + 0x811e040, + 0x8146047, + 0x28156051, + 0x815a055, + 0x8166056, + 0x8192059, + 0x819a064, + 0x81ae066, + 0x81ce06b, + 0x81ea073, + 0x81fa07a, + 0x821207e, + 0x824a084, 0x824e092, - 0x8262093, - 0x826a098, - 0x828209a, - 0x82860a0, - 0x82920a1, - 0x829e0a4, - 0x82a20a7, - 0x82a60a8, - 0x82aa0a9, - 0x82ce0aa, - 0x830e0b3, - 0x83120c3, - 0x83320c4, - 0x83820cc, - 0x83ae0e0, - 0x283b20eb, - 0x83ba0ec, - 0x84120ee, - 0x8416104, - 0x841a105, - 0x841e106, - 0x8462107, - 0x8472118, - 0x84b211c, - 0x84b612c, - 0x84e612d, - 0x8632139, - 0x865a18c, - 0x8692196, - 0x86b61a4, - 0x286be1ad, - 0x286c21af, - 0x86ca1b0, - 0x86d61b2, - 0x87f21b5, - 0x87fe1fc, - 0x880a1ff, - 0x8816202, - 0x8822205, - 0x882e208, - 0x883a20b, - 0x884620e, - 0x8852211, - 0x885e214, - 0x886a217, - 0x887621a, - 0x888221d, - 0x888e220, - 0x8896223, - 0x88a2225, - 0x88ae228, - 0x88ba22b, - 0x88c622e, - 0x88d2231, - 0x88de234, - 0x88ea237, - 0x88f623a, - 0x890223d, - 0x890e240, - 0x891a243, - 0x8946246, - 0x8952251, - 0x895e254, - 0x896a257, - 0x897625a, - 0x898225d, - 0x898a260, - 0x8996262, - 0x89a2265, - 0x89ae268, - 0x89ba26b, - 0x89c626e, - 0x89d2271, - 0x89de274, - 0x89ea277, - 0x89f627a, - 0x8a0227d, - 0x8a0e280, - 0x8a16283, - 0x8a22285, - 0x8a2a288, + 0x8322093, + 0x83260c8, + 0x833a0c9, + 0x83420ce, + 0x835a0d0, + 0x835e0d6, + 0x836a0d7, + 0x83760da, + 0x837a0dd, + 0x83820de, + 0x83860e0, + 0x83aa0e1, + 0x83ea0ea, + 0x83ee0fa, + 0x840e0fb, + 0x845e103, + 0x848e117, + 0x28492123, + 0x849a124, + 0x84f2126, + 0x84f613c, + 0x84fa13d, + 0x84fe13e, + 0x854213f, + 0x8552150, + 0x8592154, + 0x8596164, + 0x85c6165, + 0x870e171, + 0x87361c3, + 0x876e1cd, + 0x87961db, + 0x2879e1e5, + 0x287a21e7, + 0x287a61e8, + 0x87ae1e9, + 0x87ba1eb, + 0x88d61ee, + 0x88e2235, + 0x88ee238, + 0x88fa23b, + 0x890623e, + 0x8912241, + 0x891e244, + 0x892a247, + 0x893624a, + 0x894224d, + 0x894e250, + 0x895a253, + 0x8966256, + 0x8972259, + 0x897a25c, + 0x898625e, + 0x8992261, + 0x899e264, + 0x89aa267, + 0x89b626a, + 0x89c226d, + 0x89ce270, + 0x89da273, + 0x89e6276, + 0x89f2279, + 0x89fe27c, + 0x8a2a27f, 0x8a3628a, 0x8a4228d, 0x8a4e290, 0x8a5a293, 0x8a66296, - 0x8a72299, - 0x8a7e29c, - 0x8a8a29f, - 0x8a8e2a2, - 0x8a9a2a3, - 0x8ab62a6, - 0x8aba2ad, - 0x8aca2ae, - 0x8aee2b2, - 0x8af22bb, - 0x8b362bc, - 0x8b3e2cd, - 0x8b522cf, - 0x8b862d4, - 0x8ba22e1, - 0x8baa2e8, - 0x8bce2ea, - 0x8be62f3, - 0x8bfe2f9, - 0x8c162ff, - 0x8c2a305, - 0x28c7230a, - 0x8c7631c, - 0x8ca231d, - 0x8cb2328, - 0x8cc632c, + 0x8a6e299, + 0x8a7a29b, + 0x8a8629e, + 0x8a922a1, + 0x8a9e2a4, + 0x8aaa2a7, + 0x8ab62aa, + 0x8ac22ad, + 0x8ace2b0, + 0x8ada2b3, + 0x8ae62b6, + 0x8af22b9, + 0x8afa2bc, + 0x8b062be, + 0x8b0e2c1, + 0x8b1a2c3, + 0x8b262c6, + 0x8b322c9, + 0x8b3e2cc, + 0x8b4a2cf, + 0x8b562d2, + 0x8b622d5, + 0x8b6e2d8, + 0x8b722db, + 0x8b7e2dc, + 0x8b9a2df, + 0x8b9e2e6, + 0x8bae2e7, + 0x8bd22eb, + 0x8bd62f4, + 0x8c1a2f5, + 0x8c22306, + 0x8c36308, + 0x8c6a30d, + 0x8c8a31a, + 0x8c92322, + 0x8cb6324, + 0x8cce32d, + 0x8ce6333, + 0x8cfe339, + 0x8d1233f, + 0x28d5a344, + 0x8d5e356, + 0x8d8a357, + 0x8d9a362, + 0x8dae366, } -// max children 592 (capacity 1023) -// max text offset 30772 (capacity 32767) +// max children 601 (capacity 1023) +// max text offset 30901 (capacity 32767) // max text length 36 (capacity 63) -// max hi 9009 (capacity 16383) -// max lo 9004 (capacity 16383) +// max hi 9067 (capacity 16383) +// max lo 9062 (capacity 16383) diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go index 5ee692d38..dc6177c12 100644 --- a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go +++ b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go @@ -19,8 +19,7 @@ import ( var debug = false -// GetSizes returns the sizes used by the underlying driver with the given parameters. -func GetSizes(ctx context.Context, buildFlags, env []string, dir string, usesExportData bool) (types.Sizes, error) { +func GetSizes(ctx context.Context, buildFlags, env []string, gocmdRunner *gocommand.Runner, dir string) (types.Sizes, error) { // TODO(matloob): Clean this up. This code is mostly a copy of packages.findExternalDriver. const toolPrefix = "GOPACKAGESDRIVER=" tool := "" @@ -40,7 +39,7 @@ func GetSizes(ctx context.Context, buildFlags, env []string, dir string, usesExp } if tool == "off" { - return GetSizesGolist(ctx, buildFlags, env, dir, usesExportData) + return GetSizesGolist(ctx, buildFlags, env, gocmdRunner, dir) } req, err := json.Marshal(struct { @@ -76,7 +75,7 @@ func GetSizes(ctx context.Context, buildFlags, env []string, dir string, usesExp return response.Sizes, nil } -func GetSizesGolist(ctx context.Context, buildFlags, env []string, dir string, usesExportData bool) (types.Sizes, error) { +func GetSizesGolist(ctx context.Context, buildFlags, env []string, gocmdRunner *gocommand.Runner, dir string) (types.Sizes, error) { inv := gocommand.Invocation{ Verb: "list", Args: []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"}, @@ -84,7 +83,7 @@ func GetSizesGolist(ctx context.Context, buildFlags, env []string, dir string, u BuildFlags: buildFlags, WorkingDir: dir, } - stdout, stderr, friendlyErr, rawErr := inv.RunRaw(ctx) + stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv) var goarch, compiler string if rawErr != nil { if strings.Contains(rawErr.Error(), "cannot find main module") { @@ -96,7 +95,7 @@ func GetSizesGolist(ctx context.Context, buildFlags, env []string, dir string, u Env: env, WorkingDir: dir, } - envout, enverr := inv.Run(ctx) + envout, enverr := gocmdRunner.Run(ctx, inv) if enverr != nil { return nil, enverr } diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go index b4a13ef45..bc04503c1 100644 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ b/vendor/golang.org/x/tools/go/packages/golist.go @@ -24,7 +24,7 @@ import ( "golang.org/x/tools/go/internal/packagesdriver" "golang.org/x/tools/internal/gocommand" - "golang.org/x/tools/internal/packagesinternal" + "golang.org/x/xerrors" ) // debug controls verbose logging. @@ -89,6 +89,10 @@ type golistState struct { rootDirsError error rootDirs map[string]string + goVersionOnce sync.Once + goVersionError error + goVersion string // third field of 'go version' + // vendorDirs caches the (non)existence of vendor directories. vendorDirs map[string]bool } @@ -142,7 +146,7 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { sizeswg.Add(1) go func() { var sizes types.Sizes - sizes, sizeserr = packagesdriver.GetSizesGolist(ctx, cfg.BuildFlags, cfg.Env, cfg.Dir, usesExportData(cfg)) + sizes, sizeserr = packagesdriver.GetSizesGolist(ctx, cfg.BuildFlags, cfg.Env, cfg.gocmdRunner, cfg.Dir) // types.SizesFor always returns nil or a *types.StdSizes. response.dr.Sizes, _ = sizes.(*types.StdSizes) sizeswg.Done() @@ -242,6 +246,21 @@ extractQueries: } } } + // Add root for any package that matches a pattern. This applies only to + // packages that are modified by overlays, since they are not added as + // roots automatically. + for _, pattern := range restPatterns { + match := matchPattern(pattern) + for _, pkgID := range modifiedPkgs { + pkg, ok := response.seenPackages[pkgID] + if !ok { + continue + } + if match(pkg.PkgPath) { + response.addRoot(pkg.ID) + } + } + } sizeswg.Wait() if sizeserr != nil { @@ -381,7 +400,7 @@ type jsonPackage struct { Imports []string ImportMap map[string]string Deps []string - Module *packagesinternal.Module + Module *Module TestGoFiles []string TestImports []string XTestGoFiles []string @@ -502,10 +521,19 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse errkind = "use of internal package not allowed" } if errkind != "" { - if len(old.Error.ImportStack) < 2 { - return nil, fmt.Errorf(`internal error: go list gave a %q error with an import stack with fewer than two elements`, errkind) + if len(old.Error.ImportStack) < 1 { + return nil, fmt.Errorf(`internal error: go list gave a %q error with empty import stack`, errkind) + } + importingPkg := old.Error.ImportStack[len(old.Error.ImportStack)-1] + if importingPkg == old.ImportPath { + // Using an older version of Go which put this package itself on top of import + // stack, instead of the importer. Look for importer in second from top + // position. + if len(old.Error.ImportStack) < 2 { + return nil, fmt.Errorf(`internal error: go list gave a %q error with an import stack without importing package`, errkind) + } + importingPkg = old.Error.ImportStack[len(old.Error.ImportStack)-2] } - importingPkg := old.Error.ImportStack[len(old.Error.ImportStack)-2] additionalErrors[importingPkg] = append(additionalErrors[importingPkg], Error{ Pos: old.Error.Pos, Msg: old.Error.Err, @@ -531,7 +559,26 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles), OtherFiles: absJoin(p.Dir, otherFiles(p)...), forTest: p.ForTest, - module: p.Module, + Module: p.Module, + } + + if (state.cfg.Mode&typecheckCgo) != 0 && len(p.CgoFiles) != 0 { + if len(p.CompiledGoFiles) > len(p.GoFiles) { + // We need the cgo definitions, which are in the first + // CompiledGoFile after the non-cgo ones. This is a hack but there + // isn't currently a better way to find it. We also need the pure + // Go files and unprocessed cgo files, all of which are already + // in pkg.GoFiles. + cgoTypes := p.CompiledGoFiles[len(p.GoFiles)] + pkg.CompiledGoFiles = append([]string{cgoTypes}, pkg.GoFiles...) + } else { + // golang/go#38990: go list silently fails to do cgo processing + pkg.CompiledGoFiles = nil + pkg.Errors = append(pkg.Errors, Error{ + Msg: "go list failed to return CompiledGoFiles; https://golang.org/issue/38990?", + Kind: ListError, + }) + } } // Work around https://golang.org/issue/28749: @@ -607,6 +654,39 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse pkg.CompiledGoFiles = pkg.GoFiles } + // Temporary work-around for golang/go#39986. Parse filenames out of + // error messages. This happens if there are unrecoverable syntax + // errors in the source, so we can't match on a specific error message. + if err := p.Error; err != nil && state.shouldAddFilenameFromError(p) { + addFilenameFromPos := func(pos string) bool { + split := strings.Split(pos, ":") + if len(split) < 1 { + return false + } + filename := strings.TrimSpace(split[0]) + if filename == "" { + return false + } + if !filepath.IsAbs(filename) { + filename = filepath.Join(state.cfg.Dir, filename) + } + info, _ := os.Stat(filename) + if info == nil { + return false + } + pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, filename) + pkg.GoFiles = append(pkg.GoFiles, filename) + return true + } + found := addFilenameFromPos(err.Pos) + // In some cases, go list only reports the error position in the + // error text, not the error position. One such case is when the + // file's package name is a keyword (see golang.org/issue/39763). + if !found { + addFilenameFromPos(err.Err) + } + } + if p.Error != nil { msg := strings.TrimSpace(p.Error.Err) // Trim to work around golang.org/issue/32363. // Address golang.org/issue/35964 by appending import stack to error message. @@ -636,7 +716,60 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse return &response, nil } -// getPkgPath finds the package path of a directory if it's relative to a root directory. +func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool { + if len(p.GoFiles) > 0 || len(p.CompiledGoFiles) > 0 { + return false + } + + goV, err := state.getGoVersion() + if err != nil { + return false + } + + // On Go 1.14 and earlier, only add filenames from errors if the import stack is empty. + // The import stack behaves differently for these versions than newer Go versions. + if strings.HasPrefix(goV, "go1.13") || strings.HasPrefix(goV, "go1.14") { + return len(p.Error.ImportStack) == 0 + } + + // On Go 1.15 and later, only parse filenames out of error if there's no import stack, + // or the current package is at the top of the import stack. This is not guaranteed + // to work perfectly, but should avoid some cases where files in errors don't belong to this + // package. + return len(p.Error.ImportStack) == 0 || p.Error.ImportStack[len(p.Error.ImportStack)-1] == p.ImportPath +} + +func (state *golistState) getGoVersion() (string, error) { + state.goVersionOnce.Do(func() { + var b *bytes.Buffer + // Invoke go version. Don't use invokeGo because it will supply build flags, and + // go version doesn't expect build flags. + inv := gocommand.Invocation{ + Verb: "version", + Env: state.cfg.Env, + Logf: state.cfg.Logf, + } + gocmdRunner := state.cfg.gocmdRunner + if gocmdRunner == nil { + gocmdRunner = &gocommand.Runner{} + } + b, _, _, state.goVersionError = gocmdRunner.RunRaw(state.cfg.Context, inv) + if state.goVersionError != nil { + return + } + + sp := strings.Split(b.String(), " ") + if len(sp) < 3 { + state.goVersionError = fmt.Errorf("go version output: expected 'go version ', got '%s'", b.String()) + return + } + state.goVersion = sp[2] + }) + return state.goVersion, state.goVersionError +} + +// getPkgPath finds the package path of a directory if it's relative to a root +// directory. func (state *golistState) getPkgPath(dir string) (string, bool, error) { absDir, err := filepath.Abs(dir) if err != nil { @@ -707,7 +840,7 @@ func golistargs(cfg *Config, words []string) []string { func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, error) { cfg := state.cfg - inv := &gocommand.Invocation{ + inv := gocommand.Invocation{ Verb: verb, Args: args, BuildFlags: cfg.BuildFlags, @@ -715,8 +848,11 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, Logf: cfg.Logf, WorkingDir: cfg.Dir, } - - stdout, stderr, _, err := inv.RunRaw(cfg.Context) + gocmdRunner := cfg.gocmdRunner + if gocmdRunner == nil { + gocmdRunner = &gocommand.Runner{} + } + stdout, stderr, _, err := gocmdRunner.RunRaw(cfg.Context, inv) if err != nil { // Check for 'go' executable not being found. if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound { @@ -727,7 +863,7 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, if !ok { // Catastrophic error: // - context cancellation - return nil, fmt.Errorf("couldn't run 'go': %v", err) + return nil, xerrors.Errorf("couldn't run 'go': %w", err) } // Old go version? diff --git a/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/vendor/golang.org/x/tools/go/packages/golist_overlay.go index 7974a6c9b..874f90134 100644 --- a/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ b/vendor/golang.org/x/tools/go/packages/golist_overlay.go @@ -5,11 +5,15 @@ import ( "fmt" "go/parser" "go/token" + "log" "os" "path/filepath" + "regexp" "sort" "strconv" "strings" + + "golang.org/x/tools/internal/gocommand" ) // processGolistOverlay provides rudimentary support for adding @@ -22,10 +26,15 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif needPkgsSet := make(map[string]bool) modifiedPkgsSet := make(map[string]bool) + pkgOfDir := make(map[string][]*Package) for _, pkg := range response.dr.Packages { // This is an approximation of import path to id. This can be // wrong for tests, vendored packages, and a number of other cases. havePkgs[pkg.PkgPath] = pkg.ID + x := commonDir(pkg.GoFiles) + if x != "" { + pkgOfDir[x] = append(pkgOfDir[x], pkg) + } } // If no new imports are added, it is safe to avoid loading any needPkgs. @@ -64,6 +73,9 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif // to the overlay. continue } + // If all the overlay files belong to a different package, change the + // package name to that package. + maybeFixPackageName(pkgName, isTestFile, pkgOfDir[dir]) nextPackage: for _, p := range response.dr.Packages { if pkgName != p.Name && p.ID != "command-line-arguments" { @@ -80,9 +92,19 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif // because the file is generated in another directory. testVariantOf = p continue nextPackage + } else if !isTestFile && hasTestFiles(p) { + // We're examining a test variant, but the overlaid file is + // a non-test file. Because the overlay implementation + // (currently) only adds a file to one package, skip this + // package, so that we can add the file to the production + // variant of the package. (https://golang.org/issue/36857 + // tracks handling overlays on both the production and test + // variant of a package). + continue nextPackage } - // We must have already seen the package of which this is a test variant. if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath { + // We have already seen the production version of the + // for which p is a test variant. if hasTestFiles(p) { testVariantOf = pkg } @@ -93,8 +115,11 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif } } } - // The overlay could have included an entirely new package. - if pkg == nil { + // The overlay could have included an entirely new package or an + // ad-hoc package. An ad-hoc package is one that we have manually + // constructed from inadequate `go list` results for a file= query. + // It will have the ID command-line-arguments. + if pkg == nil || pkg.ID == "command-line-arguments" { // Try to find the module or gopath dir the file is contained in. // Then for modules, add the module opath to the beginning. pkgPath, ok, err := state.getPkgPath(dir) @@ -104,34 +129,53 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif if !ok { break } + var forTest string // only set for x tests isXTest := strings.HasSuffix(pkgName, "_test") if isXTest { + forTest = pkgPath pkgPath += "_test" } id := pkgPath - if isTestFile && !isXTest { - id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath) - } - // Try to reclaim a package with the same id if it exists in the response. - for _, p := range response.dr.Packages { - if reclaimPackage(p, id, opath, contents) { - pkg = p - break + if isTestFile { + if isXTest { + id = fmt.Sprintf("%s [%s.test]", pkgPath, forTest) + } else { + id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath) } } - // Otherwise, create a new package - if pkg == nil { - pkg = &Package{PkgPath: pkgPath, ID: id, Name: pkgName, Imports: make(map[string]*Package)} - response.addPackage(pkg) - havePkgs[pkg.PkgPath] = id - // Add the production package's sources for a test variant. - if isTestFile && !isXTest && testVariantOf != nil { - pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...) - pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...) - // Add the package under test and its imports to the test variant. - pkg.forTest = testVariantOf.PkgPath - for k, v := range testVariantOf.Imports { - pkg.Imports[k] = &Package{ID: v.ID} + if pkg != nil { + // TODO(rstambler): We should change the package's path and ID + // here. The only issue is that this messes with the roots. + } else { + // Try to reclaim a package with the same ID, if it exists in the response. + for _, p := range response.dr.Packages { + if reclaimPackage(p, id, opath, contents) { + pkg = p + break + } + } + // Otherwise, create a new package. + if pkg == nil { + pkg = &Package{ + PkgPath: pkgPath, + ID: id, + Name: pkgName, + Imports: make(map[string]*Package), + } + response.addPackage(pkg) + havePkgs[pkg.PkgPath] = id + // Add the production package's sources for a test variant. + if isTestFile && !isXTest && testVariantOf != nil { + pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...) + pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...) + // Add the package under test and its imports to the test variant. + pkg.forTest = testVariantOf.PkgPath + for k, v := range testVariantOf.Imports { + pkg.Imports[k] = &Package{ID: v.ID} + } + } + if isXTest { + pkg.forTest = forTest } } } @@ -149,6 +193,8 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif continue } for _, imp := range imports { + // TODO(rstambler): If the package is an x test and the import has + // a test variant, make sure to replace it. if _, found := pkg.Imports[imp]; found { continue } @@ -282,14 +328,25 @@ func (state *golistState) determineRootDirs() (map[string]string, error) { } func (state *golistState) determineRootDirsModules() (map[string]string, error) { + // List all of the modules--the first will be the directory for the main + // module. Any replaced modules will also need to be treated as roots. + // Editing files in the module cache isn't a great idea, so we don't + // plan to ever support that. out, err := state.invokeGo("list", "-m", "-json", "all") if err != nil { - return nil, err + // 'go list all' will fail if we're outside of a module and + // GO111MODULE=on. Try falling back without 'all'. + var innerErr error + out, innerErr = state.invokeGo("list", "-m", "-json") + if innerErr != nil { + return nil, err + } } - m := map[string]string{} - type jsonMod struct{ Path, Dir string } + roots := map[string]string{} + modules := map[string]string{} + var i int for dec := json.NewDecoder(out); dec.More(); { - mod := new(jsonMod) + mod := new(gocommand.ModuleJSON) if err := dec.Decode(mod); err != nil { return nil, err } @@ -299,10 +356,15 @@ func (state *golistState) determineRootDirsModules() (map[string]string, error) if err != nil { return nil, err } - m[absDir] = mod.Path + modules[absDir] = mod.Path + // The first result is the main module. + if i == 0 || mod.Replace != nil && mod.Replace.Path != "" { + roots[absDir] = mod.Path + } } + i++ } - return m, nil + return roots, nil } func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) { @@ -374,3 +436,133 @@ func extractPackageName(filename string, contents []byte) (string, bool) { } return f.Name.Name, true } + +func commonDir(a []string) string { + seen := make(map[string]bool) + x := append([]string{}, a...) + for _, f := range x { + seen[filepath.Dir(f)] = true + } + if len(seen) > 1 { + log.Fatalf("commonDir saw %v for %v", seen, x) + } + for k := range seen { + // len(seen) == 1 + return k + } + return "" // no files +} + +// It is possible that the files in the disk directory dir have a different package +// name from newName, which is deduced from the overlays. If they all have a different +// package name, and they all have the same package name, then that name becomes +// the package name. +// It returns true if it changes the package name, false otherwise. +func maybeFixPackageName(newName string, isTestFile bool, pkgsOfDir []*Package) { + names := make(map[string]int) + for _, p := range pkgsOfDir { + names[p.Name]++ + } + if len(names) != 1 { + // some files are in different packages + return + } + var oldName string + for k := range names { + oldName = k + } + if newName == oldName { + return + } + // We might have a case where all of the package names in the directory are + // the same, but the overlay file is for an x test, which belongs to its + // own package. If the x test does not yet exist on disk, we may not yet + // have its package name on disk, but we should not rename the packages. + // + // We use a heuristic to determine if this file belongs to an x test: + // The test file should have a package name whose package name has a _test + // suffix or looks like "newName_test". + maybeXTest := strings.HasPrefix(oldName+"_test", newName) || strings.HasSuffix(newName, "_test") + if isTestFile && maybeXTest { + return + } + for _, p := range pkgsOfDir { + p.Name = newName + } +} + +// This function is copy-pasted from +// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360. +// It should be deleted when we remove support for overlays from go/packages. +// +// NOTE: This does not handle any ./... or ./ style queries, as this function +// doesn't know the working directory. +// +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Unfortunately, there are two special cases. Quoting "go help packages": +// +// First, /... at the end of the pattern can match an empty string, +// so that net/... matches both net and packages in its subdirectories, like net/http. +// Second, any slash-separated pattern element containing a wildcard never +// participates in a match of the "vendor" element in the path of a vendored +// package, so that ./... does not match packages in subdirectories of +// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. +// Note, however, that a directory named vendor that itself contains code +// is not a vendored package: cmd/vendor would be a command named vendor, +// and the pattern cmd/... matches it. +func matchPattern(pattern string) func(name string) bool { + // Convert pattern to regular expression. + // The strategy for the trailing /... is to nest it in an explicit ? expression. + // The strategy for the vendor exclusion is to change the unmatchable + // vendor strings to a disallowed code point (vendorChar) and to use + // "(anything but that codepoint)*" as the implementation of the ... wildcard. + // This is a bit complicated but the obvious alternative, + // namely a hand-written search like in most shell glob matchers, + // is too easy to make accidentally exponential. + // Using package regexp guarantees linear-time matching. + + const vendorChar = "\x00" + + if strings.Contains(pattern, vendorChar) { + return func(name string) bool { return false } + } + + re := regexp.QuoteMeta(pattern) + re = replaceVendor(re, vendorChar) + switch { + case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): + re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` + case re == vendorChar+`/\.\.\.`: + re = `(/vendor|/` + vendorChar + `/\.\.\.)` + case strings.HasSuffix(re, `/\.\.\.`): + re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` + } + re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`) + + reg := regexp.MustCompile(`^` + re + `$`) + + return func(name string) bool { + if strings.Contains(name, vendorChar) { + return false + } + return reg.MatchString(replaceVendor(name, vendorChar)) + } +} + +// replaceVendor returns the result of replacing +// non-trailing vendor path elements in x with repl. +func replaceVendor(x, repl string) string { + if !strings.Contains(x, "vendor") { + return x + } + elem := strings.Split(x, "/") + for i := 0; i < len(elem)-1; i++ { + if elem[i] == "vendor" { + elem[i] = repl + } + } + return strings.Join(elem, "/") +} diff --git a/vendor/golang.org/x/tools/go/packages/loadmode_string.go b/vendor/golang.org/x/tools/go/packages/loadmode_string.go index aff94a3fe..7ea37e7ee 100644 --- a/vendor/golang.org/x/tools/go/packages/loadmode_string.go +++ b/vendor/golang.org/x/tools/go/packages/loadmode_string.go @@ -38,7 +38,7 @@ var modeStrings = []string{ func (mod LoadMode) String() string { m := mod if m == 0 { - return fmt.Sprintf("LoadMode(0)") + return "LoadMode(0)" } var out []string for i, x := range allModes { diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index 1ac6558c1..04053f1e7 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -21,9 +21,12 @@ import ( "path/filepath" "strings" "sync" + "time" "golang.org/x/tools/go/gcexportdata" + "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/packagesinternal" + "golang.org/x/tools/internal/typesinternal" ) // A LoadMode controls the amount of detail to return when loading. @@ -69,6 +72,13 @@ const ( // NeedTypesSizes adds TypesSizes. NeedTypesSizes + + // typecheckCgo enables full support for type checking cgo. Requires Go 1.15+. + // Modifies CompiledGoFiles and Types, and has no effect on its own. + typecheckCgo + + // NeedModule adds Module. + NeedModule ) const ( @@ -127,6 +137,9 @@ type Config struct { // Env []string + // gocmdRunner guards go command calls from concurrency errors. + gocmdRunner *gocommand.Runner + // BuildFlags is a list of command-line flags to be passed through to // the build system's query tool. BuildFlags []string @@ -178,6 +191,13 @@ type driver func(cfg *Config, patterns ...string) (*driverResponse, error) // driverResponse contains the results for a driver query. type driverResponse struct { + // NotHandled is returned if the request can't be handled by the current + // driver. If an external driver returns a response with NotHandled, the + // rest of the driverResponse is ignored, and go/packages will fallback + // to the next driver. If go/packages is extended in the future to support + // lists of multiple drivers, go/packages will fall back to the next driver. + NotHandled bool + // Sizes, if not nil, is the types.Sizes to use when type checking. Sizes *types.StdSizes @@ -219,14 +239,22 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) { return l.refine(response.Roots, response.Packages...) } -// defaultDriver is a driver that looks for an external driver binary, and if -// it does not find it falls back to the built in go list driver. +// defaultDriver is a driver that implements go/packages' fallback behavior. +// It will try to request to an external driver, if one exists. If there's +// no external driver, or the driver returns a response with NotHandled set, +// defaultDriver will fall back to the go list driver. func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) { driver := findExternalDriver(cfg) if driver == nil { driver = goListDriver } - return driver(cfg, patterns...) + response, err := driver(cfg, patterns...) + if err != nil { + return response, err + } else if response.NotHandled { + return goListDriver(cfg, patterns...) + } + return response, nil } // A Package describes a loaded Go package. @@ -253,7 +281,7 @@ type Package struct { GoFiles []string // CompiledGoFiles lists the absolute file paths of the package's source - // files that were presented to the compiler. + // files that are suitable for type checking. // This may differ from GoFiles if files are processed before compilation. CompiledGoFiles []string @@ -301,16 +329,39 @@ type Package struct { forTest string // module is the module information for the package if it exists. - module *packagesinternal.Module + Module *Module +} + +// Module provides module information for a package. +type Module struct { + Path string // module path + Version string // module version + Replace *Module // replaced by this module + Time *time.Time // time version was created + Main bool // is this the main module? + Indirect bool // is this module only an indirect dependency of main module? + Dir string // directory holding files for this module, if any + GoMod string // path to go.mod file used when loading this module, if any + GoVersion string // go version used in module + Error *ModuleError // error loading module +} + +// ModuleError holds errors loading a module. +type ModuleError struct { + Err string // the error itself } func init() { packagesinternal.GetForTest = func(p interface{}) string { return p.(*Package).forTest } - packagesinternal.GetModule = func(p interface{}) *packagesinternal.Module { - return p.(*Package).module + packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner { + return config.(*Config).gocmdRunner } + packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) { + config.(*Config).gocmdRunner = runner + } + packagesinternal.TypecheckCgo = int(typecheckCgo) } // An Error describes a problem with a package's metadata, syntax, or types. @@ -473,6 +524,9 @@ func newLoader(cfg *Config) *loader { if ld.Config.Env == nil { ld.Config.Env = os.Environ() } + if ld.Config.gocmdRunner == nil { + ld.Config.gocmdRunner = &gocommand.Runner{} + } if ld.Context == nil { ld.Context = context.Background() } @@ -690,6 +744,9 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { if ld.requestedMode&NeedTypesSizes == 0 { ld.pkgs[i].TypesSizes = nil } + if ld.requestedMode&NeedModule == 0 { + ld.pkgs[i].Module = nil + } } return result, nil @@ -865,6 +922,15 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { Error: appendError, Sizes: ld.sizes, } + if (ld.Mode & typecheckCgo) != 0 { + if !typesinternal.SetUsesCgo(tc) { + appendError(Error{ + Msg: "typecheckCgo requires Go 1.15+", + Kind: ListError, + }) + return + } + } types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) lpkg.importErrors = nil // no longer needed diff --git a/vendor/golang.org/x/tools/imports/forward.go b/vendor/golang.org/x/tools/imports/forward.go index dbe5b49a9..a4e40adba 100644 --- a/vendor/golang.org/x/tools/imports/forward.go +++ b/vendor/golang.org/x/tools/imports/forward.go @@ -3,10 +3,10 @@ package imports // import "golang.org/x/tools/imports" import ( - "go/build" + "io/ioutil" "log" - "os" + "golang.org/x/tools/internal/gocommand" intimp "golang.org/x/tools/internal/imports" ) @@ -31,31 +31,34 @@ var Debug = false var LocalPrefix string // Process formats and adjusts imports for the provided file. -// If opt is nil the defaults are used. +// If opt is nil the defaults are used, and if src is nil the source +// is read from the filesystem. // // Note that filename's directory influences which imports can be chosen, // so it is important that filename be accurate. // To process data ``as if'' it were in filename, pass the data as a non-nil src. func Process(filename string, src []byte, opt *Options) ([]byte, error) { + var err error + if src == nil { + src, err = ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + } if opt == nil { opt = &Options{Comments: true, TabIndent: true, TabWidth: 8} } intopt := &intimp.Options{ Env: &intimp.ProcessEnv{ - GOPATH: build.Default.GOPATH, - GOROOT: build.Default.GOROOT, - GOFLAGS: os.Getenv("GOFLAGS"), - GO111MODULE: os.Getenv("GO111MODULE"), - GOPROXY: os.Getenv("GOPROXY"), - GOSUMDB: os.Getenv("GOSUMDB"), - LocalPrefix: LocalPrefix, + GocmdRunner: &gocommand.Runner{}, }, - AllErrors: opt.AllErrors, - Comments: opt.Comments, - FormatOnly: opt.FormatOnly, - Fragment: opt.Fragment, - TabIndent: opt.TabIndent, - TabWidth: opt.TabWidth, + LocalPrefix: LocalPrefix, + AllErrors: opt.AllErrors, + Comments: opt.Comments, + FormatOnly: opt.FormatOnly, + Fragment: opt.Fragment, + TabIndent: opt.TabIndent, + TabWidth: opt.TabWidth, } if Debug { intopt.Env.Logf = log.Printf diff --git a/vendor/golang.org/x/tools/internal/event/core/event.go b/vendor/golang.org/x/tools/internal/event/core/event.go new file mode 100644 index 000000000..e37b49491 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/core/event.go @@ -0,0 +1,85 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package core provides support for event based telemetry. +package core + +import ( + "fmt" + "time" + + "golang.org/x/tools/internal/event/label" +) + +// Event holds the information about an event of note that ocurred. +type Event struct { + at time.Time + + // As events are often on the stack, storing the first few labels directly + // in the event can avoid an allocation at all for the very common cases of + // simple events. + // The length needs to be large enough to cope with the majority of events + // but no so large as to cause undue stack pressure. + // A log message with two values will use 3 labels (one for each value and + // one for the message itself). + + static [3]label.Label // inline storage for the first few labels + dynamic []label.Label // dynamically sized storage for remaining labels +} + +// eventLabelMap implements label.Map for a the labels of an Event. +type eventLabelMap struct { + event Event +} + +func (ev Event) At() time.Time { return ev.at } + +func (ev Event) Format(f fmt.State, r rune) { + if !ev.at.IsZero() { + fmt.Fprint(f, ev.at.Format("2006/01/02 15:04:05 ")) + } + for index := 0; ev.Valid(index); index++ { + if l := ev.Label(index); l.Valid() { + fmt.Fprintf(f, "\n\t%v", l) + } + } +} + +func (ev Event) Valid(index int) bool { + return index >= 0 && index < len(ev.static)+len(ev.dynamic) +} + +func (ev Event) Label(index int) label.Label { + if index < len(ev.static) { + return ev.static[index] + } + return ev.dynamic[index-len(ev.static)] +} + +func (ev Event) Find(key label.Key) label.Label { + for _, l := range ev.static { + if l.Key() == key { + return l + } + } + for _, l := range ev.dynamic { + if l.Key() == key { + return l + } + } + return label.Label{} +} + +func MakeEvent(static [3]label.Label, labels []label.Label) Event { + return Event{ + static: static, + dynamic: labels, + } +} + +// CloneEvent event returns a copy of the event with the time adjusted to at. +func CloneEvent(ev Event, at time.Time) Event { + ev.at = at + return ev +} diff --git a/vendor/golang.org/x/tools/internal/event/core/export.go b/vendor/golang.org/x/tools/internal/event/core/export.go new file mode 100644 index 000000000..05f3a9a57 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/core/export.go @@ -0,0 +1,70 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package core + +import ( + "context" + "sync/atomic" + "time" + "unsafe" + + "golang.org/x/tools/internal/event/label" +) + +// Exporter is a function that handles events. +// It may return a modified context and event. +type Exporter func(context.Context, Event, label.Map) context.Context + +var ( + exporter unsafe.Pointer +) + +// SetExporter sets the global exporter function that handles all events. +// The exporter is called synchronously from the event call site, so it should +// return quickly so as not to hold up user code. +func SetExporter(e Exporter) { + p := unsafe.Pointer(&e) + if e == nil { + // &e is always valid, and so p is always valid, but for the early abort + // of ProcessEvent to be efficient it needs to make the nil check on the + // pointer without having to dereference it, so we make the nil function + // also a nil pointer + p = nil + } + atomic.StorePointer(&exporter, p) +} + +// deliver is called to deliver an event to the supplied exporter. +// it will fill in the time. +func deliver(ctx context.Context, exporter Exporter, ev Event) context.Context { + // add the current time to the event + ev.at = time.Now() + // hand the event off to the current exporter + return exporter(ctx, ev, ev) +} + +// Export is called to deliver an event to the global exporter if set. +func Export(ctx context.Context, ev Event) context.Context { + // get the global exporter and abort early if there is not one + exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter)) + if exporterPtr == nil { + return ctx + } + return deliver(ctx, *exporterPtr, ev) +} + +// ExportPair is called to deliver a start event to the supplied exporter. +// It also returns a function that will deliver the end event to the same +// exporter. +// It will fill in the time. +func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) { + // get the global exporter and abort early if there is not one + exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter)) + if exporterPtr == nil { + return ctx, func() {} + } + ctx = deliver(ctx, *exporterPtr, begin) + return ctx, func() { deliver(ctx, *exporterPtr, end) } +} diff --git a/vendor/golang.org/x/tools/internal/event/core/fast.go b/vendor/golang.org/x/tools/internal/event/core/fast.go new file mode 100644 index 000000000..06c1d4615 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/core/fast.go @@ -0,0 +1,77 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package core + +import ( + "context" + + "golang.org/x/tools/internal/event/keys" + "golang.org/x/tools/internal/event/label" +) + +// Log1 takes a message and one label delivers a log event to the exporter. +// It is a customized version of Print that is faster and does no allocation. +func Log1(ctx context.Context, message string, t1 label.Label) { + Export(ctx, MakeEvent([3]label.Label{ + keys.Msg.Of(message), + t1, + }, nil)) +} + +// Log2 takes a message and two labels and delivers a log event to the exporter. +// It is a customized version of Print that is faster and does no allocation. +func Log2(ctx context.Context, message string, t1 label.Label, t2 label.Label) { + Export(ctx, MakeEvent([3]label.Label{ + keys.Msg.Of(message), + t1, + t2, + }, nil)) +} + +// Metric1 sends a label event to the exporter with the supplied labels. +func Metric1(ctx context.Context, t1 label.Label) context.Context { + return Export(ctx, MakeEvent([3]label.Label{ + keys.Metric.New(), + t1, + }, nil)) +} + +// Metric2 sends a label event to the exporter with the supplied labels. +func Metric2(ctx context.Context, t1, t2 label.Label) context.Context { + return Export(ctx, MakeEvent([3]label.Label{ + keys.Metric.New(), + t1, + t2, + }, nil)) +} + +// Start1 sends a span start event with the supplied label list to the exporter. +// It also returns a function that will end the span, which should normally be +// deferred. +func Start1(ctx context.Context, name string, t1 label.Label) (context.Context, func()) { + return ExportPair(ctx, + MakeEvent([3]label.Label{ + keys.Start.Of(name), + t1, + }, nil), + MakeEvent([3]label.Label{ + keys.End.New(), + }, nil)) +} + +// Start2 sends a span start event with the supplied label list to the exporter. +// It also returns a function that will end the span, which should normally be +// deferred. +func Start2(ctx context.Context, name string, t1, t2 label.Label) (context.Context, func()) { + return ExportPair(ctx, + MakeEvent([3]label.Label{ + keys.Start.Of(name), + t1, + t2, + }, nil), + MakeEvent([3]label.Label{ + keys.End.New(), + }, nil)) +} diff --git a/vendor/golang.org/x/tools/internal/event/doc.go b/vendor/golang.org/x/tools/internal/event/doc.go new file mode 100644 index 000000000..5dc6e6bab --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/doc.go @@ -0,0 +1,7 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package event provides a set of packages that cover the main +// concepts of telemetry in an implementation agnostic way. +package event diff --git a/vendor/golang.org/x/tools/internal/event/event.go b/vendor/golang.org/x/tools/internal/event/event.go new file mode 100644 index 000000000..4d55e577d --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/event.go @@ -0,0 +1,127 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package event + +import ( + "context" + + "golang.org/x/tools/internal/event/core" + "golang.org/x/tools/internal/event/keys" + "golang.org/x/tools/internal/event/label" +) + +// Exporter is a function that handles events. +// It may return a modified context and event. +type Exporter func(context.Context, core.Event, label.Map) context.Context + +// SetExporter sets the global exporter function that handles all events. +// The exporter is called synchronously from the event call site, so it should +// return quickly so as not to hold up user code. +func SetExporter(e Exporter) { + core.SetExporter(core.Exporter(e)) +} + +// Log takes a message and a label list and combines them into a single event +// before delivering them to the exporter. +func Log(ctx context.Context, message string, labels ...label.Label) { + core.Export(ctx, core.MakeEvent([3]label.Label{ + keys.Msg.Of(message), + }, labels)) +} + +// IsLog returns true if the event was built by the Log function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsLog(ev core.Event) bool { + return ev.Label(0).Key() == keys.Msg +} + +// Error takes a message and a label list and combines them into a single event +// before delivering them to the exporter. It captures the error in the +// delivered event. +func Error(ctx context.Context, message string, err error, labels ...label.Label) { + core.Export(ctx, core.MakeEvent([3]label.Label{ + keys.Msg.Of(message), + keys.Err.Of(err), + }, labels)) +} + +// IsError returns true if the event was built by the Error function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsError(ev core.Event) bool { + return ev.Label(0).Key() == keys.Msg && + ev.Label(1).Key() == keys.Err +} + +// Metric sends a label event to the exporter with the supplied labels. +func Metric(ctx context.Context, labels ...label.Label) { + core.Export(ctx, core.MakeEvent([3]label.Label{ + keys.Metric.New(), + }, labels)) +} + +// IsMetric returns true if the event was built by the Metric function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsMetric(ev core.Event) bool { + return ev.Label(0).Key() == keys.Metric +} + +// Label sends a label event to the exporter with the supplied labels. +func Label(ctx context.Context, labels ...label.Label) context.Context { + return core.Export(ctx, core.MakeEvent([3]label.Label{ + keys.Label.New(), + }, labels)) +} + +// IsLabel returns true if the event was built by the Label function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsLabel(ev core.Event) bool { + return ev.Label(0).Key() == keys.Label +} + +// Start sends a span start event with the supplied label list to the exporter. +// It also returns a function that will end the span, which should normally be +// deferred. +func Start(ctx context.Context, name string, labels ...label.Label) (context.Context, func()) { + return core.ExportPair(ctx, + core.MakeEvent([3]label.Label{ + keys.Start.Of(name), + }, labels), + core.MakeEvent([3]label.Label{ + keys.End.New(), + }, nil)) +} + +// IsStart returns true if the event was built by the Start function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsStart(ev core.Event) bool { + return ev.Label(0).Key() == keys.Start +} + +// IsEnd returns true if the event was built by the End function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsEnd(ev core.Event) bool { + return ev.Label(0).Key() == keys.End +} + +// Detach returns a context without an associated span. +// This allows the creation of spans that are not children of the current span. +func Detach(ctx context.Context) context.Context { + return core.Export(ctx, core.MakeEvent([3]label.Label{ + keys.Detach.New(), + }, nil)) +} + +// IsDetach returns true if the event was built by the Detach function. +// It is intended to be used in exporters to identify the semantics of the +// event when deciding what to do with it. +func IsDetach(ev core.Event) bool { + return ev.Label(0).Key() == keys.Detach +} diff --git a/vendor/golang.org/x/tools/internal/event/keys/keys.go b/vendor/golang.org/x/tools/internal/event/keys/keys.go new file mode 100644 index 000000000..a02206e30 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/keys/keys.go @@ -0,0 +1,564 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package keys + +import ( + "fmt" + "io" + "math" + "strconv" + + "golang.org/x/tools/internal/event/label" +) + +// Value represents a key for untyped values. +type Value struct { + name string + description string +} + +// New creates a new Key for untyped values. +func New(name, description string) *Value { + return &Value{name: name, description: description} +} + +func (k *Value) Name() string { return k.name } +func (k *Value) Description() string { return k.description } + +func (k *Value) Format(w io.Writer, buf []byte, l label.Label) { + fmt.Fprint(w, k.From(l)) +} + +// Get can be used to get a label for the key from a label.Map. +func (k *Value) Get(lm label.Map) interface{} { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return nil +} + +// From can be used to get a value from a Label. +func (k *Value) From(t label.Label) interface{} { return t.UnpackValue() } + +// Of creates a new Label with this key and the supplied value. +func (k *Value) Of(value interface{}) label.Label { return label.OfValue(k, value) } + +// Tag represents a key for tagging labels that have no value. +// These are used when the existence of the label is the entire information it +// carries, such as marking events to be of a specific kind, or from a specific +// package. +type Tag struct { + name string + description string +} + +// NewTag creates a new Key for tagging labels. +func NewTag(name, description string) *Tag { + return &Tag{name: name, description: description} +} + +func (k *Tag) Name() string { return k.name } +func (k *Tag) Description() string { return k.description } + +func (k *Tag) Format(w io.Writer, buf []byte, l label.Label) {} + +// New creates a new Label with this key. +func (k *Tag) New() label.Label { return label.OfValue(k, nil) } + +// Int represents a key +type Int struct { + name string + description string +} + +// NewInt creates a new Key for int values. +func NewInt(name, description string) *Int { + return &Int{name: name, description: description} +} + +func (k *Int) Name() string { return k.name } +func (k *Int) Description() string { return k.description } + +func (k *Int) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Int) Of(v int) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *Int) Get(lm label.Map) int { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Int) From(t label.Label) int { return int(t.Unpack64()) } + +// Int8 represents a key +type Int8 struct { + name string + description string +} + +// NewInt8 creates a new Key for int8 values. +func NewInt8(name, description string) *Int8 { + return &Int8{name: name, description: description} +} + +func (k *Int8) Name() string { return k.name } +func (k *Int8) Description() string { return k.description } + +func (k *Int8) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Int8) Of(v int8) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *Int8) Get(lm label.Map) int8 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Int8) From(t label.Label) int8 { return int8(t.Unpack64()) } + +// Int16 represents a key +type Int16 struct { + name string + description string +} + +// NewInt16 creates a new Key for int16 values. +func NewInt16(name, description string) *Int16 { + return &Int16{name: name, description: description} +} + +func (k *Int16) Name() string { return k.name } +func (k *Int16) Description() string { return k.description } + +func (k *Int16) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Int16) Of(v int16) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *Int16) Get(lm label.Map) int16 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Int16) From(t label.Label) int16 { return int16(t.Unpack64()) } + +// Int32 represents a key +type Int32 struct { + name string + description string +} + +// NewInt32 creates a new Key for int32 values. +func NewInt32(name, description string) *Int32 { + return &Int32{name: name, description: description} +} + +func (k *Int32) Name() string { return k.name } +func (k *Int32) Description() string { return k.description } + +func (k *Int32) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Int32) Of(v int32) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *Int32) Get(lm label.Map) int32 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Int32) From(t label.Label) int32 { return int32(t.Unpack64()) } + +// Int64 represents a key +type Int64 struct { + name string + description string +} + +// NewInt64 creates a new Key for int64 values. +func NewInt64(name, description string) *Int64 { + return &Int64{name: name, description: description} +} + +func (k *Int64) Name() string { return k.name } +func (k *Int64) Description() string { return k.description } + +func (k *Int64) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendInt(buf, k.From(l), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Int64) Of(v int64) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *Int64) Get(lm label.Map) int64 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Int64) From(t label.Label) int64 { return int64(t.Unpack64()) } + +// UInt represents a key +type UInt struct { + name string + description string +} + +// NewUInt creates a new Key for uint values. +func NewUInt(name, description string) *UInt { + return &UInt{name: name, description: description} +} + +func (k *UInt) Name() string { return k.name } +func (k *UInt) Description() string { return k.description } + +func (k *UInt) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *UInt) Of(v uint) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *UInt) Get(lm label.Map) uint { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *UInt) From(t label.Label) uint { return uint(t.Unpack64()) } + +// UInt8 represents a key +type UInt8 struct { + name string + description string +} + +// NewUInt8 creates a new Key for uint8 values. +func NewUInt8(name, description string) *UInt8 { + return &UInt8{name: name, description: description} +} + +func (k *UInt8) Name() string { return k.name } +func (k *UInt8) Description() string { return k.description } + +func (k *UInt8) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *UInt8) Of(v uint8) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *UInt8) Get(lm label.Map) uint8 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *UInt8) From(t label.Label) uint8 { return uint8(t.Unpack64()) } + +// UInt16 represents a key +type UInt16 struct { + name string + description string +} + +// NewUInt16 creates a new Key for uint16 values. +func NewUInt16(name, description string) *UInt16 { + return &UInt16{name: name, description: description} +} + +func (k *UInt16) Name() string { return k.name } +func (k *UInt16) Description() string { return k.description } + +func (k *UInt16) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *UInt16) Of(v uint16) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *UInt16) Get(lm label.Map) uint16 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *UInt16) From(t label.Label) uint16 { return uint16(t.Unpack64()) } + +// UInt32 represents a key +type UInt32 struct { + name string + description string +} + +// NewUInt32 creates a new Key for uint32 values. +func NewUInt32(name, description string) *UInt32 { + return &UInt32{name: name, description: description} +} + +func (k *UInt32) Name() string { return k.name } +func (k *UInt32) Description() string { return k.description } + +func (k *UInt32) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *UInt32) Of(v uint32) label.Label { return label.Of64(k, uint64(v)) } + +// Get can be used to get a label for the key from a label.Map. +func (k *UInt32) Get(lm label.Map) uint32 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *UInt32) From(t label.Label) uint32 { return uint32(t.Unpack64()) } + +// UInt64 represents a key +type UInt64 struct { + name string + description string +} + +// NewUInt64 creates a new Key for uint64 values. +func NewUInt64(name, description string) *UInt64 { + return &UInt64{name: name, description: description} +} + +func (k *UInt64) Name() string { return k.name } +func (k *UInt64) Description() string { return k.description } + +func (k *UInt64) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendUint(buf, k.From(l), 10)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *UInt64) Of(v uint64) label.Label { return label.Of64(k, v) } + +// Get can be used to get a label for the key from a label.Map. +func (k *UInt64) Get(lm label.Map) uint64 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *UInt64) From(t label.Label) uint64 { return t.Unpack64() } + +// Float32 represents a key +type Float32 struct { + name string + description string +} + +// NewFloat32 creates a new Key for float32 values. +func NewFloat32(name, description string) *Float32 { + return &Float32{name: name, description: description} +} + +func (k *Float32) Name() string { return k.name } +func (k *Float32) Description() string { return k.description } + +func (k *Float32) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendFloat(buf, float64(k.From(l)), 'E', -1, 32)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Float32) Of(v float32) label.Label { + return label.Of64(k, uint64(math.Float32bits(v))) +} + +// Get can be used to get a label for the key from a label.Map. +func (k *Float32) Get(lm label.Map) float32 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Float32) From(t label.Label) float32 { + return math.Float32frombits(uint32(t.Unpack64())) +} + +// Float64 represents a key +type Float64 struct { + name string + description string +} + +// NewFloat64 creates a new Key for int64 values. +func NewFloat64(name, description string) *Float64 { + return &Float64{name: name, description: description} +} + +func (k *Float64) Name() string { return k.name } +func (k *Float64) Description() string { return k.description } + +func (k *Float64) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendFloat(buf, k.From(l), 'E', -1, 64)) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Float64) Of(v float64) label.Label { + return label.Of64(k, math.Float64bits(v)) +} + +// Get can be used to get a label for the key from a label.Map. +func (k *Float64) Get(lm label.Map) float64 { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return 0 +} + +// From can be used to get a value from a Label. +func (k *Float64) From(t label.Label) float64 { + return math.Float64frombits(t.Unpack64()) +} + +// String represents a key +type String struct { + name string + description string +} + +// NewString creates a new Key for int64 values. +func NewString(name, description string) *String { + return &String{name: name, description: description} +} + +func (k *String) Name() string { return k.name } +func (k *String) Description() string { return k.description } + +func (k *String) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendQuote(buf, k.From(l))) +} + +// Of creates a new Label with this key and the supplied value. +func (k *String) Of(v string) label.Label { return label.OfString(k, v) } + +// Get can be used to get a label for the key from a label.Map. +func (k *String) Get(lm label.Map) string { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return "" +} + +// From can be used to get a value from a Label. +func (k *String) From(t label.Label) string { return t.UnpackString() } + +// Boolean represents a key +type Boolean struct { + name string + description string +} + +// NewBoolean creates a new Key for bool values. +func NewBoolean(name, description string) *Boolean { + return &Boolean{name: name, description: description} +} + +func (k *Boolean) Name() string { return k.name } +func (k *Boolean) Description() string { return k.description } + +func (k *Boolean) Format(w io.Writer, buf []byte, l label.Label) { + w.Write(strconv.AppendBool(buf, k.From(l))) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Boolean) Of(v bool) label.Label { + if v { + return label.Of64(k, 1) + } + return label.Of64(k, 0) +} + +// Get can be used to get a label for the key from a label.Map. +func (k *Boolean) Get(lm label.Map) bool { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return false +} + +// From can be used to get a value from a Label. +func (k *Boolean) From(t label.Label) bool { return t.Unpack64() > 0 } + +// Error represents a key +type Error struct { + name string + description string +} + +// NewError creates a new Key for int64 values. +func NewError(name, description string) *Error { + return &Error{name: name, description: description} +} + +func (k *Error) Name() string { return k.name } +func (k *Error) Description() string { return k.description } + +func (k *Error) Format(w io.Writer, buf []byte, l label.Label) { + io.WriteString(w, k.From(l).Error()) +} + +// Of creates a new Label with this key and the supplied value. +func (k *Error) Of(v error) label.Label { return label.OfValue(k, v) } + +// Get can be used to get a label for the key from a label.Map. +func (k *Error) Get(lm label.Map) error { + if t := lm.Find(k); t.Valid() { + return k.From(t) + } + return nil +} + +// From can be used to get a value from a Label. +func (k *Error) From(t label.Label) error { + err, _ := t.UnpackValue().(error) + return err +} diff --git a/vendor/golang.org/x/tools/internal/event/keys/standard.go b/vendor/golang.org/x/tools/internal/event/keys/standard.go new file mode 100644 index 000000000..7e9586659 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/keys/standard.go @@ -0,0 +1,22 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package keys + +var ( + // Msg is a key used to add message strings to label lists. + Msg = NewString("message", "a readable message") + // Label is a key used to indicate an event adds labels to the context. + Label = NewTag("label", "a label context marker") + // Start is used for things like traces that have a name. + Start = NewString("start", "span start") + // Metric is a key used to indicate an event records metrics. + End = NewTag("end", "a span end marker") + // Metric is a key used to indicate an event records metrics. + Detach = NewTag("detach", "a span detach marker") + // Err is a key used to add error values to label lists. + Err = NewError("error", "an error that occurred") + // Metric is a key used to indicate an event records metrics. + Metric = NewTag("metric", "a metric event marker") +) diff --git a/vendor/golang.org/x/tools/internal/event/label/label.go b/vendor/golang.org/x/tools/internal/event/label/label.go new file mode 100644 index 000000000..b55c12eb2 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/label/label.go @@ -0,0 +1,213 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package label + +import ( + "fmt" + "io" + "reflect" + "unsafe" +) + +// Key is used as the identity of a Label. +// Keys are intended to be compared by pointer only, the name should be unique +// for communicating with external systems, but it is not required or enforced. +type Key interface { + // Name returns the key name. + Name() string + // Description returns a string that can be used to describe the value. + Description() string + + // Format is used in formatting to append the value of the label to the + // supplied buffer. + // The formatter may use the supplied buf as a scratch area to avoid + // allocations. + Format(w io.Writer, buf []byte, l Label) +} + +// Label holds a key and value pair. +// It is normally used when passing around lists of labels. +type Label struct { + key Key + packed uint64 + untyped interface{} +} + +// Map is the interface to a collection of Labels indexed by key. +type Map interface { + // Find returns the label that matches the supplied key. + Find(key Key) Label +} + +// List is the interface to something that provides an iterable +// list of labels. +// Iteration should start from 0 and continue until Valid returns false. +type List interface { + // Valid returns true if the index is within range for the list. + // It does not imply the label at that index will itself be valid. + Valid(index int) bool + // Label returns the label at the given index. + Label(index int) Label +} + +// list implements LabelList for a list of Labels. +type list struct { + labels []Label +} + +// filter wraps a LabelList filtering out specific labels. +type filter struct { + keys []Key + underlying List +} + +// listMap implements LabelMap for a simple list of labels. +type listMap struct { + labels []Label +} + +// mapChain implements LabelMap for a list of underlying LabelMap. +type mapChain struct { + maps []Map +} + +// OfValue creates a new label from the key and value. +// This method is for implementing new key types, label creation should +// normally be done with the Of method of the key. +func OfValue(k Key, value interface{}) Label { return Label{key: k, untyped: value} } + +// UnpackValue assumes the label was built using LabelOfValue and returns the value +// that was passed to that constructor. +// This method is for implementing new key types, for type safety normal +// access should be done with the From method of the key. +func (t Label) UnpackValue() interface{} { return t.untyped } + +// Of64 creates a new label from a key and a uint64. This is often +// used for non uint64 values that can be packed into a uint64. +// This method is for implementing new key types, label creation should +// normally be done with the Of method of the key. +func Of64(k Key, v uint64) Label { return Label{key: k, packed: v} } + +// Unpack64 assumes the label was built using LabelOf64 and returns the value that +// was passed to that constructor. +// This method is for implementing new key types, for type safety normal +// access should be done with the From method of the key. +func (t Label) Unpack64() uint64 { return t.packed } + +// OfString creates a new label from a key and a string. +// This method is for implementing new key types, label creation should +// normally be done with the Of method of the key. +func OfString(k Key, v string) Label { + hdr := (*reflect.StringHeader)(unsafe.Pointer(&v)) + return Label{ + key: k, + packed: uint64(hdr.Len), + untyped: unsafe.Pointer(hdr.Data), + } +} + +// UnpackString assumes the label was built using LabelOfString and returns the +// value that was passed to that constructor. +// This method is for implementing new key types, for type safety normal +// access should be done with the From method of the key. +func (t Label) UnpackString() string { + var v string + hdr := (*reflect.StringHeader)(unsafe.Pointer(&v)) + hdr.Data = uintptr(t.untyped.(unsafe.Pointer)) + hdr.Len = int(t.packed) + return *(*string)(unsafe.Pointer(hdr)) +} + +// Valid returns true if the Label is a valid one (it has a key). +func (t Label) Valid() bool { return t.key != nil } + +// Key returns the key of this Label. +func (t Label) Key() Key { return t.key } + +// Format is used for debug printing of labels. +func (t Label) Format(f fmt.State, r rune) { + if !t.Valid() { + io.WriteString(f, `nil`) + return + } + io.WriteString(f, t.Key().Name()) + io.WriteString(f, "=") + var buf [128]byte + t.Key().Format(f, buf[:0], t) +} + +func (l *list) Valid(index int) bool { + return index >= 0 && index < len(l.labels) +} + +func (l *list) Label(index int) Label { + return l.labels[index] +} + +func (f *filter) Valid(index int) bool { + return f.underlying.Valid(index) +} + +func (f *filter) Label(index int) Label { + l := f.underlying.Label(index) + for _, f := range f.keys { + if l.Key() == f { + return Label{} + } + } + return l +} + +func (lm listMap) Find(key Key) Label { + for _, l := range lm.labels { + if l.Key() == key { + return l + } + } + return Label{} +} + +func (c mapChain) Find(key Key) Label { + for _, src := range c.maps { + l := src.Find(key) + if l.Valid() { + return l + } + } + return Label{} +} + +var emptyList = &list{} + +func NewList(labels ...Label) List { + if len(labels) == 0 { + return emptyList + } + return &list{labels: labels} +} + +func Filter(l List, keys ...Key) List { + if len(keys) == 0 { + return l + } + return &filter{keys: keys, underlying: l} +} + +func NewMap(labels ...Label) Map { + return listMap{labels: labels} +} + +func MergeMaps(srcs ...Map) Map { + var nonNil []Map + for _, src := range srcs { + if src != nil { + nonNil = append(nonNil, src) + } + } + if len(nonNil) == 1 { + return nonNil[0] + } + return mapChain{maps: nonNil} +} diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go index 468db4010..f516e1762 100644 --- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go @@ -1,3 +1,7 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + // Package gocommand is a helper for calling the go command. package gocommand @@ -8,10 +12,119 @@ import ( "io" "os" "os/exec" + "regexp" "strings" + "sync" "time" + + "golang.org/x/tools/internal/event" ) +// An Runner will run go command invocations and serialize +// them if it sees a concurrency error. +type Runner struct { + // once guards the runner initialization. + once sync.Once + + // inFlight tracks available workers. + inFlight chan struct{} + + // serialized guards the ability to run a go command serially, + // to avoid deadlocks when claiming workers. + serialized chan struct{} +} + +const maxInFlight = 10 + +func (runner *Runner) initialize() { + runner.once.Do(func() { + runner.inFlight = make(chan struct{}, maxInFlight) + runner.serialized = make(chan struct{}, 1) + }) +} + +// 1.13: go: updates to go.mod needed, but contents have changed +// 1.14: go: updating go.mod: existing contents have changed since last read +var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`) + +// Run is a convenience wrapper around RunRaw. +// It returns only stdout and a "friendly" error. +func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, error) { + stdout, _, friendly, _ := runner.RunRaw(ctx, inv) + return stdout, friendly +} + +// RunPiped runs the invocation serially, always waiting for any concurrent +// invocations to complete first. +func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) error { + _, err := runner.runPiped(ctx, inv, stdout, stderr) + return err +} + +// RunRaw runs the invocation, serializing requests only if they fight over +// go.mod changes. +func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) { + // Make sure the runner is always initialized. + runner.initialize() + + // First, try to run the go command concurrently. + stdout, stderr, friendlyErr, err := runner.runConcurrent(ctx, inv) + + // If we encounter a load concurrency error, we need to retry serially. + if friendlyErr == nil || !modConcurrencyError.MatchString(friendlyErr.Error()) { + return stdout, stderr, friendlyErr, err + } + event.Error(ctx, "Load concurrency error, will retry serially", err) + + // Run serially by calling runPiped. + stdout.Reset() + stderr.Reset() + friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr) + return stdout, stderr, friendlyErr, err +} + +func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) { + // Wait for 1 worker to become available. + select { + case <-ctx.Done(): + return nil, nil, nil, ctx.Err() + case runner.inFlight <- struct{}{}: + defer func() { <-runner.inFlight }() + } + + stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{} + friendlyErr, err := inv.runWithFriendlyError(ctx, stdout, stderr) + return stdout, stderr, friendlyErr, err +} + +func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) (error, error) { + // Make sure the runner is always initialized. + runner.initialize() + + // Acquire the serialization lock. This avoids deadlocks between two + // runPiped commands. + select { + case <-ctx.Done(): + return nil, ctx.Err() + case runner.serialized <- struct{}{}: + defer func() { <-runner.serialized }() + } + + // Wait for all in-progress go commands to return before proceeding, + // to avoid load concurrency errors. + for i := 0; i < maxInFlight; i++ { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case runner.inFlight <- struct{}{}: + // Make sure we always "return" any workers we took. + defer func() { <-runner.inFlight }() + } + } + + return inv.runWithFriendlyError(ctx, stdout, stderr) +} + // An Invocation represents a call to the go command. type Invocation struct { Verb string @@ -22,20 +135,10 @@ type Invocation struct { Logf func(format string, args ...interface{}) } -// Run runs the invocation, returning its stdout and an error suitable for -// human consumption, including stderr. -func (i *Invocation) Run(ctx context.Context) (*bytes.Buffer, error) { - stdout, _, friendly, _ := i.RunRaw(ctx) - return stdout, friendly -} - -// RunRaw is like RunPiped, but also returns the raw stderr and error for callers -// that want to do low-level error handling/recovery. -func (i *Invocation) RunRaw(ctx context.Context) (stdout *bytes.Buffer, stderr *bytes.Buffer, friendlyError error, rawError error) { - stdout = &bytes.Buffer{} - stderr = &bytes.Buffer{} - rawError = i.RunPiped(ctx, stdout, stderr) +func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io.Writer) (friendlyError error, rawError error) { + rawError = i.run(ctx, stdout, stderr) if rawError != nil { + friendlyError = rawError // Check for 'go' executable not being found. if ee, ok := rawError.(*exec.Error); ok && ee.Err == exec.ErrNotFound { friendlyError = fmt.Errorf("go command required, not found: %v", ee) @@ -43,13 +146,12 @@ func (i *Invocation) RunRaw(ctx context.Context) (stdout *bytes.Buffer, stderr * if ctx.Err() != nil { friendlyError = ctx.Err() } - friendlyError = fmt.Errorf("err: %v: stderr: %s", rawError, stderr) + friendlyError = fmt.Errorf("err: %v: stderr: %s", friendlyError, stderr) } return } -// RunPiped is like Run, but relies on the given stdout/stderr -func (i *Invocation) RunPiped(ctx context.Context, stdout, stderr io.Writer) error { +func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error { log := i.Logf if log == nil { log = func(string, ...interface{}) {} @@ -78,9 +180,11 @@ func (i *Invocation) RunPiped(ctx context.Context, stdout, stderr io.Writer) err // The Go stdlib has a special feature where if the cwd and the PWD are the // same node then it trusts the PWD, so by setting it in the env for the child // process we fix up all the paths returned by the go command. - cmd.Env = append(append([]string{}, i.Env...), "PWD="+i.WorkingDir) - cmd.Dir = i.WorkingDir - + cmd.Env = append(os.Environ(), i.Env...) + if i.WorkingDir != "" { + cmd.Env = append(cmd.Env, "PWD="+i.WorkingDir) + cmd.Dir = i.WorkingDir + } defer func(start time.Time) { log("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now()) return runCmdContext(ctx, cmd) diff --git a/vendor/golang.org/x/tools/internal/gocommand/vendor.go b/vendor/golang.org/x/tools/internal/gocommand/vendor.go new file mode 100644 index 000000000..1cd8d8473 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/gocommand/vendor.go @@ -0,0 +1,102 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gocommand + +import ( + "bytes" + "context" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "golang.org/x/mod/semver" +) + +// ModuleJSON holds information about a module. +type ModuleJSON struct { + Path string // module path + Replace *ModuleJSON // replaced by this module + Main bool // is this the main module? + Indirect bool // is this module only an indirect dependency of main module? + Dir string // directory holding files for this module, if any + GoMod string // path to go.mod file for this module, if any + GoVersion string // go version used in module +} + +var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`) + +// VendorEnabled reports whether vendoring is enabled. It takes a *Runner to execute Go commands +// with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields, +// of which only Verb and Args are modified to run the appropriate Go command. +// Inspired by setDefaultBuildMod in modload/init.go +func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) { + mainMod, go114, err := getMainModuleAnd114(ctx, inv, r) + if err != nil { + return nil, false, err + } + + // We check the GOFLAGS to see if there is anything overridden or not. + inv.Verb = "env" + inv.Args = []string{"GOFLAGS"} + stdout, err := r.Run(ctx, inv) + if err != nil { + return nil, false, err + } + goflags := string(bytes.TrimSpace(stdout.Bytes())) + matches := modFlagRegexp.FindStringSubmatch(goflags) + var modFlag string + if len(matches) != 0 { + modFlag = matches[1] + } + if modFlag != "" { + // Don't override an explicit '-mod=' argument. + return mainMod, modFlag == "vendor", nil + } + if mainMod == nil || !go114 { + return mainMod, false, nil + } + // Check 1.14's automatic vendor mode. + if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() { + if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 { + // The Go version is at least 1.14, and a vendor directory exists. + // Set -mod=vendor by default. + return mainMod, true, nil + } + } + return mainMod, false, nil +} + +// getMainModuleAnd114 gets the main module's information and whether the +// go command in use is 1.14+. This is the information needed to figure out +// if vendoring should be enabled. +func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) { + const format = `{{.Path}} +{{.Dir}} +{{.GoMod}} +{{.GoVersion}} +{{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}} +` + inv.Verb = "list" + inv.Args = []string{"-m", "-f", format} + stdout, err := r.Run(ctx, inv) + if err != nil { + return nil, false, err + } + + lines := strings.Split(stdout.String(), "\n") + if len(lines) < 5 { + return nil, false, fmt.Errorf("unexpected stdout: %q", stdout.String()) + } + mod := &ModuleJSON{ + Path: lines[0], + Dir: lines[1], + GoMod: lines[2], + GoVersion: lines[3], + Main: true, + } + return mod, lines[4] == "go1.14", nil +} diff --git a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go index 390cb9db7..925ff5356 100644 --- a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go +++ b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go @@ -10,7 +10,6 @@ import ( "bufio" "bytes" "fmt" - "go/build" "io/ioutil" "log" "os" @@ -47,16 +46,6 @@ type Root struct { Type RootType } -// SrcDirsRoots returns the roots from build.Default.SrcDirs(). Not modules-compatible. -func SrcDirsRoots(ctx *build.Context) []Root { - var roots []Root - roots = append(roots, Root{filepath.Join(ctx.GOROOT, "src"), RootGOROOT}) - for _, p := range filepath.SplitList(ctx.GOPATH) { - roots = append(roots, Root{filepath.Join(p, "src"), RootGOPATH}) - } - return roots -} - // Walk walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. // For each package found, add will be called (concurrently) with the absolute // paths of the containing source directory and the package directory. diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go index 92a23439f..613afc4d6 100644 --- a/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/vendor/golang.org/x/tools/internal/imports/fix.go @@ -7,6 +7,7 @@ package imports import ( "bytes" "context" + "encoding/json" "fmt" "go/ast" "go/build" @@ -31,35 +32,36 @@ import ( // importToGroup is a list of functions which map from an import path to // a group number. -var importToGroup = []func(env *ProcessEnv, importPath string) (num int, ok bool){ - func(env *ProcessEnv, importPath string) (num int, ok bool) { - if env.LocalPrefix == "" { +var importToGroup = []func(localPrefix, importPath string) (num int, ok bool){ + func(localPrefix, importPath string) (num int, ok bool) { + if localPrefix == "" { return } - for _, p := range strings.Split(env.LocalPrefix, ",") { + for _, p := range strings.Split(localPrefix, ",") { if strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, "/") == importPath { return 3, true } } return }, - func(_ *ProcessEnv, importPath string) (num int, ok bool) { + func(_, importPath string) (num int, ok bool) { if strings.HasPrefix(importPath, "appengine") { return 2, true } return }, - func(_ *ProcessEnv, importPath string) (num int, ok bool) { - if strings.Contains(importPath, ".") { + func(_, importPath string) (num int, ok bool) { + firstComponent := strings.Split(importPath, "/")[0] + if strings.Contains(firstComponent, ".") { return 1, true } return }, } -func importGroup(env *ProcessEnv, importPath string) int { +func importGroup(localPrefix, importPath string) int { for _, fn := range importToGroup { - if n, ok := fn(env, importPath); ok { + if n, ok := fn(localPrefix, importPath); ok { return n } } @@ -276,7 +278,12 @@ func (p *pass) loadPackageNames(imports []*ImportInfo) error { unknown = append(unknown, imp.ImportPath) } - names, err := p.env.GetResolver().loadPackageNames(unknown, p.srcDir) + resolver, err := p.env.GetResolver() + if err != nil { + return err + } + + names, err := resolver.loadPackageNames(unknown, p.srcDir) if err != nil { return err } @@ -566,7 +573,9 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv return fixes, nil } - addStdlibCandidates(p, p.missingRefs) + if err := addStdlibCandidates(p, p.missingRefs); err != nil { + return nil, err + } p.assumeSiblingImportsValid() if fixes, done := p.fix(); done { return fixes, nil @@ -594,15 +603,19 @@ func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filena notSelf := func(p *pkg) bool { return p.packageName != filePkg || p.dir != filepath.Dir(filename) } + goenv, err := env.goEnv() + if err != nil { + return err + } // Start off with the standard library. for importPath, exports := range stdlib { p := &pkg{ - dir: filepath.Join(env.GOROOT, "src", importPath), + dir: filepath.Join(goenv["GOROOT"], "src", importPath), importPathShort: importPath, packageName: path.Base(importPath), relevance: MaxRelevance, } - if notSelf(p) && wrappedCallback.packageNameLoaded(p) { + if notSelf(p) && wrappedCallback.dirFound(p) && wrappedCallback.packageNameLoaded(p) { wrappedCallback.exportsLoaded(p, exports) } } @@ -638,15 +651,23 @@ func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filena wrappedCallback.exportsLoaded(pkg, exports) }, } - return env.GetResolver().scan(ctx, scanFilter) + resolver, err := env.GetResolver() + if err != nil { + return err + } + return resolver.scan(ctx, scanFilter) } -func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) map[string]int { +func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) (map[string]int, error) { result := make(map[string]int) - for _, path := range paths { - result[path] = env.GetResolver().scoreImportPath(ctx, path) + resolver, err := env.GetResolver() + if err != nil { + return nil, err } - return result + for _, path := range paths { + result[path] = resolver.scoreImportPath(ctx, path) + } + return result, nil } func PrimeCache(ctx context.Context, env *ProcessEnv) error { @@ -672,8 +693,9 @@ func candidateImportName(pkg *pkg) string { return "" } -// getAllCandidates gets all of the candidates to be imported, regardless of if they are needed. -func getAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error { +// GetAllCandidates calls wrapped for each package whose name starts with +// searchPrefix, and can be imported from filename with the package name filePkg. +func GetAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error { callback := &scanCallback{ rootFound: func(gopathwalk.Root) bool { return true @@ -706,13 +728,43 @@ func getAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix return getCandidatePkgs(ctx, callback, filename, filePkg, env) } +// GetImportPaths calls wrapped for each package whose import path starts with +// searchPrefix, and can be imported from filename with the package name filePkg. +func GetImportPaths(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error { + callback := &scanCallback{ + rootFound: func(gopathwalk.Root) bool { + return true + }, + dirFound: func(pkg *pkg) bool { + if !canUse(filename, pkg.dir) { + return false + } + return strings.HasPrefix(pkg.importPathShort, searchPrefix) + }, + packageNameLoaded: func(pkg *pkg) bool { + wrapped(ImportFix{ + StmtInfo: ImportInfo{ + ImportPath: pkg.importPathShort, + Name: candidateImportName(pkg), + }, + IdentName: pkg.packageName, + FixType: AddImport, + Relevance: pkg.relevance, + }) + return false + }, + } + return getCandidatePkgs(ctx, callback, filename, filePkg, env) +} + // A PackageExport is a package and its exports. type PackageExport struct { Fix *ImportFix Exports []string } -func getPackageExports(ctx context.Context, wrapped func(PackageExport), searchPkg, filename, filePkg string, env *ProcessEnv) error { +// GetPackageExports returns all known packages with name pkg and their exports. +func GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchPkg, filename, filePkg string, env *ProcessEnv) error { callback := &scanCallback{ rootFound: func(gopathwalk.Root) bool { return true @@ -742,67 +794,126 @@ func getPackageExports(ctx context.Context, wrapped func(PackageExport), searchP return getCandidatePkgs(ctx, callback, filename, filePkg, env) } +var RequiredGoEnvVars = []string{"GO111MODULE", "GOFLAGS", "GOINSECURE", "GOMOD", "GOMODCACHE", "GONOPROXY", "GONOSUMDB", "GOPATH", "GOPROXY", "GOROOT", "GOSUMDB"} + // ProcessEnv contains environment variables and settings that affect the use of // the go command, the go/build package, etc. type ProcessEnv struct { - LocalPrefix string + GocmdRunner *gocommand.Runner BuildFlags []string - // If non-empty, these will be used instead of the - // process-wide values. - GOPATH, GOROOT, GO111MODULE, GOPROXY, GOFLAGS, GOSUMDB string - WorkingDir string + // Env overrides the OS environment, and can be used to specify + // GOPROXY, GO111MODULE, etc. PATH cannot be set here, because + // exec.Command will not honor it. + // Specifying all of RequiredGoEnvVars avoids a call to `go env`. + Env map[string]string + + WorkingDir string // If Logf is non-nil, debug logging is enabled through this function. Logf func(format string, args ...interface{}) + initialized bool + resolver Resolver } +func (e *ProcessEnv) goEnv() (map[string]string, error) { + if err := e.init(); err != nil { + return nil, err + } + return e.Env, nil +} + +func (e *ProcessEnv) matchFile(dir, name string) (bool, error) { + return build.Default.MatchFile(dir, name) +} + // CopyConfig copies the env's configuration into a new env. func (e *ProcessEnv) CopyConfig() *ProcessEnv { - copy := *e - copy.resolver = nil - return © + copy := &ProcessEnv{ + GocmdRunner: e.GocmdRunner, + initialized: e.initialized, + BuildFlags: e.BuildFlags, + Logf: e.Logf, + WorkingDir: e.WorkingDir, + resolver: nil, + Env: map[string]string{}, + } + for k, v := range e.Env { + copy.Env[k] = v + } + return copy +} + +func (e *ProcessEnv) init() error { + if e.initialized { + return nil + } + + foundAllRequired := true + for _, k := range RequiredGoEnvVars { + if _, ok := e.Env[k]; !ok { + foundAllRequired = false + break + } + } + if foundAllRequired { + e.initialized = true + return nil + } + + if e.Env == nil { + e.Env = map[string]string{} + } + + goEnv := map[string]string{} + stdout, err := e.invokeGo(context.TODO(), "env", append([]string{"-json"}, RequiredGoEnvVars...)...) + if err != nil { + return err + } + if err := json.Unmarshal(stdout.Bytes(), &goEnv); err != nil { + return err + } + for k, v := range goEnv { + e.Env[k] = v + } + e.initialized = true + return nil } func (e *ProcessEnv) env() []string { - env := os.Environ() - add := func(k, v string) { - if v != "" { - env = append(env, k+"="+v) - } - } - add("GOPATH", e.GOPATH) - add("GOROOT", e.GOROOT) - add("GO111MODULE", e.GO111MODULE) - add("GOPROXY", e.GOPROXY) - add("GOFLAGS", e.GOFLAGS) - add("GOSUMDB", e.GOSUMDB) - if e.WorkingDir != "" { - add("PWD", e.WorkingDir) + var env []string // the gocommand package will prepend os.Environ. + for k, v := range e.Env { + env = append(env, k+"="+v) } return env } -func (e *ProcessEnv) GetResolver() Resolver { +func (e *ProcessEnv) GetResolver() (Resolver, error) { if e.resolver != nil { - return e.resolver + return e.resolver, nil } - out, err := e.invokeGo(context.TODO(), "env", "GOMOD") - if err != nil || len(bytes.TrimSpace(out.Bytes())) == 0 { + if err := e.init(); err != nil { + return nil, err + } + if len(e.Env["GOMOD"]) == 0 { e.resolver = newGopathResolver(e) - return e.resolver + return e.resolver, nil } e.resolver = newModuleResolver(e) - return e.resolver + return e.resolver, nil } -func (e *ProcessEnv) buildContext() *build.Context { +func (e *ProcessEnv) buildContext() (*build.Context, error) { ctx := build.Default - ctx.GOROOT = e.GOROOT - ctx.GOPATH = e.GOPATH + goenv, err := e.goEnv() + if err != nil { + return nil, err + } + ctx.GOROOT = goenv["GOROOT"] + ctx.GOPATH = goenv["GOPATH"] // As of Go 1.14, build.Context has a Dir field // (see golang.org/issue/34860). @@ -818,7 +929,7 @@ func (e *ProcessEnv) buildContext() *build.Context { dir.SetString(e.WorkingDir) } - return &ctx + return &ctx, nil } func (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) (*bytes.Buffer, error) { @@ -830,13 +941,17 @@ func (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) Logf: e.Logf, WorkingDir: e.WorkingDir, } - return inv.Run(ctx) + return e.GocmdRunner.Run(ctx, inv) } -func addStdlibCandidates(pass *pass, refs references) { +func addStdlibCandidates(pass *pass, refs references) error { + goenv, err := pass.env.goEnv() + if err != nil { + return err + } add := func(pkg string) { // Prevent self-imports. - if path.Base(pkg) == pass.f.Name.Name && filepath.Join(pass.env.GOROOT, "src", pkg) == pass.srcDir { + if path.Base(pkg) == pass.f.Name.Name && filepath.Join(goenv["GOROOT"], "src", pkg) == pass.srcDir { return } exports := copyExports(stdlib[pkg]) @@ -857,6 +972,7 @@ func addStdlibCandidates(pass *pass, refs references) { } } } + return nil } // A Resolver does the build-system-specific parts of goimports. @@ -921,10 +1037,13 @@ func addExternalCandidates(pass *pass, refs references, filename string) error { return false // We'll do our own loading after we sort. }, } - err := pass.env.GetResolver().scan(context.Background(), callback) + resolver, err := pass.env.GetResolver() if err != nil { return err } + if err = resolver.scan(context.Background(), callback); err != nil { + return err + } // Search for imports matching potential package references. type result struct { @@ -1050,21 +1169,24 @@ func (r *gopathResolver) ClearForNewScan() { func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { names := map[string]string{} + bctx, err := r.env.buildContext() + if err != nil { + return nil, err + } for _, path := range importPaths { - names[path] = importPathToName(r.env, path, srcDir) + names[path] = importPathToName(bctx, path, srcDir) } return names, nil } // importPathToName finds out the actual package name, as declared in its .go files. -// If there's a problem, it returns "". -func importPathToName(env *ProcessEnv, importPath, srcDir string) (packageName string) { +func importPathToName(bctx *build.Context, importPath, srcDir string) string { // Fast path for standard library without going to disk. if _, ok := stdlib[importPath]; ok { return path.Base(importPath) // stdlib packages always match their paths. } - buildPkg, err := env.buildContext().Import(importPath, srcDir, build.FindOnly) + buildPkg, err := bctx.Import(importPath, srcDir, build.FindOnly) if err != nil { return "" } @@ -1225,8 +1347,18 @@ func (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error } stop := r.cache.ScanAndListen(ctx, processDir) defer stop() + + goenv, err := r.env.goEnv() + if err != nil { + return err + } + var roots []gopathwalk.Root + roots = append(roots, gopathwalk.Root{filepath.Join(goenv["GOROOT"], "src"), gopathwalk.RootGOROOT}) + for _, p := range filepath.SplitList(goenv["GOPATH"]) { + roots = append(roots, gopathwalk.Root{filepath.Join(p, "src"), gopathwalk.RootGOPATH}) + } // The callback is not necessarily safe to use in the goroutine below. Process roots eagerly. - roots := filterRoots(gopathwalk.SrcDirsRoots(r.env.buildContext()), callback.rootFound) + roots = filterRoots(roots, callback.rootFound) // We can't cancel walks, because we need them to finish to have a usable // cache. Instead, run them in a separate goroutine and detach. scanDone := make(chan struct{}) @@ -1286,8 +1418,6 @@ func VendorlessPath(ipath string) string { } func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []string, error) { - var exports []string - // Look for non-test, buildable .go files which could provide exports. all, err := ioutil.ReadDir(dir) if err != nil { @@ -1299,7 +1429,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl if !strings.HasSuffix(name, ".go") || (!includeTest && strings.HasSuffix(name, "_test.go")) { continue } - match, err := env.buildContext().MatchFile(dir, fi.Name()) + match, err := env.matchFile(dir, fi.Name()) if err != nil || !match { continue } @@ -1311,6 +1441,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl } var pkgName string + var exports []string fset := token.NewFileSet() for _, fi := range files { select { @@ -1322,7 +1453,10 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl fullFile := filepath.Join(dir, fi.Name()) f, err := parser.ParseFile(fset, fullFile, nil, 0) if err != nil { - return "", nil, fmt.Errorf("parsing %s: %v", fullFile, err) + if env.Logf != nil { + env.Logf("error parsing %v: %v", fullFile, err) + } + continue } if f.Name.Name == "documentation" { // Special case from go/build.ImportDir, not @@ -1362,6 +1496,10 @@ func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgNa pass.env.Logf("%s candidate %d/%d: %v in %v", pkgName, i+1, len(candidates), c.pkg.importPathShort, c.pkg.dir) } } + resolver, err := pass.env.GetResolver() + if err != nil { + return nil, err + } // Collect exports for packages with matching names. rescv := make([]chan *pkg, len(candidates)) @@ -1400,7 +1538,7 @@ func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgNa } // If we're an x_test, load the package under test's test variant. includeTest := strings.HasSuffix(pass.f.Name.Name, "_test") && c.pkg.dir == pass.srcDir - _, exports, err := pass.env.GetResolver().loadExports(ctx, c.pkg, includeTest) + _, exports, err := resolver.loadExports(ctx, c.pkg, includeTest) if err != nil { if pass.env.Logf != nil { pass.env.Logf("loading exports in dir %s (seeking package %s): %v", c.pkg.dir, pkgName, err) diff --git a/vendor/golang.org/x/tools/internal/imports/imports.go b/vendor/golang.org/x/tools/internal/imports/imports.go index b18daea29..2815edc33 100644 --- a/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/vendor/golang.org/x/tools/internal/imports/imports.go @@ -11,17 +11,13 @@ package imports import ( "bufio" "bytes" - "context" "fmt" "go/ast" - "go/build" "go/format" "go/parser" "go/printer" "go/token" "io" - "io/ioutil" - "os" "regexp" "strconv" "strings" @@ -33,6 +29,11 @@ import ( type Options struct { Env *ProcessEnv // The environment to use. Note: this contains the cached module and filesystem state. + // LocalPrefix is a comma-separated string of import path prefixes, which, if + // set, instructs Process to sort the import paths with the given prefixes + // into another group after 3rd-party packages. + LocalPrefix string + Fragment bool // Accept fragment of a source file (no package statement) AllErrors bool // Report all errors (not just the first 10 on different lines) @@ -43,13 +44,8 @@ type Options struct { FormatOnly bool // Disable the insertion and deletion of imports } -// Process implements golang.org/x/tools/imports.Process with explicit context in env. +// Process implements golang.org/x/tools/imports.Process with explicit context in opt.Env. func Process(filename string, src []byte, opt *Options) (formatted []byte, err error) { - src, opt, err = initialize(filename, src, opt) - if err != nil { - return nil, err - } - fileSet := token.NewFileSet() file, adjust, err := parse(fileSet, filename, src, opt) if err != nil { @@ -65,16 +61,12 @@ func Process(filename string, src []byte, opt *Options) (formatted []byte, err e } // FixImports returns a list of fixes to the imports that, when applied, -// will leave the imports in the same state as Process. +// will leave the imports in the same state as Process. src and opt must +// be specified. // // Note that filename's directory influences which imports can be chosen, // so it is important that filename be accurate. func FixImports(filename string, src []byte, opt *Options) (fixes []*ImportFix, err error) { - src, opt, err = initialize(filename, src, opt) - if err != nil { - return nil, err - } - fileSet := token.NewFileSet() file, _, err := parse(fileSet, filename, src, opt) if err != nil { @@ -85,13 +77,9 @@ func FixImports(filename string, src []byte, opt *Options) (fixes []*ImportFix, } // ApplyFixes applies all of the fixes to the file and formats it. extraMode -// is added in when parsing the file. +// is added in when parsing the file. src and opts must be specified, but no +// env is needed. func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) { - src, opt, err = initialize(filename, src, opt) - if err != nil { - return nil, err - } - // Don't use parse() -- we don't care about fragments or statement lists // here, and we need to work with unparseable files. fileSet := token.NewFileSet() @@ -115,59 +103,9 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, e return formatFile(fileSet, file, src, nil, opt) } -// GetAllCandidates gets all of the packages starting with prefix that can be -// imported by filename, sorted by import path. -func GetAllCandidates(ctx context.Context, callback func(ImportFix), searchPrefix, filename, filePkg string, opt *Options) error { - _, opt, err := initialize(filename, []byte{}, opt) - if err != nil { - return err - } - return getAllCandidates(ctx, callback, searchPrefix, filename, filePkg, opt.Env) -} - -// GetPackageExports returns all known packages with name pkg and their exports. -func GetPackageExports(ctx context.Context, callback func(PackageExport), searchPkg, filename, filePkg string, opt *Options) error { - _, opt, err := initialize(filename, []byte{}, opt) - if err != nil { - return err - } - return getPackageExports(ctx, callback, searchPkg, filename, filePkg, opt.Env) -} - -// initialize sets the values for opt and src. -// If they are provided, they are not changed. Otherwise opt is set to the -// default values and src is read from the file system. -func initialize(filename string, src []byte, opt *Options) ([]byte, *Options, error) { - // Use defaults if opt is nil. - if opt == nil { - opt = &Options{Comments: true, TabIndent: true, TabWidth: 8} - } - - // Set the env if the user has not provided it. - if opt.Env == nil { - opt.Env = &ProcessEnv{ - GOPATH: build.Default.GOPATH, - GOROOT: build.Default.GOROOT, - GOFLAGS: os.Getenv("GOFLAGS"), - GO111MODULE: os.Getenv("GO111MODULE"), - GOPROXY: os.Getenv("GOPROXY"), - GOSUMDB: os.Getenv("GOSUMDB"), - } - } - if src == nil { - b, err := ioutil.ReadFile(filename) - if err != nil { - return nil, nil, err - } - src = b - } - - return src, opt, nil -} - func formatFile(fileSet *token.FileSet, file *ast.File, src []byte, adjust func(orig []byte, src []byte) []byte, opt *Options) ([]byte, error) { - mergeImports(opt.Env, fileSet, file) - sortImports(opt.Env, fileSet, file) + mergeImports(fileSet, file) + sortImports(opt.LocalPrefix, fileSet, file) imps := astutil.Imports(fileSet, file) var spacesBefore []string // import paths we need spaces before for _, impSection := range imps { @@ -178,7 +116,7 @@ func formatFile(fileSet *token.FileSet, file *ast.File, src []byte, adjust func( lastGroup := -1 for _, importSpec := range impSection { importPath, _ := strconv.Unquote(importSpec.Path.Value) - groupNum := importGroup(opt.Env, importPath) + groupNum := importGroup(opt.LocalPrefix, importPath) if groupNum != lastGroup && lastGroup != -1 { spacesBefore = append(spacesBefore, importPath) } diff --git a/vendor/golang.org/x/tools/internal/imports/mod.go b/vendor/golang.org/x/tools/internal/imports/mod.go index 69e3eecc4..94880d616 100644 --- a/vendor/golang.org/x/tools/internal/imports/mod.go +++ b/vendor/golang.org/x/tools/internal/imports/mod.go @@ -15,7 +15,7 @@ import ( "strings" "golang.org/x/mod/module" - "golang.org/x/mod/semver" + "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" ) @@ -24,31 +24,21 @@ import ( type ModuleResolver struct { env *ProcessEnv moduleCacheDir string - dummyVendorMod *ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory. + dummyVendorMod *gocommand.ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory. roots []gopathwalk.Root scanSema chan struct{} // scanSema prevents concurrent scans and guards scannedRoots. scannedRoots map[gopathwalk.Root]bool initialized bool - main *ModuleJSON - modsByModPath []*ModuleJSON // All modules, ordered by # of path components in module Path... - modsByDir []*ModuleJSON // ...or Dir. + main *gocommand.ModuleJSON + modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path... + modsByDir []*gocommand.ModuleJSON // ...or Dir. // moduleCacheCache stores information about the module cache. moduleCacheCache *dirInfoCache otherCache *dirInfoCache } -type ModuleJSON struct { - Path string // module path - Replace *ModuleJSON // replaced by this module - Main bool // is this the main module? - Indirect bool // is this module only an indirect dependency of main module? - Dir string // directory holding files for this module, if any - GoMod string // path to go.mod file for this module, if any - GoVersion string // go version used in module -} - func newModuleResolver(e *ProcessEnv) *ModuleResolver { r := &ModuleResolver{ env: e, @@ -62,7 +52,18 @@ func (r *ModuleResolver) init() error { if r.initialized { return nil } - mainMod, vendorEnabled, err := vendorEnabled(r.env) + + goenv, err := r.env.goEnv() + if err != nil { + return err + } + inv := gocommand.Invocation{ + BuildFlags: r.env.BuildFlags, + Env: r.env.env(), + Logf: r.env.Logf, + WorkingDir: r.env.WorkingDir, + } + mainMod, vendorEnabled, err := gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner) if err != nil { return err } @@ -71,18 +72,22 @@ func (r *ModuleResolver) init() error { // Vendor mode is on, so all the non-Main modules are irrelevant, // and we need to search /vendor for everything. r.main = mainMod - r.dummyVendorMod = &ModuleJSON{ + r.dummyVendorMod = &gocommand.ModuleJSON{ Path: "", Dir: filepath.Join(mainMod.Dir, "vendor"), } - r.modsByModPath = []*ModuleJSON{mainMod, r.dummyVendorMod} - r.modsByDir = []*ModuleJSON{mainMod, r.dummyVendorMod} + r.modsByModPath = []*gocommand.ModuleJSON{mainMod, r.dummyVendorMod} + r.modsByDir = []*gocommand.ModuleJSON{mainMod, r.dummyVendorMod} } else { // Vendor mode is off, so run go list -m ... to find everything. r.initAllMods() } - r.moduleCacheDir = filepath.Join(filepath.SplitList(r.env.GOPATH)[0], "/pkg/mod") + if gmc := r.env.Env["GOMODCACHE"]; gmc != "" { + r.moduleCacheDir = gmc + } else { + r.moduleCacheDir = filepath.Join(filepath.SplitList(goenv["GOPATH"])[0], "/pkg/mod") + } sort.Slice(r.modsByModPath, func(i, j int) bool { count := func(x int) int { @@ -98,7 +103,7 @@ func (r *ModuleResolver) init() error { }) r.roots = []gopathwalk.Root{ - {filepath.Join(r.env.GOROOT, "/src"), gopathwalk.RootGOROOT}, + {filepath.Join(goenv["GOROOT"], "/src"), gopathwalk.RootGOROOT}, } if r.main != nil { r.roots = append(r.roots, gopathwalk.Root{r.main.Dir, gopathwalk.RootCurrentModule}) @@ -106,7 +111,7 @@ func (r *ModuleResolver) init() error { if vendorEnabled { r.roots = append(r.roots, gopathwalk.Root{r.dummyVendorMod.Dir, gopathwalk.RootOther}) } else { - addDep := func(mod *ModuleJSON) { + addDep := func(mod *gocommand.ModuleJSON) { if mod.Replace == nil { // This is redundant with the cache, but we'll skip it cheaply enough. r.roots = append(r.roots, gopathwalk.Root{mod.Dir, gopathwalk.RootModuleCache}) @@ -151,7 +156,7 @@ func (r *ModuleResolver) initAllMods() error { return err } for dec := json.NewDecoder(stdout); dec.More(); { - mod := &ModuleJSON{} + mod := &gocommand.ModuleJSON{} if err := dec.Decode(mod); err != nil { return err } @@ -197,7 +202,7 @@ func (r *ModuleResolver) ClearForNewMod() { // findPackage returns the module and directory that contains the package at // the given import path, or returns nil, "" if no module is in scope. -func (r *ModuleResolver) findPackage(importPath string) (*ModuleJSON, string) { +func (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) { // This can't find packages in the stdlib, but that's harmless for all // the existing code paths. for _, m := range r.modsByModPath { @@ -239,7 +244,7 @@ func (r *ModuleResolver) findPackage(importPath string) (*ModuleJSON, string) { // files in that directory. If not, it could be provided by an // outer module. See #29736. for _, fi := range pkgFiles { - if ok, _ := r.env.buildContext().MatchFile(pkgDir, fi.Name()); ok { + if ok, _ := r.env.matchFile(pkgDir, fi.Name()); ok { return m, pkgDir } } @@ -283,7 +288,7 @@ func (r *ModuleResolver) cacheExports(ctx context.Context, env *ProcessEnv, info // findModuleByDir returns the module that contains dir, or nil if no such // module is in scope. -func (r *ModuleResolver) findModuleByDir(dir string) *ModuleJSON { +func (r *ModuleResolver) findModuleByDir(dir string) *gocommand.ModuleJSON { // This is quite tricky and may not be correct. dir could be: // - a package in the main module. // - a replace target underneath the main module's directory. @@ -310,7 +315,7 @@ func (r *ModuleResolver) findModuleByDir(dir string) *ModuleJSON { // dirIsNestedModule reports if dir is contained in a nested module underneath // mod, not actually in mod. -func (r *ModuleResolver) dirIsNestedModule(dir string, mod *ModuleJSON) bool { +func (r *ModuleResolver) dirIsNestedModule(dir string, mod *gocommand.ModuleJSON) bool { if !strings.HasPrefix(dir, mod.Dir) { return false } @@ -490,7 +495,7 @@ func (r *ModuleResolver) scoreImportPath(ctx context.Context, path string) int { return modRelevance(mod) } -func modRelevance(mod *ModuleJSON) int { +func modRelevance(mod *gocommand.ModuleJSON) int { switch { case mod == nil: // out of scope return MaxRelevance - 4 @@ -656,63 +661,3 @@ func modulePath(mod []byte) string { } return "" // missing module path } - -var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`) - -// vendorEnabled indicates if vendoring is enabled. -// Inspired by setDefaultBuildMod in modload/init.go -func vendorEnabled(env *ProcessEnv) (*ModuleJSON, bool, error) { - mainMod, go114, err := getMainModuleAnd114(env) - if err != nil { - return nil, false, err - } - matches := modFlagRegexp.FindStringSubmatch(env.GOFLAGS) - var modFlag string - if len(matches) != 0 { - modFlag = matches[1] - } - if modFlag != "" { - // Don't override an explicit '-mod=' argument. - return mainMod, modFlag == "vendor", nil - } - if mainMod == nil || !go114 { - return mainMod, false, nil - } - // Check 1.14's automatic vendor mode. - if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() { - if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 { - // The Go version is at least 1.14, and a vendor directory exists. - // Set -mod=vendor by default. - return mainMod, true, nil - } - } - return mainMod, false, nil -} - -// getMainModuleAnd114 gets the main module's information and whether the -// go command in use is 1.14+. This is the information needed to figure out -// if vendoring should be enabled. -func getMainModuleAnd114(env *ProcessEnv) (*ModuleJSON, bool, error) { - const format = `{{.Path}} -{{.Dir}} -{{.GoMod}} -{{.GoVersion}} -{{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}} -` - stdout, err := env.invokeGo(context.TODO(), "list", "-m", "-f", format) - if err != nil { - return nil, false, nil - } - lines := strings.Split(stdout.String(), "\n") - if len(lines) < 5 { - return nil, false, fmt.Errorf("unexpected stdout: %q", stdout) - } - mod := &ModuleJSON{ - Path: lines[0], - Dir: lines[1], - GoMod: lines[2], - GoVersion: lines[3], - Main: true, - } - return mod, lines[4] == "go1.14", nil -} diff --git a/vendor/golang.org/x/tools/internal/imports/sortimports.go b/vendor/golang.org/x/tools/internal/imports/sortimports.go index 226279471..be8ffa25f 100644 --- a/vendor/golang.org/x/tools/internal/imports/sortimports.go +++ b/vendor/golang.org/x/tools/internal/imports/sortimports.go @@ -15,7 +15,7 @@ import ( // sortImports sorts runs of consecutive import lines in import blocks in f. // It also removes duplicate imports when it is possible to do so without data loss. -func sortImports(env *ProcessEnv, fset *token.FileSet, f *ast.File) { +func sortImports(localPrefix string, fset *token.FileSet, f *ast.File) { for i, d := range f.Decls { d, ok := d.(*ast.GenDecl) if !ok || d.Tok != token.IMPORT { @@ -40,11 +40,11 @@ func sortImports(env *ProcessEnv, fset *token.FileSet, f *ast.File) { for j, s := range d.Specs { if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line { // j begins a new run. End this one. - specs = append(specs, sortSpecs(env, fset, f, d.Specs[i:j])...) + specs = append(specs, sortSpecs(localPrefix, fset, f, d.Specs[i:j])...) i = j } } - specs = append(specs, sortSpecs(env, fset, f, d.Specs[i:])...) + specs = append(specs, sortSpecs(localPrefix, fset, f, d.Specs[i:])...) d.Specs = specs // Deduping can leave a blank line before the rparen; clean that up. @@ -60,7 +60,7 @@ func sortImports(env *ProcessEnv, fset *token.FileSet, f *ast.File) { // mergeImports merges all the import declarations into the first one. // Taken from golang.org/x/tools/ast/astutil. -func mergeImports(env *ProcessEnv, fset *token.FileSet, f *ast.File) { +func mergeImports(fset *token.FileSet, f *ast.File) { if len(f.Decls) <= 1 { return } @@ -142,7 +142,7 @@ type posSpan struct { End token.Pos } -func sortSpecs(env *ProcessEnv, fset *token.FileSet, f *ast.File, specs []ast.Spec) []ast.Spec { +func sortSpecs(localPrefix string, fset *token.FileSet, f *ast.File, specs []ast.Spec) []ast.Spec { // Can't short-circuit here even if specs are already sorted, // since they might yet need deduplication. // A lone import, however, may be safely ignored. @@ -191,7 +191,7 @@ func sortSpecs(env *ProcessEnv, fset *token.FileSet, f *ast.File, specs []ast.Sp // Reassign the import paths to have the same position sequence. // Reassign each comment to abut the end of its spec. // Sort the comments by new position. - sort.Sort(byImportSpec{env, specs}) + sort.Sort(byImportSpec{localPrefix, specs}) // Dedup. Thanks to our sorting, we can just consider // adjacent pairs of imports. @@ -245,8 +245,8 @@ func sortSpecs(env *ProcessEnv, fset *token.FileSet, f *ast.File, specs []ast.Sp } type byImportSpec struct { - env *ProcessEnv - specs []ast.Spec // slice of *ast.ImportSpec + localPrefix string + specs []ast.Spec // slice of *ast.ImportSpec } func (x byImportSpec) Len() int { return len(x.specs) } @@ -255,8 +255,8 @@ func (x byImportSpec) Less(i, j int) bool { ipath := importPath(x.specs[i]) jpath := importPath(x.specs[j]) - igroup := importGroup(x.env, ipath) - jgroup := importGroup(x.env, jpath) + igroup := importGroup(x.localPrefix, ipath) + jgroup := importGroup(x.localPrefix, jpath) if igroup != jgroup { return igroup < jgroup } diff --git a/vendor/golang.org/x/tools/internal/imports/zstdlib.go b/vendor/golang.org/x/tools/internal/imports/zstdlib.go index 7e60eb04e..7b573b983 100644 --- a/vendor/golang.org/x/tools/internal/imports/zstdlib.go +++ b/vendor/golang.org/x/tools/internal/imports/zstdlib.go @@ -56,6 +56,7 @@ var stdlib = map[string][]string{ }, "bufio": []string{ "ErrAdvanceTooFar", + "ErrBadReadCount", "ErrBufferFull", "ErrFinalToken", "ErrInvalidUnreadByte", @@ -303,7 +304,9 @@ var stdlib = map[string][]string{ "PrivateKey", "PublicKey", "Sign", + "SignASN1", "Verify", + "VerifyASN1", }, "crypto/ed25519": []string{ "GenerateKey", @@ -322,11 +325,13 @@ var stdlib = map[string][]string{ "CurveParams", "GenerateKey", "Marshal", + "MarshalCompressed", "P224", "P256", "P384", "P521", "Unmarshal", + "UnmarshalCompressed", }, "crypto/hmac": []string{ "Equal", @@ -415,6 +420,9 @@ var stdlib = map[string][]string{ "crypto/tls": []string{ "Certificate", "CertificateRequestInfo", + "CipherSuite", + "CipherSuiteName", + "CipherSuites", "Client", "ClientAuthType", "ClientHelloInfo", @@ -429,11 +437,13 @@ var stdlib = map[string][]string{ "CurveP521", "Dial", "DialWithDialer", + "Dialer", "ECDSAWithP256AndSHA256", "ECDSAWithP384AndSHA384", "ECDSAWithP521AndSHA512", "ECDSAWithSHA1", "Ed25519", + "InsecureCipherSuites", "Listen", "LoadX509KeyPair", "NewLRUClientSessionCache", @@ -465,6 +475,7 @@ var stdlib = map[string][]string{ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", @@ -473,6 +484,7 @@ var stdlib = map[string][]string{ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_FALLBACK_SCSV", "TLS_RSA_WITH_3DES_EDE_CBC_SHA", @@ -501,6 +513,7 @@ var stdlib = map[string][]string{ "ConstraintViolationError", "CreateCertificate", "CreateCertificateRequest", + "CreateRevocationList", "DSA", "DSAWithSHA1", "DSAWithSHA256", @@ -575,6 +588,7 @@ var stdlib = map[string][]string{ "PublicKeyAlgorithm", "PureEd25519", "RSA", + "RevocationList", "SHA1WithRSA", "SHA256WithRSA", "SHA256WithRSAPSS", @@ -688,6 +702,7 @@ var stdlib = map[string][]string{ "String", "Tx", "TxOptions", + "Validator", "Value", "ValueConverter", "Valuer", @@ -698,36 +713,65 @@ var stdlib = map[string][]string{ "Attr", "AttrAbstractOrigin", "AttrAccessibility", + "AttrAddrBase", "AttrAddrClass", + "AttrAlignment", "AttrAllocated", "AttrArtificial", "AttrAssociated", "AttrBaseTypes", + "AttrBinaryScale", "AttrBitOffset", "AttrBitSize", "AttrByteSize", + "AttrCallAllCalls", + "AttrCallAllSourceCalls", + "AttrCallAllTailCalls", "AttrCallColumn", + "AttrCallDataLocation", + "AttrCallDataValue", "AttrCallFile", "AttrCallLine", + "AttrCallOrigin", + "AttrCallPC", + "AttrCallParameter", + "AttrCallReturnPC", + "AttrCallTailCall", + "AttrCallTarget", + "AttrCallTargetClobbered", + "AttrCallValue", "AttrCalling", "AttrCommonRef", "AttrCompDir", + "AttrConstExpr", "AttrConstValue", "AttrContainingType", "AttrCount", + "AttrDataBitOffset", "AttrDataLocation", "AttrDataMemberLoc", + "AttrDecimalScale", + "AttrDecimalSign", "AttrDeclColumn", "AttrDeclFile", "AttrDeclLine", "AttrDeclaration", "AttrDefaultValue", + "AttrDefaulted", + "AttrDeleted", "AttrDescription", + "AttrDigitCount", "AttrDiscr", "AttrDiscrList", "AttrDiscrValue", + "AttrDwoName", + "AttrElemental", "AttrEncoding", + "AttrEndianity", "AttrEntrypc", + "AttrEnumClass", + "AttrExplicit", + "AttrExportSymbols", "AttrExtension", "AttrExternal", "AttrFrameBase", @@ -738,27 +782,47 @@ var stdlib = map[string][]string{ "AttrInline", "AttrIsOptional", "AttrLanguage", + "AttrLinkageName", "AttrLocation", + "AttrLoclistsBase", "AttrLowerBound", "AttrLowpc", "AttrMacroInfo", + "AttrMacros", + "AttrMainSubprogram", + "AttrMutable", "AttrName", "AttrNamelistItem", + "AttrNoreturn", + "AttrObjectPointer", "AttrOrdering", + "AttrPictureString", "AttrPriority", "AttrProducer", "AttrPrototyped", + "AttrPure", "AttrRanges", + "AttrRank", + "AttrRecursive", + "AttrReference", "AttrReturnAddr", + "AttrRnglistsBase", + "AttrRvalueReference", "AttrSegment", "AttrSibling", + "AttrSignature", + "AttrSmall", "AttrSpecification", "AttrStartScope", "AttrStaticLink", "AttrStmtList", + "AttrStrOffsetsBase", "AttrStride", "AttrStrideSize", "AttrStringLength", + "AttrStringLengthBitSize", + "AttrStringLengthByteSize", + "AttrThreadsScaled", "AttrTrampoline", "AttrType", "AttrUpperBound", @@ -772,18 +836,23 @@ var stdlib = map[string][]string{ "BoolType", "CharType", "Class", + "ClassAddrPtr", "ClassAddress", "ClassBlock", "ClassConstant", "ClassExprLoc", "ClassFlag", "ClassLinePtr", + "ClassLocList", "ClassLocListPtr", "ClassMacPtr", "ClassRangeListPtr", "ClassReference", "ClassReferenceAlt", "ClassReferenceSig", + "ClassRngList", + "ClassRngListsPtr", + "ClassStrOffsetsPtr", "ClassString", "ClassStringAlt", "ClassUnknown", @@ -814,9 +883,13 @@ var stdlib = map[string][]string{ "Tag", "TagAccessDeclaration", "TagArrayType", + "TagAtomicType", "TagBaseType", + "TagCallSite", + "TagCallSiteParameter", "TagCatchDwarfBlock", "TagClassType", + "TagCoarrayType", "TagCommonDwarfBlock", "TagCommonInclusion", "TagCompileUnit", @@ -824,12 +897,15 @@ var stdlib = map[string][]string{ "TagConstType", "TagConstant", "TagDwarfProcedure", + "TagDynamicType", "TagEntryPoint", "TagEnumerationType", "TagEnumerator", "TagFileType", "TagFormalParameter", "TagFriend", + "TagGenericSubrange", + "TagImmutableType", "TagImportedDeclaration", "TagImportedModule", "TagImportedUnit", @@ -853,6 +929,7 @@ var stdlib = map[string][]string{ "TagRvalueReferenceType", "TagSetType", "TagSharedType", + "TagSkeletonUnit", "TagStringType", "TagStructType", "TagSubprogram", @@ -2281,6 +2358,27 @@ var stdlib = map[string][]string{ "IMAGE_DIRECTORY_ENTRY_RESOURCE", "IMAGE_DIRECTORY_ENTRY_SECURITY", "IMAGE_DIRECTORY_ENTRY_TLS", + "IMAGE_DLLCHARACTERISTICS_APPCONTAINER", + "IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE", + "IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY", + "IMAGE_DLLCHARACTERISTICS_GUARD_CF", + "IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA", + "IMAGE_DLLCHARACTERISTICS_NO_BIND", + "IMAGE_DLLCHARACTERISTICS_NO_ISOLATION", + "IMAGE_DLLCHARACTERISTICS_NO_SEH", + "IMAGE_DLLCHARACTERISTICS_NX_COMPAT", + "IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE", + "IMAGE_DLLCHARACTERISTICS_WDM_DRIVER", + "IMAGE_FILE_32BIT_MACHINE", + "IMAGE_FILE_AGGRESIVE_WS_TRIM", + "IMAGE_FILE_BYTES_REVERSED_HI", + "IMAGE_FILE_BYTES_REVERSED_LO", + "IMAGE_FILE_DEBUG_STRIPPED", + "IMAGE_FILE_DLL", + "IMAGE_FILE_EXECUTABLE_IMAGE", + "IMAGE_FILE_LARGE_ADDRESS_AWARE", + "IMAGE_FILE_LINE_NUMS_STRIPPED", + "IMAGE_FILE_LOCAL_SYMS_STRIPPED", "IMAGE_FILE_MACHINE_AM33", "IMAGE_FILE_MACHINE_AMD64", "IMAGE_FILE_MACHINE_ARM", @@ -2303,6 +2401,25 @@ var stdlib = map[string][]string{ "IMAGE_FILE_MACHINE_THUMB", "IMAGE_FILE_MACHINE_UNKNOWN", "IMAGE_FILE_MACHINE_WCEMIPSV2", + "IMAGE_FILE_NET_RUN_FROM_SWAP", + "IMAGE_FILE_RELOCS_STRIPPED", + "IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP", + "IMAGE_FILE_SYSTEM", + "IMAGE_FILE_UP_SYSTEM_ONLY", + "IMAGE_SUBSYSTEM_EFI_APPLICATION", + "IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER", + "IMAGE_SUBSYSTEM_EFI_ROM", + "IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER", + "IMAGE_SUBSYSTEM_NATIVE", + "IMAGE_SUBSYSTEM_NATIVE_WINDOWS", + "IMAGE_SUBSYSTEM_OS2_CUI", + "IMAGE_SUBSYSTEM_POSIX_CUI", + "IMAGE_SUBSYSTEM_UNKNOWN", + "IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION", + "IMAGE_SUBSYSTEM_WINDOWS_CE_GUI", + "IMAGE_SUBSYSTEM_WINDOWS_CUI", + "IMAGE_SUBSYSTEM_WINDOWS_GUI", + "IMAGE_SUBSYSTEM_XBOX", "ImportDirectory", "NewFile", "Open", @@ -2359,6 +2476,7 @@ var stdlib = map[string][]string{ "RawValue", "StructuralError", "SyntaxError", + "TagBMPString", "TagBitString", "TagBoolean", "TagEnum", @@ -2787,6 +2905,7 @@ var stdlib = map[string][]string{ "IsPredeclared", "Mode", "New", + "NewFromFiles", "Note", "Package", "PreserveAST", @@ -3115,6 +3234,11 @@ var stdlib = map[string][]string{ "New64", "New64a", }, + "hash/maphash": []string{ + "Hash", + "MakeSeed", + "Seed", + }, "html": []string{ "EscapeString", "UnescapeString", @@ -3367,6 +3491,7 @@ var stdlib = map[string][]string{ "Ldate", "Llongfile", "Lmicroseconds", + "Lmsgprefix", "Logger", "Lshortfile", "LstdFlags", @@ -3443,6 +3568,7 @@ var stdlib = map[string][]string{ "Exp", "Exp2", "Expm1", + "FMA", "Float32bits", "Float32frombits", "Float64bits", @@ -3567,6 +3693,9 @@ var stdlib = map[string][]string{ "OnesCount32", "OnesCount64", "OnesCount8", + "Rem", + "Rem32", + "Rem64", "Reverse", "Reverse16", "Reverse32", @@ -4108,6 +4237,7 @@ var stdlib = map[string][]string{ "DevNull", "Environ", "ErrClosed", + "ErrDeadlineExceeded", "ErrExist", "ErrInvalid", "ErrNoDeadline", @@ -4566,6 +4696,7 @@ var stdlib = map[string][]string{ "ErrRange", "ErrSyntax", "FormatBool", + "FormatComplex", "FormatFloat", "FormatInt", "FormatUint", @@ -4575,6 +4706,7 @@ var stdlib = map[string][]string{ "Itoa", "NumError", "ParseBool", + "ParseComplex", "ParseFloat", "ParseInt", "ParseUint", @@ -5140,7 +5272,10 @@ var stdlib = map[string][]string{ "CTL_NET", "CTL_QUERY", "CTRL_BREAK_EVENT", + "CTRL_CLOSE_EVENT", "CTRL_C_EVENT", + "CTRL_LOGOFF_EVENT", + "CTRL_SHUTDOWN_EVENT", "CancelIo", "CancelIoEx", "CertAddCertificateContextToStore", @@ -10112,6 +10247,7 @@ var stdlib = map[string][]string{ "Duployan", "Egyptian_Hieroglyphs", "Elbasan", + "Elymaic", "Ethiopic", "Extender", "FoldCategory", @@ -10215,6 +10351,7 @@ var stdlib = map[string][]string{ "Myanmar", "N", "Nabataean", + "Nandinagari", "Nd", "New_Tai_Lue", "Newa", @@ -10224,6 +10361,7 @@ var stdlib = map[string][]string{ "Noncharacter_Code_Point", "Number", "Nushu", + "Nyiakeng_Puachue_Hmong", "Ogham", "Ol_Chiki", "Old_Hungarian", @@ -10331,6 +10469,7 @@ var stdlib = map[string][]string{ "Vai", "Variation_Selector", "Version", + "Wancho", "Warang_Citi", "White_Space", "Yi", diff --git a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go index b13ce33a3..2c4527f24 100644 --- a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go +++ b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go @@ -1,27 +1,14 @@ // Package packagesinternal exposes internal-only fields from go/packages. package packagesinternal -import "time" - -// Fields must match go list; -type Module struct { - Path string // module path - Version string // module version - Versions []string // available module versions (with -versions) - Replace *Module // replaced by this module - Time *time.Time // time version was created - Update *Module // available update, if any (with -u) - Main bool // is this the main module? - Indirect bool // is this module only an indirect dependency of main module? - Dir string // directory holding files for this module, if any - GoMod string // path to go.mod file used when loading this module, if any - GoVersion string // go version used in module - Error *ModuleError // error loading module -} -type ModuleError struct { - Err string // the error itself -} +import ( + "golang.org/x/tools/internal/gocommand" +) var GetForTest = func(p interface{}) string { return "" } -var GetModule = func(p interface{}) *Module { return nil } +var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil } + +var SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {} + +var TypecheckCgo int diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go new file mode 100644 index 000000000..a5bb408e2 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go @@ -0,0 +1,28 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typesinternal + +import ( + "go/types" + "reflect" + "unsafe" +) + +func SetUsesCgo(conf *types.Config) bool { + v := reflect.ValueOf(conf).Elem() + + f := v.FieldByName("go115UsesCgo") + if !f.IsValid() { + f = v.FieldByName("UsesCgo") + if !f.IsValid() { + return false + } + } + + addr := unsafe.Pointer(f.UnsafeAddr()) + *(*bool)(addr) = true + + return true +} diff --git a/vendor/gopkg.in/yaml.v2/.travis.yml b/vendor/gopkg.in/yaml.v2/.travis.yml index 9f556934d..055480b9e 100644 --- a/vendor/gopkg.in/yaml.v2/.travis.yml +++ b/vendor/gopkg.in/yaml.v2/.travis.yml @@ -1,12 +1,16 @@ language: go go: - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - 1.8 - - 1.9 - - tip + - "1.4.x" + - "1.5.x" + - "1.6.x" + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" + - "1.11.x" + - "1.12.x" + - "1.13.x" + - "tip" go_import_path: gopkg.in/yaml.v2 diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v2/apic.go index 1f7e87e67..d2c2308f1 100644 --- a/vendor/gopkg.in/yaml.v2/apic.go +++ b/vendor/gopkg.in/yaml.v2/apic.go @@ -86,6 +86,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) { raw_buffer: make([]byte, 0, output_raw_buffer_size), states: make([]yaml_emitter_state_t, 0, initial_stack_size), events: make([]yaml_event_t, 0, initial_queue_size), + best_width: -1, } } diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v2/decode.go index 531087655..129bc2a97 100644 --- a/vendor/gopkg.in/yaml.v2/decode.go +++ b/vendor/gopkg.in/yaml.v2/decode.go @@ -319,10 +319,14 @@ func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unm } const ( - // 400,000 decode operations is ~500kb of dense object declarations, or ~5kb of dense object declarations with 10000% alias expansion + // 400,000 decode operations is ~500kb of dense object declarations, or + // ~5kb of dense object declarations with 10000% alias expansion alias_ratio_range_low = 400000 - // 4,000,000 decode operations is ~5MB of dense object declarations, or ~4.5MB of dense object declarations with 10% alias expansion + + // 4,000,000 decode operations is ~5MB of dense object declarations, or + // ~4.5MB of dense object declarations with 10% alias expansion alias_ratio_range_high = 4000000 + // alias_ratio_range is the range over which we scale allowed alias ratios alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) ) @@ -784,8 +788,7 @@ func (d *decoder) merge(n *node, out reflect.Value) { case mappingNode: d.unmarshal(n, out) case aliasNode: - an, ok := d.doc.anchors[n.value] - if ok && an.kind != mappingNode { + if n.alias != nil && n.alias.kind != mappingNode { failWantMap() } d.unmarshal(n, out) @@ -794,8 +797,7 @@ func (d *decoder) merge(n *node, out reflect.Value) { for i := len(n.children) - 1; i >= 0; i-- { ni := n.children[i] if ni.kind == aliasNode { - an, ok := d.doc.anchors[ni.value] - if ok && an.kind != mappingNode { + if ni.alias != nil && ni.alias.kind != mappingNode { failWantMap() } } else if ni.kind != mappingNode { diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v2/scannerc.go index 570b8ecd1..0b9bb6030 100644 --- a/vendor/gopkg.in/yaml.v2/scannerc.go +++ b/vendor/gopkg.in/yaml.v2/scannerc.go @@ -626,30 +626,17 @@ func trace(args ...interface{}) func() { func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { // While we need more tokens to fetch, do it. for { - // Check if we really need to fetch more tokens. - need_more_tokens := false - - if parser.tokens_head == len(parser.tokens) { - // Queue is empty. - need_more_tokens = true - } else { - // Check if any potential simple key may occupy the head position. - if !yaml_parser_stale_simple_keys(parser) { + if parser.tokens_head != len(parser.tokens) { + // If queue is non-empty, check if any potential simple key may + // occupy the head position. + head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] + if !ok { + break + } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { return false + } else if !valid { + break } - - for i := range parser.simple_keys { - simple_key := &parser.simple_keys[i] - if simple_key.possible && simple_key.token_number == parser.tokens_parsed { - need_more_tokens = true - break - } - } - } - - // We are finished. - if !need_more_tokens { - break } // Fetch the next token. if !yaml_parser_fetch_next_token(parser) { @@ -678,11 +665,6 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { return false } - // Remove obsolete potential simple keys. - if !yaml_parser_stale_simple_keys(parser) { - return false - } - // Check the indentation level against the current column. if !yaml_parser_unroll_indent(parser, parser.mark.column) { return false @@ -837,29 +819,30 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { "found character that cannot start any token") } -// Check the list of potential simple keys and remove the positions that -// cannot contain simple keys anymore. -func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool { - // Check for a potential simple key for each flow level. - for i := range parser.simple_keys { - simple_key := &parser.simple_keys[i] - - // The specification requires that a simple key - // - // - is limited to a single line, - // - is shorter than 1024 characters. - if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) { - - // Check if the potential simple key to be removed is required. - if simple_key.required { - return yaml_parser_set_scanner_error(parser, - "while scanning a simple key", simple_key.mark, - "could not find expected ':'") - } - simple_key.possible = false - } +func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { + if !simple_key.possible { + return false, true } - return true + + // The 1.2 specification says: + // + // "If the ? indicator is omitted, parsing needs to see past the + // implicit key to recognize it as such. To limit the amount of + // lookahead required, the “:” indicator must appear at most 1024 + // Unicode characters beyond the start of the key. In addition, the key + // is restricted to a single line." + // + if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { + // Check if the potential simple key to be removed is required. + if simple_key.required { + return false, yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key.mark, + "could not find expected ':'") + } + simple_key.possible = false + return false, true + } + return true, true } // Check if a simple key may start at the current position and add it if @@ -879,13 +862,14 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { possible: true, required: required, token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, } - simple_key.mark = parser.mark if !yaml_parser_remove_simple_key(parser) { return false } parser.simple_keys[len(parser.simple_keys)-1] = simple_key + parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 } return true } @@ -900,9 +884,10 @@ func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { "while scanning a simple key", parser.simple_keys[i].mark, "could not find expected ':'") } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) } - // Remove the key from the stack. - parser.simple_keys[i].possible = false return true } @@ -912,7 +897,12 @@ const max_flow_level = 10000 // Increase the flow level and resize the simple key list if needed. func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { // Reset the simple key on the next level. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ + possible: false, + required: false, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + }) // Increase the flow level. parser.flow_level++ @@ -928,7 +918,9 @@ func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { if parser.flow_level > 0 { parser.flow_level-- - parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1] + last := len(parser.simple_keys) - 1 + delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) + parser.simple_keys = parser.simple_keys[:last] } return true } @@ -1005,6 +997,8 @@ func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { // Initialize the simple key stack. parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + parser.simple_keys_by_tok = make(map[int]int) + // A simple key is allowed at the beginning of the stream. parser.simple_key_allowed = true @@ -1286,7 +1280,11 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool { simple_key := &parser.simple_keys[len(parser.simple_keys)-1] // Have we found a simple key? - if simple_key.possible { + if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { + return false + + } else if valid { + // Create the KEY token and insert it into the queue. token := yaml_token_t{ typ: yaml_KEY_TOKEN, @@ -1304,6 +1302,7 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool { // Remove the simple key. simple_key.possible = false + delete(parser.simple_keys_by_tok, simple_key.token_number) // A simple key cannot follow another simple key. parser.simple_key_allowed = false diff --git a/vendor/gopkg.in/yaml.v2/yaml.go b/vendor/gopkg.in/yaml.v2/yaml.go index de85aa4cd..89650e293 100644 --- a/vendor/gopkg.in/yaml.v2/yaml.go +++ b/vendor/gopkg.in/yaml.v2/yaml.go @@ -89,7 +89,7 @@ func UnmarshalStrict(in []byte, out interface{}) (err error) { return unmarshal(in, out, true) } -// A Decorder reads and decodes YAML values from an input stream. +// A Decoder reads and decodes YAML values from an input stream. type Decoder struct { strict bool parser *parser diff --git a/vendor/gopkg.in/yaml.v2/yamlh.go b/vendor/gopkg.in/yaml.v2/yamlh.go index e25cee563..f6a9c8e34 100644 --- a/vendor/gopkg.in/yaml.v2/yamlh.go +++ b/vendor/gopkg.in/yaml.v2/yamlh.go @@ -579,6 +579,7 @@ type yaml_parser_t struct { simple_key_allowed bool // May a simple key occur at the current position? simple_keys []yaml_simple_key_t // The stack of simple keys. + simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number // Parser stuff diff --git a/vendor/modules.txt b/vendor/modules.txt index 48b432abd..ea595a4df 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/99designs/gqlgen v0.9.0 +# github.com/99designs/gqlgen v0.12.2 github.com/99designs/gqlgen github.com/99designs/gqlgen/api github.com/99designs/gqlgen/cmd @@ -7,17 +7,34 @@ github.com/99designs/gqlgen/codegen/config github.com/99designs/gqlgen/codegen/templates github.com/99designs/gqlgen/complexity github.com/99designs/gqlgen/graphql +github.com/99designs/gqlgen/graphql/errcode +github.com/99designs/gqlgen/graphql/executor +github.com/99designs/gqlgen/graphql/handler +github.com/99designs/gqlgen/graphql/handler/extension +github.com/99designs/gqlgen/graphql/handler/lru +github.com/99designs/gqlgen/graphql/handler/transport github.com/99designs/gqlgen/graphql/introspection +github.com/99designs/gqlgen/graphql/playground github.com/99designs/gqlgen/handler github.com/99designs/gqlgen/internal/code github.com/99designs/gqlgen/internal/imports +github.com/99designs/gqlgen/internal/rewrite github.com/99designs/gqlgen/plugin +github.com/99designs/gqlgen/plugin/federation github.com/99designs/gqlgen/plugin/modelgen github.com/99designs/gqlgen/plugin/resolvergen github.com/99designs/gqlgen/plugin/servergen # github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml -# github.com/agnivade/levenshtein v1.0.1 +# github.com/Yamashou/gqlgenc v0.0.0-20200902035953-4dbef3551953 +github.com/Yamashou/gqlgenc +github.com/Yamashou/gqlgenc/client +github.com/Yamashou/gqlgenc/clientgen +github.com/Yamashou/gqlgenc/config +github.com/Yamashou/gqlgenc/generator +github.com/Yamashou/gqlgenc/graphqljson +github.com/Yamashou/gqlgenc/introspection +# github.com/agnivade/levenshtein v1.1.0 github.com/agnivade/levenshtein # github.com/antchfx/htmlquery v1.2.3 github.com/antchfx/htmlquery @@ -75,6 +92,8 @@ github.com/chromedp/cdproto/webauthn github.com/chromedp/chromedp github.com/chromedp/chromedp/device github.com/chromedp/chromedp/kb +# github.com/cpuguy83/go-md2man/v2 v2.0.0 +github.com/cpuguy83/go-md2man/v2/md2man # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew # github.com/disintegration/imaging v1.6.0 @@ -192,6 +211,9 @@ github.com/mailru/easyjson/jwriter github.com/markbates/oncer # github.com/markbates/safe v1.0.1 github.com/markbates/safe +# github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 +github.com/matryer/moq +github.com/matryer/moq/pkg/moq # github.com/mattn/go-sqlite3 v1.13.0 github.com/mattn/go-sqlite3 # github.com/mitchellh/go-homedir v1.1.0 @@ -206,7 +228,7 @@ github.com/modern-go/reflect2 github.com/natefinch/pie # github.com/pelletier/go-toml v1.2.0 github.com/pelletier/go-toml -# github.com/pkg/errors v0.8.1 +# github.com/pkg/errors v0.9.1 github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib @@ -221,10 +243,14 @@ github.com/rs/zerolog github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log +# github.com/russross/blackfriday/v2 v2.0.1 +github.com/russross/blackfriday/v2 # github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f github.com/shurcooL/graphql github.com/shurcooL/graphql/ident github.com/shurcooL/graphql/internal/jsonutil +# github.com/shurcooL/sanitized_anchor_name v1.0.0 +github.com/shurcooL/sanitized_anchor_name # github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus # github.com/spf13/afero v1.2.0 @@ -253,26 +279,27 @@ github.com/tidwall/gjson github.com/tidwall/match # github.com/tidwall/pretty v1.0.0 github.com/tidwall/pretty -# github.com/urfave/cli v1.20.0 -github.com/urfave/cli +# github.com/urfave/cli/v2 v2.1.1 +github.com/urfave/cli/v2 # 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 -github.com/vektah/gqlparser/ast -github.com/vektah/gqlparser/gqlerror -github.com/vektah/gqlparser/lexer -github.com/vektah/gqlparser/parser -github.com/vektah/gqlparser/validator -github.com/vektah/gqlparser/validator/rules +# github.com/vektah/gqlparser/v2 v2.0.1 +github.com/vektah/gqlparser/v2 +github.com/vektah/gqlparser/v2/ast +github.com/vektah/gqlparser/v2/formatter +github.com/vektah/gqlparser/v2/gqlerror +github.com/vektah/gqlparser/v2/lexer +github.com/vektah/gqlparser/v2/parser +github.com/vektah/gqlparser/v2/validator +github.com/vektah/gqlparser/v2/validator/rules # github.com/vektra/mockery/v2 v2.2.1 github.com/vektra/mockery/v2 github.com/vektra/mockery/v2/cmd github.com/vektra/mockery/v2/pkg github.com/vektra/mockery/v2/pkg/config github.com/vektra/mockery/v2/pkg/logging -# golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 +# golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/ssh/terminal @@ -285,10 +312,10 @@ golang.org/x/image/tiff/lzw golang.org/x/image/vp8 golang.org/x/image/vp8l golang.org/x/image/webp -# golang.org/x/mod v0.2.0 +# golang.org/x/mod v0.3.0 golang.org/x/mod/module golang.org/x/mod/semver -# golang.org/x/net v0.0.0-20200602114024-627f9648deb9 +# golang.org/x/net v0.0.0-20200822124328-c89045814202 golang.org/x/net/context/ctxhttp golang.org/x/net/html golang.org/x/net/html/atom @@ -316,22 +343,27 @@ golang.org/x/text/language golang.org/x/text/runes golang.org/x/text/transform golang.org/x/text/unicode/norm -# golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e +# golang.org/x/tools v0.0.0-20200915031644-64986481280e golang.org/x/tools/go/ast/astutil golang.org/x/tools/go/gcexportdata golang.org/x/tools/go/internal/gcimporter golang.org/x/tools/go/internal/packagesdriver golang.org/x/tools/go/packages golang.org/x/tools/imports +golang.org/x/tools/internal/event +golang.org/x/tools/internal/event/core +golang.org/x/tools/internal/event/keys +golang.org/x/tools/internal/event/label golang.org/x/tools/internal/fastwalk golang.org/x/tools/internal/gocommand golang.org/x/tools/internal/gopathwalk golang.org/x/tools/internal/imports golang.org/x/tools/internal/packagesinternal -# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 +golang.org/x/tools/internal/typesinternal +# golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 golang.org/x/xerrors golang.org/x/xerrors/internal # gopkg.in/ini.v1 v1.51.0 gopkg.in/ini.v1 -# gopkg.in/yaml.v2 v2.2.4 +# gopkg.in/yaml.v2 v2.3.0 gopkg.in/yaml.v2